diff --git a/javascript/iroha_js/src/toriiClient.js b/javascript/iroha_js/src/toriiClient.js index 94d3ac804ec..0e33357d241 100644 --- a/javascript/iroha_js/src/toriiClient.js +++ b/javascript/iroha_js/src/toriiClient.js @@ -108,11 +108,23 @@ import { } from "./validationFeeConsensus.js"; import { assertCanonicalBls12381G1Compressed } from "./bls12381G1.js"; +// Capture frequently used statics once: this reduces the complete Torii bundle +// and keeps validation stable if application code later replaces a global. +const arrayIsArray = Array.isArray; +const numberIsFinite = Number.isFinite; +const numberIsInteger = Number.isInteger; +const numberIsSafeInteger = Number.isSafeInteger; +const objectEntries = Object.entries; +const objectFreeze = Object.freeze; +const objectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; +const objectHasOwn = Object.hasOwn; +const objectKeys = Object.keys; + const DEFAULT_PAGE_SIZE = 100; const APPLICATION_JSON = "application/json"; const APPLICATION_NORITO = "application/x-norito"; -const JSON_ACCEPT_HEADERS = Object.freeze({ Accept: APPLICATION_JSON }); -const JSON_REQUEST_HEADERS = Object.freeze({ +const JSON_ACCEPT_HEADERS = objectFreeze({ Accept: APPLICATION_JSON }); +const JSON_REQUEST_HEADERS = objectFreeze({ "Content-Type": APPLICATION_JSON, Accept: APPLICATION_JSON, }); @@ -155,66 +167,66 @@ const JSON_CLONE_MAX_DEPTH = 128; const JSON_CLONE_MAX_NODES = 100_000; const SUMERAGI_TYPED_JSON_MAX_NODES = 2_000_000; const typedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype); -const typedArrayBufferGetter = Object.getOwnPropertyDescriptor( +const typedArrayBufferGetter = objectGetOwnPropertyDescriptor( typedArrayPrototype, "buffer", ).get; -const typedArrayByteOffsetGetter = Object.getOwnPropertyDescriptor( +const typedArrayByteOffsetGetter = objectGetOwnPropertyDescriptor( typedArrayPrototype, "byteOffset", ).get; -const typedArrayByteLengthGetter = Object.getOwnPropertyDescriptor( +const typedArrayByteLengthGetter = objectGetOwnPropertyDescriptor( typedArrayPrototype, "byteLength", ).get; -const typedArrayTagGetter = Object.getOwnPropertyDescriptor( +const typedArrayTagGetter = objectGetOwnPropertyDescriptor( typedArrayPrototype, Symbol.toStringTag, ).get; -const typedArraySet = Object.getOwnPropertyDescriptor( +const typedArraySet = objectGetOwnPropertyDescriptor( typedArrayPrototype, "set", ).value; const Uint8ArrayIntrinsic = Uint8Array; -const dataViewBufferGetter = Object.getOwnPropertyDescriptor( +const dataViewBufferGetter = objectGetOwnPropertyDescriptor( DataView.prototype, "buffer", ).get; -const dataViewByteOffsetGetter = Object.getOwnPropertyDescriptor( +const dataViewByteOffsetGetter = objectGetOwnPropertyDescriptor( DataView.prototype, "byteOffset", ).get; -const dataViewByteLengthGetter = Object.getOwnPropertyDescriptor( +const dataViewByteLengthGetter = objectGetOwnPropertyDescriptor( DataView.prototype, "byteLength", ).get; -const arrayBufferByteLengthGetter = Object.getOwnPropertyDescriptor( +const arrayBufferByteLengthGetter = objectGetOwnPropertyDescriptor( ArrayBuffer.prototype, "byteLength", ).get; const sharedArrayBufferByteLengthGetter = typeof SharedArrayBuffer === "undefined" ? null - : Object.getOwnPropertyDescriptor( + : objectGetOwnPropertyDescriptor( SharedArrayBuffer.prototype, "byteLength", ).get; const responseBodyGetter = typeof Response === "undefined" ? null - : (Object.getOwnPropertyDescriptor(Response.prototype, "body")?.get ?? null); + : (objectGetOwnPropertyDescriptor(Response.prototype, "body")?.get ?? null); const responseHeadersGetter = typeof Response === "undefined" ? null - : (Object.getOwnPropertyDescriptor(Response.prototype, "headers")?.get ?? null); + : (objectGetOwnPropertyDescriptor(Response.prototype, "headers")?.get ?? null); const responseStatusGetter = typeof Response === "undefined" ? null - : (Object.getOwnPropertyDescriptor(Response.prototype, "status")?.get ?? null); + : (objectGetOwnPropertyDescriptor(Response.prototype, "status")?.get ?? null); const responseStatusTextGetter = typeof Response === "undefined" ? null - : (Object.getOwnPropertyDescriptor(Response.prototype, "statusText")?.get ?? + : (objectGetOwnPropertyDescriptor(Response.prototype, "statusText")?.get ?? null); const headersGet = typeof Headers === "undefined" ? null : Headers.prototype.get; @@ -229,7 +241,7 @@ const readableStreamCancel = const readableStreamLockedGetter = typeof ReadableStream === "undefined" ? null - : (Object.getOwnPropertyDescriptor( + : (objectGetOwnPropertyDescriptor( ReadableStream.prototype, "locked", )?.get ?? null); @@ -248,12 +260,12 @@ const readerReleaseLock = const abortSignalAbortedGetter = typeof AbortSignal === "undefined" ? null - : (Object.getOwnPropertyDescriptor(AbortSignal.prototype, "aborted")?.get ?? + : (objectGetOwnPropertyDescriptor(AbortSignal.prototype, "aborted")?.get ?? null); const abortSignalReasonGetter = typeof AbortSignal === "undefined" ? null - : (Object.getOwnPropertyDescriptor(AbortSignal.prototype, "reason")?.get ?? + : (objectGetOwnPropertyDescriptor(AbortSignal.prototype, "reason")?.get ?? null); const eventTargetAddEventListener = typeof EventTarget === "undefined" ? null : EventTarget.prototype.addEventListener; @@ -447,7 +459,7 @@ function ownDataMethod(target, name) { if (target === null || (typeof target !== "object" && typeof target !== "function")) { return null; } - const descriptor = Object.getOwnPropertyDescriptor(target, name); + const descriptor = objectGetOwnPropertyDescriptor(target, name); return descriptor && "value" in descriptor && typeof descriptor.value === "function" ? descriptor.value : null; @@ -482,7 +494,7 @@ function responseBodyWithoutUserGetter(response) { // Custom fetch responses may expose an own data property instead. } } - const descriptor = Object.getOwnPropertyDescriptor(response, "body"); + const descriptor = objectGetOwnPropertyDescriptor(response, "body"); return descriptor && "value" in descriptor ? descriptor.value : null; } @@ -494,7 +506,7 @@ function responseHeadersWithoutUserGetter(response) { // Custom fetch responses may expose an own data property instead. } } - const descriptor = Object.getOwnPropertyDescriptor(response, "headers"); + const descriptor = objectGetOwnPropertyDescriptor(response, "headers"); return descriptor && "value" in descriptor ? descriptor.value : null; } @@ -522,13 +534,13 @@ function responseStatusWithoutUserGetter(response) { } } if (status === undefined) { - const descriptor = Object.getOwnPropertyDescriptor(response, "status"); + const descriptor = objectGetOwnPropertyDescriptor(response, "status"); if (!descriptor || !("value" in descriptor)) { throw new TypeError("Torii response status must be an own data property"); } status = descriptor.value; } - if (!Number.isInteger(status) || status < 0 || status > 999) { + if (!numberIsInteger(status) || status < 0 || status > 999) { throw new TypeError("Torii response status must be an integer HTTP status"); } return status; @@ -542,7 +554,7 @@ function responseStatusTextWithoutUserGetter(response) { // Custom fetch responses may expose an own data property instead. } } - const descriptor = Object.getOwnPropertyDescriptor(response, "statusText"); + const descriptor = objectGetOwnPropertyDescriptor(response, "statusText"); return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : null; @@ -609,7 +621,7 @@ function signalIsAborted(signal) { if (hasAbortSignalBrand(signal)) { return abortSignalAbortedGetter.call(signal); } - const descriptor = Object.getOwnPropertyDescriptor(signal, "aborted"); + const descriptor = objectGetOwnPropertyDescriptor(signal, "aborted"); if (!descriptor || !("value" in descriptor) || typeof descriptor.value !== "boolean") { throw new TypeError("signal.aborted must be an own boolean data property"); } @@ -623,7 +635,7 @@ function signalAbortReason(signal) { ? undefined : abortSignalReasonGetter.call(signal); } - const descriptor = Object.getOwnPropertyDescriptor(signal, "reason"); + const descriptor = objectGetOwnPropertyDescriptor(signal, "reason"); return descriptor && "value" in descriptor ? descriptor.value : undefined; } @@ -1471,7 +1483,7 @@ export class ToriiHttpError extends Error { details, }) { const expectedLabel = - Array.isArray(expected) && expected.length > 0 + arrayIsArray(expected) && expected.length > 0 ? expected.slice().sort((a, b) => a - b).join(", ") : "none"; const statusLabel = statusText ? `${status} ${statusText}` : String(status); @@ -1493,7 +1505,7 @@ export class ToriiHttpError extends Error { this.name = "ToriiHttpError"; this.status = status; this.statusText = statusText ?? null; - this.expected = Array.isArray(expected) ? [...expected] : []; + this.expected = arrayIsArray(expected) ? [...expected] : []; this.code = code ?? null; this.rejectCode = rejectCode ?? null; this.errorMessage = errorMessage ?? null; @@ -1736,14 +1748,14 @@ function stripBase64Padding(value) { } function sortJsonForErrorMessage(value) { - if (Array.isArray(value)) { + if (arrayIsArray(value)) { return value.map((item) => sortJsonForErrorMessage(item)); } if (!value || typeof value !== "object") { return value; } const sorted = {}; - for (const key of Object.keys(value).sort()) { + for (const key of objectKeys(value).sort()) { sorted[key] = sortJsonForErrorMessage(value[key]); } return sorted; @@ -2351,7 +2363,7 @@ export class ToriiClient { page, perPage: normalized.perPage, }); - const items = Array.isArray(pageResult?.items) ? pageResult.items : []; + const items = arrayIsArray(pageResult?.items) ? pageResult.items : []; if (items.length === 0) { return; } @@ -2533,7 +2545,7 @@ export class ToriiClient { page, perPage: normalized.perPage, }); - const items = Array.isArray(pageResult?.items) ? pageResult.items : []; + const items = arrayIsArray(pageResult?.items) ? pageResult.items : []; if (items.length === 0) { return; } @@ -2612,7 +2624,7 @@ export class ToriiClient { delete params.asset_id; } const response = await this._request("GET", `/v1/accounts/${encodedId}/assets`, { - params: Object.keys(params).length > 0 ? params : undefined, + params: objectKeys(params).length > 0 ? params : undefined, headers: JSON_ACCEPT_HEADERS, signal, canonicalAuth, @@ -2881,7 +2893,7 @@ export class ToriiClient { params.result_ok = requireBooleanLike(rest.resultOk, "resultOk"); } const response = await this._request("GET", "/v1/contracts/events", { - params: Object.keys(params).length > 0 ? params : undefined, + params: objectKeys(params).length > 0 ? params : undefined, headers: JSON_ACCEPT_HEADERS, signal, canonicalAuth, @@ -3486,11 +3498,11 @@ export class ToriiClient { normalizedBinding, normalizedCheckpoint, ); - const promotedCheckpoint = Object.freeze({ + const promotedCheckpoint = objectFreeze({ height: projection.evaluated_block_height, contextId: projection.evaluated_context_id, }); - return Object.freeze({ + return objectFreeze({ proofNorito, projection, promotedCheckpoint, @@ -3546,7 +3558,7 @@ export class ToriiClient { } checkpoint = page.promotedCheckpoint; if (!page.projection.more_available) { - return Object.freeze({ + return objectFreeze({ ...page, binding: normalizedBinding, pagesVerified, @@ -3572,8 +3584,8 @@ export class ToriiClient { "lookupRetailRecipient request", ); if ( - Object.prototype.hasOwnProperty.call(requestRecord, "accountId") && - Object.prototype.hasOwnProperty.call(requestRecord, "account_id") && + objectHasOwn(requestRecord, "accountId") && + objectHasOwn(requestRecord, "account_id") && requestRecord.accountId !== requestRecord.account_id ) { throw new TypeError( @@ -3581,8 +3593,8 @@ export class ToriiClient { ); } if ( - Object.prototype.hasOwnProperty.call(requestRecord, "aliasFqn") && - Object.prototype.hasOwnProperty.call(requestRecord, "alias_fqn") && + objectHasOwn(requestRecord, "aliasFqn") && + objectHasOwn(requestRecord, "alias_fqn") && requestRecord.aliasFqn !== requestRecord.alias_fqn ) { throw new TypeError( @@ -4284,38 +4296,14 @@ export class ToriiClient { * @returns {Promise | null>} */ async getSorafsReputationLatest(options = {}) { - const { signal, rest } = ToriiClient._normalizeOptionsWithSignal( + return getSorafsReputationJson( + this, + "/v1/sorafs/reputation/latest", options, "getSorafsReputationLatest", - ); - assertSupportedOptionKeys( - rest, - SORAFS_REPUTATION_CACHE_OPTION_KEYS, - "getSorafsReputationLatest options", - ); - const auth = buildSorafsReputationRequestAuth( - rest, - this._config.defaultHeaders, - "getSorafsReputationLatest", - ); - const response = await this._request("GET", "/v1/sorafs/reputation/latest", { - headers: auth.headers, - canonicalAuth: auth.canonicalAuth, - disableRetries: true, - redirect: "error", - signal, - }); - await this._expectStatus(response, [200, 304, 404]); - if (response.status === 304 || response.status === 404) { - return null; - } - const payload = await this._readBoundedLosslessIntegerJson( - response, - SORAFS_REPUTATION_JSON_MAX_BYTES, "sorafs reputation latest endpoint", - { signal }, + parseSorafsReputationSnapshot, ); - return parseSorafsReputationSnapshot(payload, "sorafs reputation latest endpoint"); } /** @@ -4330,44 +4318,13 @@ export class ToriiClient { providerId, "getSorafsReputationProvider.providerId", ); - const { signal, rest } = ToriiClient._normalizeOptionsWithSignal( + return getSorafsReputationJson( + this, + `/v1/sorafs/reputation/providers/${normalizedProvider}`, options, "getSorafsReputationProvider", - ); - assertSupportedOptionKeys( - rest, - SORAFS_REPUTATION_CACHE_OPTION_KEYS, - "getSorafsReputationProvider options", - ); - const auth = buildSorafsReputationRequestAuth( - rest, - this._config.defaultHeaders, - "getSorafsReputationProvider", - ); - const response = await this._request( - "GET", - `/v1/sorafs/reputation/providers/${normalizedProvider}`, - { - headers: auth.headers, - canonicalAuth: auth.canonicalAuth, - disableRetries: true, - redirect: "error", - signal, - }, - ); - await this._expectStatus(response, [200, 304, 404]); - if (response.status === 304 || response.status === 404) { - return null; - } - const payload = await this._readBoundedLosslessIntegerJson( - response, - SORAFS_REPUTATION_JSON_MAX_BYTES, - "sorafs reputation provider endpoint", - { signal }, - ); - return parseSorafsReputationProviderResponse( - payload, "sorafs reputation provider endpoint", + parseSorafsReputationProviderResponse, normalizedProvider, ); } @@ -4384,44 +4341,13 @@ export class ToriiClient { snapshotIdHex, "getSorafsReputationSnapshot.snapshotIdHex", ); - const { signal, rest } = ToriiClient._normalizeOptionsWithSignal( + return getSorafsReputationJson( + this, + `/v1/sorafs/reputation/snapshots/${normalizedSnapshotId}`, options, "getSorafsReputationSnapshot", - ); - assertSupportedOptionKeys( - rest, - SORAFS_REPUTATION_CACHE_OPTION_KEYS, - "getSorafsReputationSnapshot options", - ); - const auth = buildSorafsReputationRequestAuth( - rest, - this._config.defaultHeaders, - "getSorafsReputationSnapshot", - ); - const response = await this._request( - "GET", - `/v1/sorafs/reputation/snapshots/${normalizedSnapshotId}`, - { - headers: auth.headers, - canonicalAuth: auth.canonicalAuth, - disableRetries: true, - redirect: "error", - signal, - }, - ); - await this._expectStatus(response, [200, 304, 404]); - if (response.status === 304 || response.status === 404) { - return null; - } - const payload = await this._readBoundedLosslessIntegerJson( - response, - SORAFS_REPUTATION_JSON_MAX_BYTES, - "sorafs reputation snapshot endpoint", - { signal }, - ); - return parseSorafsReputationSnapshot( - payload, "sorafs reputation snapshot endpoint", + parseSorafsReputationSnapshot, { expectedSnapshotId: normalizedSnapshotId }, ); } @@ -4433,40 +4359,13 @@ export class ToriiClient { * @returns {Promise | null>} */ async getSorafsReputationWeights(options = {}) { - const { signal, rest } = ToriiClient._normalizeOptionsWithSignal( + return getSorafsReputationJson( + this, + "/v1/sorafs/reputation/weights", options, "getSorafsReputationWeights", - ); - assertSupportedOptionKeys( - rest, - SORAFS_REPUTATION_CACHE_OPTION_KEYS, - "getSorafsReputationWeights options", - ); - const auth = buildSorafsReputationRequestAuth( - rest, - this._config.defaultHeaders, - "getSorafsReputationWeights", - ); - const response = await this._request("GET", "/v1/sorafs/reputation/weights", { - headers: auth.headers, - canonicalAuth: auth.canonicalAuth, - disableRetries: true, - redirect: "error", - signal, - }); - await this._expectStatus(response, [200, 304, 404]); - if (response.status === 304 || response.status === 404) { - return null; - } - const payload = await this._readBoundedLosslessIntegerJson( - response, - SORAFS_REPUTATION_JSON_MAX_BYTES, - "sorafs reputation weights endpoint", - { signal }, - ); - return parseSorafsReputationWeightsResponse( - payload, "sorafs reputation weights endpoint", + parseSorafsReputationWeightsResponse, ); } @@ -5669,7 +5568,7 @@ export class ToriiClient { { headers: JSON_ACCEPT_HEADERS, signal, - params: Object.keys(params).length === 0 ? undefined : params, + params: objectKeys(params).length === 0 ? undefined : params, }, ); await this._expectStatus(response, [200]); @@ -5829,7 +5728,7 @@ export class ToriiClient { if (value === null || value === undefined) { return { route }; } - if (typeof value === "object" && !Array.isArray(value)) { + if (typeof value === "object" && !arrayIsArray(value)) { return { ...value, route }; } return { value, route }; @@ -5873,7 +5772,7 @@ export class ToriiClient { */ async submitTransactionBatch(payloads, options = {}) { const { signal } = normalizeSignalOnlyOption(options, "submitTransactionBatch"); - if (!Array.isArray(payloads)) { + if (!arrayIsArray(payloads)) { throw new TypeError("submitTransactionBatch payloads must be an array"); } if (payloads.length === 0) { @@ -6111,7 +6010,7 @@ export class ToriiClient { if ( typeof payload === "object" && payload !== null && - Object.keys(payload).length === 0 + objectKeys(payload).length === 0 ) { return null; } @@ -6578,7 +6477,7 @@ export class ToriiClient { async _submitSoracloudAppInfraMutation(path, request, options, context) { const { signal } = normalizeSignalOnlyOption(options, context); - if (request == null || typeof request !== "object" || Array.isArray(request)) { + if (request == null || typeof request !== "object" || arrayIsArray(request)) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, "request must be an object", @@ -6839,7 +6738,7 @@ export class ToriiClient { const record = requirePlainObjectOption(options, "getSccpRecentMessages.options", { message: "must be a plain object", }); - const unknown = Object.keys(record).find( + const unknown = objectKeys(record).find( (key) => key !== "from" && key !== "after_index" && key !== "limit" && key !== "signal", ); @@ -6848,7 +6747,7 @@ export class ToriiClient { } const params = {}; if (record.from !== undefined) { - if (!Number.isSafeInteger(record.from) || record.from < 1) { + if (!numberIsSafeInteger(record.from) || record.from < 1) { throw new TypeError( "getSccpRecentMessages.options.from must be a positive safe integer", ); @@ -6860,7 +6759,7 @@ export class ToriiClient { throw new TypeError("getSccpRecentMessages.options.after_index requires from"); } if ( - !Number.isSafeInteger(record.after_index) || + !numberIsSafeInteger(record.after_index) || record.after_index < 0 || record.after_index > 511 ) { @@ -6871,7 +6770,7 @@ export class ToriiClient { params.after_index = String(record.after_index); } if (record.limit !== undefined) { - if (!Number.isSafeInteger(record.limit) || record.limit < 1 || record.limit > 50) { + if (!numberIsSafeInteger(record.limit) || record.limit < 1 || record.limit > 50) { throw new TypeError("getSccpRecentMessages.options.limit must be an integer in 1..50"); } params.limit = String(record.limit); @@ -8251,7 +8150,7 @@ export class ToriiClient { } const response = await this._request("GET", "/v1/sumeragi/evidence", { headers: JSON_ACCEPT_HEADERS, - params: Object.keys(params).length > 0 ? params : undefined, + params: objectKeys(params).length > 0 ? params : undefined, signal, }); await this._expectStatus(response, [200]); @@ -8272,7 +8171,7 @@ export class ToriiClient { "sumeragi evidence count response", ); const count = Number(payload.count ?? 0); - if (!Number.isFinite(count) || count < 0) { + if (!numberIsFinite(count) || count < 0) { throw new TypeError("sumeragi evidence count response.count must be a non-negative number"); } return { count }; @@ -8394,7 +8293,7 @@ export class ToriiClient { params.per_page = normalizedOptions.perPage; } const response = await this._request("GET", "/v1/explorer/blocks", { - params: Object.keys(params).length > 0 ? params : undefined, + params: objectKeys(params).length > 0 ? params : undefined, headers: JSON_ACCEPT_HEADERS, signal: normalizedOptions.signal, }); @@ -8427,7 +8326,7 @@ export class ToriiClient { params.filter = filterPayload; } return this._streamSse("/v1/events/sse", { - params: Object.keys(params).length > 0 ? params : undefined, + params: objectKeys(params).length > 0 ? params : undefined, signal, }); } @@ -8505,7 +8404,7 @@ export class ToriiClient { } } return this._streamSse("/v1/contracts/events/sse", { - params: Object.keys(params).length > 0 ? params : undefined, + params: objectKeys(params).length > 0 ? params : undefined, signal, }); } @@ -8849,7 +8748,7 @@ export class ToriiClient { } const response = await this._request("GET", "/v1/connect/app/apps", { headers: JSON_ACCEPT_HEADERS, - params: Object.keys(params).length === 0 ? undefined : params, + params: objectKeys(params).length === 0 ? undefined : params, signal, }); await this._expectStatus(response, [200]); @@ -10236,7 +10135,7 @@ export class ToriiClient { "signal", "retryProfile", ]); - const unsupportedKeys = Object.keys(resolvedOptions).filter((key) => !allowedKeys.has(key)); + const unsupportedKeys = objectKeys(resolvedOptions).filter((key) => !allowedKeys.has(key)); if (unsupportedKeys.length > 0) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, @@ -10579,10 +10478,10 @@ export class ToriiClient { originMatches, }); } - if (options.params && Object.keys(options.params).length > 0) { + if (options.params && objectKeys(options.params).length > 0) { const search = new URLSearchParams(); - for (const [key, value] of Object.entries(options.params)) { - if (Array.isArray(value)) { + for (const [key, value] of objectEntries(options.params)) { + if (arrayIsArray(value)) { for (const item of value) { search.append(key, String(item)); } @@ -10615,7 +10514,7 @@ export class ToriiClient { body: bodyForSigning, privateKey: canonicalAuth.privateKey, }); - for (const [key, value] of Object.entries(canonicalHeaders)) { + for (const [key, value] of objectEntries(canonicalHeaders)) { setHeader(initHeaders, key, value); } } @@ -10943,7 +10842,7 @@ export class ToriiClient { return; } if (typeof source === "object") { - for (const [key, value] of Object.entries(source)) { + for (const [key, value] of objectEntries(source)) { if (value === null) { deleteHeader(headers, key); continue; @@ -11205,7 +11104,7 @@ export class ToriiClient { if (typeof value === "string") { return this._trimErrorBodyText(value); } - if (Array.isArray(value)) { + if (arrayIsArray(value)) { for (const item of value) { const nested = this._extractErrorMessageValue(item); if (nested) { @@ -11228,7 +11127,7 @@ export class ToriiClient { "description", ]; const caseInsensitiveValues = new Map(); - for (const [key, entryValue] of Object.entries(value)) { + for (const [key, entryValue] of objectEntries(value)) { const normalizedKey = String(key).toLowerCase(); if (!caseInsensitiveValues.has(normalizedKey)) { caseInsensitiveValues.set(normalizedKey, entryValue); @@ -11312,7 +11211,7 @@ export class ToriiClient { } const record = ToriiClient._requirePlainObject(filters, "prover filters"); const params = {}; - for (const [rawKey, rawValue] of Object.entries(record)) { + for (const [rawKey, rawValue] of objectEntries(record)) { if (rawValue === undefined || rawValue === null) { continue; } @@ -11496,7 +11395,7 @@ export class ToriiClient { break; case "retry": { const parsed = Number(value); - if (Number.isFinite(parsed)) { + if (numberIsFinite(parsed)) { retry = parsed; } break; @@ -11535,7 +11434,7 @@ export class ToriiClient { _acceptHeader() { const headers = this._config?.defaultHeaders ?? {}; - for (const [key, value] of Object.entries(headers)) { + for (const [key, value] of objectEntries(headers)) { if (value !== undefined && value !== null && key.toLowerCase() === "accept") { return String(value); } @@ -11685,7 +11584,7 @@ export class ToriiClient { ); } const declaredBytes = Number(contentLength); - if (!Number.isSafeInteger(declaredBytes)) { + if (!numberIsSafeInteger(declaredBytes)) { rejectResponse( new RangeError( `${context} Content-Length exceeds the safe integer range`, @@ -11730,7 +11629,7 @@ export class ToriiClient { const configuredTimeoutMs = Number(this._config?.timeoutMs); const readTimeoutMs = - Number.isFinite(configuredTimeoutMs) && configuredTimeoutMs > 0 + numberIsFinite(configuredTimeoutMs) && configuredTimeoutMs > 0 ? Math.min(configuredTimeoutMs, BOUNDED_JSON_MAX_READ_TIMEOUT_MS) : BOUNDED_JSON_MAX_READ_TIMEOUT_MS; let rejectDeadline; @@ -11995,11 +11894,11 @@ export class ToriiClient { const page = await fetchPage.call(self, pageOptions); if (page && page.total !== undefined && page.total !== null) { const parsedTotal = Number(page.total); - if (Number.isFinite(parsedTotal)) { + if (numberIsFinite(parsedTotal)) { knownTotal = Math.max(0, parsedTotal); } } - const items = Array.isArray(page?.items) ? page.items : []; + const items = arrayIsArray(page?.items) ? page.items : []; if (items.length === 0) { return; } @@ -12116,14 +12015,14 @@ export class ToriiClient { })(); function extractOffsetItems(page) { - if (Array.isArray(page)) { + if (arrayIsArray(page)) { return page; } if (!page || typeof page !== "object") { return []; } for (const key of normalizedItemKeys) { - if (Array.isArray(page[key])) { + if (arrayIsArray(page[key])) { return page[key]; } } @@ -12145,7 +12044,7 @@ export class ToriiClient { } return [trimmed]; } - if (!Array.isArray(rawKeys)) { + if (!arrayIsArray(rawKeys)) { throw new Error(`${contextLabel} item keys must be a string or array of strings`); } const keys = []; @@ -12224,7 +12123,7 @@ export class ToriiClient { signal, }; const page = await fetchPage.call(self, pageOptions); - const items = Array.isArray(page?.items) ? page.items : []; + const items = arrayIsArray(page?.items) ? page.items : []; if (items.length === 0) { return; } @@ -12303,7 +12202,7 @@ export class ToriiClient { signal, }; const page = await fetchPage.call(self, pageOptions); - const items = Array.isArray(page?.instances) ? page.instances : []; + const items = arrayIsArray(page?.instances) ? page.instances : []; if (items.length === 0) { return; } @@ -12325,7 +12224,7 @@ export class ToriiClient { } static _validateIterablePayload(payload) { - if (!payload || typeof payload !== "object" || !Array.isArray(payload.items)) { + if (!payload || typeof payload !== "object" || !arrayIsArray(payload.items)) { throw new Error("iterable endpoint returned unexpected payload"); } const hasTotal = payload.total !== undefined && payload.total !== null; @@ -12351,7 +12250,7 @@ export class ToriiClient { : null; if ( totalValue !== null && - (!Number.isFinite(totalValue) || totalValue < 0 || !Number.isInteger(totalValue)) + (!numberIsFinite(totalValue) || totalValue < 0 || !numberIsInteger(totalValue)) ) { throw new Error("iterable endpoint returned invalid total count"); } @@ -12488,7 +12387,7 @@ export class ToriiClient { buffer = Buffer.from(value.buffer, value.byteOffset, value.byteLength); } else if (value instanceof ArrayBuffer) { buffer = Buffer.from(value); - } else if (Array.isArray(value)) { + } else if (arrayIsArray(value)) { buffer = normalizeByteArray(value, path); } else { throw createValidationError( @@ -13070,7 +12969,7 @@ export class ToriiClient { ) { params.include_expired = "true"; } - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } static _normalizeOptionalString(value, context) { @@ -13181,7 +13080,7 @@ export class ToriiClient { }); return trimmed; } - if (Array.isArray(sort)) { + if (arrayIsArray(sort)) { if (sort.length === 0) { return undefined; } @@ -13256,7 +13155,7 @@ export class ToriiClient { envelope.query = name; } if (options.select !== undefined && options.select !== null) { - if (!Array.isArray(options.select)) { + if (!arrayIsArray(options.select)) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, "select must be an array of projection field paths or objects", @@ -13347,7 +13246,7 @@ export class ToriiClient { static _validateFilterExpression(node, context, rules) { const expr = ToriiClient._requirePlainObject(node, context); - const operators = Object.keys(expr); + const operators = objectKeys(expr); if (operators.length !== 1) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, @@ -13375,7 +13274,7 @@ export class ToriiClient { return; } case "Not": { - if (Array.isArray(operand)) { + if (arrayIsArray(operand)) { if (operand.length !== 1) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, @@ -13533,7 +13432,7 @@ export class ToriiClient { } static _extractFilterFieldName(operand, operator, context) { - if (Array.isArray(operand)) { + if (arrayIsArray(operand)) { if (operand.length === 0) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, @@ -13571,7 +13470,7 @@ export class ToriiClient { } static _assertFilterNumberValue(value, context) { - if (typeof value !== "number" || !Number.isFinite(value)) { + if (typeof value !== "number" || !numberIsFinite(value)) { throw createValidationError( ValidationErrorCode.INVALID_NUMERIC, `${context} must be numeric`, @@ -13582,7 +13481,7 @@ export class ToriiClient { } static _requireArray(value, context, { expectedLength = null, allowEmpty = true } = {}) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, `${context} must be an array`, @@ -13612,7 +13511,7 @@ export class ToriiClient { if (sort === undefined || sort === null) { return []; } - if (Array.isArray(sort)) { + if (arrayIsArray(sort)) { return sort.map((entry, index) => { if (!entry || typeof entry !== "object" || typeof entry.key !== "string") { throw createValidationError( @@ -13723,7 +13622,7 @@ export class ToriiClient { if (options.offset !== undefined && options.offset !== null) { params.offset = ToriiClient._normalizeOffset(options.offset); } - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } static _normalizeOffset(value) { @@ -13739,7 +13638,7 @@ export class ToriiClient { const max = options.max; let numeric; if (typeof value === "number") { - if (!Number.isFinite(value) || !Number.isInteger(value)) { + if (!numberIsFinite(value) || !numberIsInteger(value)) { const qualifier = allowZero ? "non-negative integer" : "positive integer"; throw createValidationError( ValidationErrorCode.INVALID_NUMERIC, @@ -13755,7 +13654,7 @@ export class ToriiClient { name, ); } - if (!Number.isSafeInteger(value)) { + if (!numberIsSafeInteger(value)) { throw createValidationError( ValidationErrorCode.VALUE_OUT_OF_RANGE, `${name} must be at most ${MAX_SAFE_INTEGER}`, @@ -13841,7 +13740,7 @@ function normalizeUint64DecimalString(value, name, options = {}) { const allowZero = options.allowZero !== false; let integer; if (typeof value === "number") { - if (!Number.isFinite(value) || !Number.isInteger(value) || !Number.isSafeInteger(value)) { + if (!numberIsFinite(value) || !numberIsInteger(value) || !numberIsSafeInteger(value)) { const qualifier = allowZero ? "non-negative integer" : "positive integer"; throw createValidationError( ValidationErrorCode.INVALID_NUMERIC, @@ -13991,7 +13890,7 @@ function normalizeIsoStatusHistory(value, context) { if (value === undefined || value === null) { return []; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((entry, index) => { @@ -14077,7 +13976,7 @@ function normalizeIsoSubmissionOptions(options, context, extraAllowedKeys = []) ); } const allowedKeys = new Set(["signal", "contentType", "retryProfile", "profile", ...extraAllowedKeys]); - const extras = Object.keys(options).filter((key) => !allowedKeys.has(key)); + const extras = objectKeys(options).filter((key) => !allowedKeys.has(key)); if (extras.length > 0) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, @@ -14139,7 +14038,7 @@ function normalizeIsoStatusOptions(options, context) { optionPath, ); } - const extras = Object.keys(options).filter( + const extras = objectKeys(options).filter( (key) => key !== "signal" && key !== "retryProfile", ); if (extras.length > 0) { @@ -14209,7 +14108,7 @@ function normalizeIsoStringArray(value, name) { if (value === undefined || value === null) { return []; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${name} must be an array of strings`); } return value.map((entry, index) => { @@ -14291,7 +14190,7 @@ function normalizeTimeStatusResponse(payload) { { allowZero: true }, ); const rawSamples = record.samples === undefined ? [] : record.samples; - if (!Array.isArray(rawSamples)) { + if (!arrayIsArray(rawSamples)) { throw new TypeError("time status response.samples must be an array"); } const samples = rawSamples.map((entry, index) => { @@ -14316,7 +14215,7 @@ function normalizeTimeStatusResponse(payload) { const rttRecord = ensureRecord(record.rtt ?? {}, "time status response.rtt"); const rawBuckets = rttRecord.buckets === undefined ? [] : rttRecord.buckets; - if (!Array.isArray(rawBuckets)) { + if (!arrayIsArray(rawBuckets)) { throw new TypeError("time status response.rtt.buckets must be an array"); } const buckets = rawBuckets.map((entry, index) => { @@ -14395,7 +14294,7 @@ function parseStatusPayload(payload) { payload.lane_governance_sealed_aliases, "status.lane_governance_sealed_aliases", ), - raw: Object.freeze({ ...payload }), + raw: objectFreeze({ ...payload }), }; } @@ -14506,7 +14405,7 @@ function parseGovernanceActivations(payload) { if (payload == null) { return []; } - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError( "governance.recent_manifest_activations must be an array", ); @@ -14567,14 +14466,14 @@ function normalizePipelineStatusPayload(payload) { : record.status; const status = normalizePipelineStatusStatus(statusValue); const normalizedContent = - contentRecord === null ? null : Object.freeze({ ...contentRecord }); - return Object.freeze({ + contentRecord === null ? null : objectFreeze({ ...contentRecord }); + return objectFreeze({ kind, hashHex, authority, status, content: normalizedContent, - raw: Object.freeze({ ...record }), + raw: objectFreeze({ ...record }), }); } @@ -14583,17 +14482,17 @@ function normalizePipelineStatusStatus(value) { return null; } if (typeof value === "string") { - return Object.freeze({ kind: value, content: null, raw: value }); + return objectFreeze({ kind: value, content: null, raw: value }); } if (isPlainObject(value)) { const record = ensureRecord(value, "pipeline status payload.status"); - return Object.freeze({ + return objectFreeze({ kind: record.kind == null ? null : String(record.kind), content: record.content ?? null, - raw: Object.freeze({ ...record }), + raw: objectFreeze({ ...record }), }); } - return Object.freeze({ + return objectFreeze({ kind: String(value), content: null, raw: value, @@ -14604,7 +14503,7 @@ function parseLaneCommitments(payload) { if (payload == null) { return []; } - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError("status.lane_commitments must be an array"); } return payload.map((entry, index) => { @@ -14640,7 +14539,7 @@ function parseDataspaceCommitments(payload) { if (payload == null) { return []; } - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError("status.dataspace_commitments must be an array"); } return payload.map((entry, index) => { @@ -14681,7 +14580,7 @@ function parseDataspaceCatalog(payload) { if (payload == null) { return []; } - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError("status.dataspace_catalog must be an array"); } return payload.map((entry, index) => { @@ -14739,7 +14638,7 @@ function parseLanePrivacyCommitments(payload, context) { if (payload == null) { return []; } - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError(`${context} must be an array`); } return payload.map((entry, index) => @@ -14803,7 +14702,7 @@ function parseSumeragiNexusFeeSchedule(value, context) { ], context, ); - return Object.freeze({ + return objectFreeze({ tx_bytes_len: parseSumeragiUnsigned(record.tx_bytes_len, `${context}.tx_bytes_len`), instruction_count: parseSumeragiUnsigned( record.instruction_count, @@ -14843,7 +14742,7 @@ function parseSumeragiNexusFeeReceipt(value, context) { if (version !== 1) { throw new RangeError(`${context}.version must equal 1`); } - return Object.freeze({ + return objectFreeze({ version, source_id: parseSumeragiByte32(record.source_id, `${context}.source_id`), dataspace_id: parseSumeragiUnsigned(record.dataspace_id, `${context}.dataspace_id`), @@ -14963,7 +14862,7 @@ function parseSumeragiNativeAmxBody(value, context) { ) { throw new RangeError(`${context} contains inconsistent round or quorum fields`); } - return Object.freeze({ + return objectFreeze({ round, epoch: parseSumeragiUnsigned(record.epoch, `${context}.epoch`), chain_id_hash: parseSumeragiHash(record.chain_id_hash, `${context}.chain_id_hash`), @@ -15110,7 +15009,7 @@ function parseSumeragiBlsNormalPeerId(value, context) { cause: error, }); } - return Object.freeze({ + return objectFreeze({ literal: matched[1], orderingKey: Buffer.concat([Buffer.from([2]), compressed]), }); @@ -15131,7 +15030,7 @@ function parseSumeragiBlsNormalValidatorSet(value, context) { `${context} must be strictly ordered by canonical validator id`, ); } - return Object.freeze(parsed.map((validator) => validator.literal)); + return objectFreeze(parsed.map((validator) => validator.literal)); } function encodeSumeragiNativeU32(value) { @@ -15353,7 +15252,7 @@ function computeSumeragiNativeParticipantSettlementHash(settlement) { ); } -export const __sumeragiNativeAmxTestHelpers = Object.freeze({ +export const __sumeragiNativeAmxTestHelpers = objectFreeze({ computeDescriptorHash: computeSumeragiNativeDescriptorHash, computeParticipantSettlementHash: computeSumeragiNativeParticipantSettlementHash, @@ -15408,7 +15307,7 @@ function parseSumeragiNativeAmxQc(value, context) { ) { throw new TypeError(`${context} committee fields differ from its signed body`); } - const pops = Object.freeze( + const pops = objectFreeze( assertSumeragiArrayBound( record.validator_set_pops, validators.length, @@ -15442,7 +15341,7 @@ function parseSumeragiNativeAmxQc(value, context) { if (signature.every((byte) => byte === 0)) { throw new TypeError(`${context}.bls_aggregate_signature must not be all zeroes`); } - return Object.freeze({ + return objectFreeze({ body, validator_set_hash_version: version, validator_set_hash: validatorSetHash, @@ -15487,11 +15386,11 @@ function parseSumeragiNativeAmxParticipantProposal(value, context) { "previous_lane_block_descriptor_hash", ]); for (const field of requiredFields) { - if (!Object.prototype.hasOwnProperty.call(descriptor, field)) { + if (!objectHasOwn(descriptor, field)) { throw new TypeError(`${descriptorContext} is missing required field ${field}`); } } - for (const field of Object.keys(descriptor)) { + for (const field of objectKeys(descriptor)) { if (!allowedFields.has(field)) { throw new TypeError(`${descriptorContext} contains unknown field ${field}`); } @@ -15503,11 +15402,11 @@ function parseSumeragiNativeAmxParticipantProposal(value, context) { ); let previousDescriptorHash = null; if (previousHeight === 0) { - if (Object.prototype.hasOwnProperty.call(descriptor, "previous_lane_block_descriptor_hash")) { + if (objectHasOwn(descriptor, "previous_lane_block_descriptor_hash")) { throw new TypeError(`${descriptorContext} must omit the genesis predecessor hash`); } } else { - if (!Object.prototype.hasOwnProperty.call(descriptor, "previous_lane_block_descriptor_hash")) { + if (!objectHasOwn(descriptor, "previous_lane_block_descriptor_hash")) { throw new TypeError(`${descriptorContext} must carry a predecessor descriptor hash`); } previousDescriptorHash = parseSumeragiNonzeroHash( @@ -15524,7 +15423,7 @@ function parseSumeragiNativeAmxParticipantProposal(value, context) { throw new RangeError(`${descriptorContext} lane-block heights must be contiguous`); } - const acceptedCandidateIndices = Object.freeze( + const acceptedCandidateIndices = objectFreeze( assertSumeragiArrayBound( descriptor.accepted_candidate_indices, 4096, @@ -15537,7 +15436,7 @@ function parseSumeragiNativeAmxParticipantProposal(value, context) { ), ), ); - const acceptedTransactionHashes = Object.freeze( + const acceptedTransactionHashes = objectFreeze( assertSumeragiArrayBound( descriptor.accepted_transaction_hashes, 4096, @@ -15673,8 +15572,8 @@ function parseSumeragiNativeAmxParticipantProposal(value, context) { `${context}.proposal_hash does not match its canonical preimage`, ); } - return Object.freeze({ - descriptor: Object.freeze(normalizedDescriptor), + return objectFreeze({ + descriptor: objectFreeze(normalizedDescriptor), proposal_hash: proposalHash, }); } @@ -15706,13 +15605,13 @@ function parseSumeragiNativeAmxLeg(value, context) { `${context}.participant_settlement`, ); if ( - !Array.isArray(settlementWire.native_amx_receipts) || + !arrayIsArray(settlementWire.native_amx_receipts) || settlementWire.native_amx_receipts.length !== 0 ) { throw new TypeError(`${context}.participant_settlement must be terminal`); } if ( - !Array.isArray(settlementWire.nexus_fee_receipts) || + !arrayIsArray(settlementWire.nexus_fee_receipts) || settlementWire.nexus_fee_receipts.length !== 0 ) { throw new TypeError(`${context}.participant_settlement cannot contain fee receipts`); @@ -15834,7 +15733,7 @@ function parseSumeragiNativeAmxLeg(value, context) { ) { throw new TypeError(`${context} participant settlement differs from its signed body`); } - return Object.freeze({ + return objectFreeze({ lane_id: laneId, dataspace_id: dataspaceId, participant_proposal: participantProposal, @@ -15898,7 +15797,7 @@ function parseSumeragiNativeAmxReceipt(value, context) { record.coordinator_proposal_hash, `${context}.coordinator_proposal_hash`, ); - const legs = Object.freeze( + const legs = objectFreeze( assertSumeragiArrayBound(record.legs, 255, `${context}.legs`, 1).map((leg, index) => parseSumeragiNativeAmxLeg(leg, `${context}.legs[${index}]`), ), @@ -15938,7 +15837,7 @@ function parseSumeragiNativeAmxReceipt(value, context) { throw new TypeError(`${context}.legs contain mismatched signed identities`); } } - return Object.freeze({ + return objectFreeze({ version, source_id: sourceId, chain_id_hash: chainIdHash, @@ -16027,7 +15926,7 @@ function parseLaneSettlementCommitments(payload) { }; } const receiptsRecord = record.receipts; - if (!Array.isArray(receiptsRecord)) { + if (!arrayIsArray(receiptsRecord)) { throw new TypeError( `status.lane_settlement_commitments[${index}].receipts must be an array`, ); @@ -16072,7 +15971,7 @@ function parseLaneSettlementCommitments(payload) { ), }; }); - const nexusFeeReceipts = Object.freeze( + const nexusFeeReceipts = objectFreeze( assertSumeragiArrayBound( record.nexus_fee_receipts, Number.MAX_SAFE_INTEGER, @@ -16084,7 +15983,7 @@ function parseLaneSettlementCommitments(payload) { ), ), ); - const nativeAmxReceipts = Object.freeze( + const nativeAmxReceipts = objectFreeze( assertSumeragiArrayBound( record.native_amx_receipts, MAX_NATIVE_AMX_PARTICIPANT_SETTLEMENT_RECEIPTS, @@ -16274,7 +16173,7 @@ function parseLaneGovernance(payload) { if (payload == null) { return []; } - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError("status.lane_governance must be an array"); } return payload.map((entry, index) => { @@ -16383,7 +16282,7 @@ function parseSumeragiStatusPayload(payload) { "last_commit_qc", "liveness", ]); - const unknownField = Object.keys(record).find((field) => !allowedFields.has(field)); + const unknownField = objectKeys(record).find((field) => !allowedFields.has(field)); if (unknownField !== undefined) { throw new TypeError(`sumeragi status payload contains unknown field ${unknownField}`); } @@ -16464,7 +16363,7 @@ function parseSumeragiStatusPayload(payload) { } } - return Object.freeze({ + return objectFreeze({ protocol_version: protocolVersion, node_fingerprint: parseSumeragiHash( record.node_fingerprint, @@ -16538,7 +16437,7 @@ function parseSumeragiStatusPayload(payload) { }); } -const SUMERAGI_PIPELINE_EXECUTION_FIELDS = Object.freeze([ +const SUMERAGI_PIPELINE_EXECUTION_FIELDS = objectFreeze([ "tx_vertices_total", "tx_edges_total", "overlay_count_total", @@ -16586,12 +16485,12 @@ function parseSumeragiDiagnosticsPayload(payload) { "autonomous_lane_executions", ]; const allowedFields = new Set([...requiredFields, "npos"]); - const unknown = Object.keys(record).find((field) => !allowedFields.has(field)); + const unknown = objectKeys(record).find((field) => !allowedFields.has(field)); if (unknown !== undefined) { throw new TypeError(`${context} contains unknown field ${unknown}`); } const missing = requiredFields.find( - (field) => !Object.prototype.hasOwnProperty.call(record, field), + (field) => !objectHasOwn(record, field), ); if (missing !== undefined) { throw new TypeError(`${context} is missing required field ${missing}`); @@ -16602,7 +16501,7 @@ function parseSumeragiDiagnosticsPayload(payload) { SUMERAGI_PIPELINE_EXECUTION_FIELDS, `${context}.pipeline_execution`, ); - const pipelineExecution = Object.freeze(Object.fromEntries( + const pipelineExecution = objectFreeze(Object.fromEntries( SUMERAGI_PIPELINE_EXECUTION_FIELDS.map((field) => [ field, parseSumeragiUnsigned( @@ -16654,7 +16553,7 @@ function parseSumeragiDiagnosticsPayload(payload) { throw new TypeError(`${context}.tx_queue_saturated disagrees with its causes`); } - const sealedAliases = Object.freeze( + const sealedAliases = objectFreeze( assertSumeragiArrayBound( record.lane_governance_sealed_aliases, 128, @@ -16677,7 +16576,7 @@ function parseSumeragiDiagnosticsPayload(payload) { ); } - return Object.freeze({ + return objectFreeze({ pipeline_execution: pipelineExecution, tx_queue_depth: txQueueDepth, tx_queue_capacity: txQueueCapacity, @@ -16761,7 +16660,7 @@ function parseSumeragiNposDiagnostics(value) { if (!epochSeed.some((byte) => byte !== 0)) { throw new TypeError(`${context}.epoch_seed must not be zero`); } - return Object.freeze({ + return objectFreeze({ epoch_length_blocks: epochLength, vrf_commit_deadline_offset: commit, vrf_reveal_deadline_offset: reveal, @@ -16798,11 +16697,11 @@ function parseSumeragiDiagnosticLaneCommitments(value) { "teu_total", "block_hash", ]; - return Object.freeze( + return objectFreeze( assertSumeragiArrayBound(value, 1024, context).map((item, index) => { const itemContext = `${context}[${index}]`; const record = assertExactSumeragiRecord(item, fields, itemContext); - return Object.freeze({ + return objectFreeze({ block_height: parseSumeragiUnsigned( record.block_height, `${itemContext}.block_height`, @@ -16838,11 +16737,11 @@ function parseSumeragiDiagnosticDataspaceCommitments(value) { "teu_total", "block_hash", ]; - return Object.freeze( + return objectFreeze( assertSumeragiArrayBound(value, 128, context).map((item, index) => { const itemContext = `${context}[${index}]`; const record = assertExactSumeragiRecord(item, fields, itemContext); - return Object.freeze({ + return objectFreeze({ block_height: parseSumeragiUnsigned( record.block_height, `${itemContext}.block_height`, @@ -16884,7 +16783,7 @@ function parseSumeragiDiagnosticLaneGovernance(value) { "protected_namespaces", "runtime_upgrade", ]; - return Object.freeze( + return objectFreeze( assertSumeragiArrayBound(value, 128, context).map((item, index) => { const itemContext = `${context}[${index}]`; const record = assertExactSumeragiRecord(item, fields, itemContext); @@ -16911,7 +16810,7 @@ function parseSumeragiDiagnosticLaneGovernance(value) { if (quorum !== null && quorum > validatorIds.length) { throw new RangeError(`${itemContext}.quorum exceeds the validator roster`); } - return Object.freeze({ + return objectFreeze({ lane_id: parseSumeragiUnsigned(record.lane_id, `${itemContext}.lane_id`, { max: 0xffffffff, }), @@ -16960,7 +16859,7 @@ function parseSumeragiDiagnosticRuntimeUpgrade(value, context) { if (new Set(allowedIds).size !== allowedIds.length) { throw new TypeError(`${context}.allowed_ids contains duplicates`); } - return Object.freeze({ + return objectFreeze({ allow: parseSumeragiBoolean(record.allow, `${context}.allow`), require_metadata: parseSumeragiBoolean( record.require_metadata, @@ -16974,7 +16873,7 @@ function parseSumeragiDiagnosticRuntimeUpgrade(value, context) { } function parseSumeragiDiagnosticStringArray(value, context) { - return Object.freeze( + return objectFreeze( assertSumeragiArrayBound(value, 128, context).map((item, index) => requireExactNonEmptyString(item, `${context}[${index}]`), ), @@ -17002,14 +16901,14 @@ function parseSumeragiNativeParticipantApplications(value) { "application_block_hash", ]; let previousKey = null; - return Object.freeze( + return objectFreeze( assertSumeragiArrayBound(value, 1024, context).map((item, index) => { const itemContext = `${context}[${index}]`; const record = ensureRecord(item, itemContext); const allowed = new Set([...requiredFields, ...optionalFields]); - const unknown = Object.keys(record).find((field) => !allowed.has(field)); + const unknown = objectKeys(record).find((field) => !allowed.has(field)); const missing = requiredFields.find( - (field) => !Object.prototype.hasOwnProperty.call(record, field), + (field) => !objectHasOwn(record, field), ); if (unknown !== undefined || missing !== undefined) { throw new TypeError( @@ -17090,7 +16989,7 @@ function parseSumeragiNativeParticipantApplications(value) { `${itemContext} durably applied evidence requires an application block`, ); } - return Object.freeze({ + return objectFreeze({ lane_id: laneId, dataspace_id: dataspaceId, lane_incarnation: laneIncarnation, @@ -17152,13 +17051,13 @@ function parseSumeragiAutonomousLaneExecutions(value) { "queue_finalization_unverifiable", "evidence_conflict", ]); let previousKey = null; - return Object.freeze(assertSumeragiArrayBound(value, 128, context).map((item, index) => { + return objectFreeze(assertSumeragiArrayBound(value, 128, context).map((item, index) => { const itemContext = `${context}[${index}]`; const record = ensureRecord(item, itemContext); const allowed = new Set([...required, ...optional]); - const unknown = Object.keys(record).find((field) => !allowed.has(field)); + const unknown = objectKeys(record).find((field) => !allowed.has(field)); const missing = required.find( - (field) => !Object.prototype.hasOwnProperty.call(record, field), + (field) => !objectHasOwn(record, field), ); if (unknown !== undefined || missing !== undefined) { throw new TypeError(unknown !== undefined @@ -17249,7 +17148,7 @@ function parseSumeragiAutonomousLaneExecutions(value) { throw new TypeError(`${itemContext} evidence does not match durable stage`); } } - return Object.freeze({ + return objectFreeze({ lane_id: laneId, dataspace_id: dataspaceId, lane_incarnation: incarnation, lane_block_height: laneHeight, lane_block_view: laneView, proposal_height: proposalHeight, proposal_view: proposalView, @@ -17298,13 +17197,13 @@ function parseSumeragiLivenessStatus(value, context, active) { "blocker", "ignore_counts", ]); - const unknown = Object.keys(record).find((field) => !fields.has(field)); + const unknown = objectKeys(record).find((field) => !fields.has(field)); if (unknown !== undefined) { throw new TypeError(`${context} contains unknown field ${unknown}`); } for (const field of fields) { if (field !== "last_progress" && field !== "blocker" && - !Object.prototype.hasOwnProperty.call(record, field)) { + !objectHasOwn(record, field)) { throw new TypeError(`${context} is missing required field ${field}`); } } @@ -17392,7 +17291,7 @@ function parseSumeragiLivenessStatus(value, context, active) { ) { throw new RangeError(`${itemContext} does not form its advertised dual quorum`); } - return Object.freeze({ + return objectFreeze({ round, signer_count: signerCount, signed_power: signedPower, @@ -17406,7 +17305,7 @@ function parseSumeragiLivenessStatus(value, context, active) { `${itemContext}.proposal_round`, ); validateSumeragiProposalRound(proposalRound, round, itemContext); - return Object.freeze({ + return objectFreeze({ round, proposal_round: proposalRound, subject: parseSumeragiBlockSubject(item.subject, `${itemContext}.subject`), @@ -17420,7 +17319,7 @@ function parseSumeragiLivenessStatus(value, context, active) { total_power: totalPower, }); }; - const voteQuorums = (field, phase) => Object.freeze( + const voteQuorums = (field, phase) => objectFreeze( assertSumeragiArrayBound(record[field], 128, `${context}.${field}`).map( (item, index) => checkedPartialQuorum( item, @@ -17429,7 +17328,7 @@ function parseSumeragiLivenessStatus(value, context, active) { ), ), ); - const timeoutQuorums = Object.freeze( + const timeoutQuorums = objectFreeze( assertSumeragiArrayBound( record.timeout_quorums, 128, @@ -17448,7 +17347,7 @@ function parseSumeragiLivenessStatus(value, context, active) { "prepare_qc", "commit_qc", ]); - const outboundIntents = Object.freeze( + const outboundIntents = objectFreeze( assertSumeragiArrayBound( record.outbound_intents, 7, @@ -17464,12 +17363,12 @@ function parseSumeragiLivenessStatus(value, context, active) { "execution_commitment", "stage", ]); - const unknownField = Object.keys(item).find((field) => !allowedFields.has(field)); + const unknownField = objectKeys(item).find((field) => !allowedFields.has(field)); if (unknownField !== undefined) { throw new TypeError(`${itemContext} contains unknown field ${unknownField}`); } for (const field of ["kind", "round", "stage"]) { - if (!Object.prototype.hasOwnProperty.call(item, field)) { + if (!objectHasOwn(item, field)) { throw new TypeError(`${itemContext} is missing required field ${field}`); } } @@ -17524,7 +17423,7 @@ function parseSumeragiLivenessStatus(value, context, active) { if (proposalRound !== null) { validateSumeragiProposalRound(proposalRound, round, itemContext); } - return Object.freeze({ + return objectFreeze({ kind, round, proposal_round: proposalRound, @@ -17540,8 +17439,8 @@ function parseSumeragiLivenessStatus(value, context, active) { ["candidate", "body_recovery", "body_store", "validation", "application", "successor_height"], `${context}.work`, ); - const work = Object.freeze(Object.fromEntries( - Object.keys(workRecord).map((field) => [ + const work = objectFreeze(Object.fromEntries( + objectKeys(workRecord).map((field) => [ field, parseSumeragiTaggedUnit( workRecord[field], @@ -17553,7 +17452,7 @@ function parseSumeragiLivenessStatus(value, context, active) { )); const queueNames = new Set(); - const queues = Object.freeze( + const queues = objectFreeze( assertSumeragiArrayBound(record.queues, 10, `${context}.queues`).map((raw, index) => { const itemContext = `${context}.queues[${index}]`; const item = ensureRecord(raw, itemContext); @@ -17564,12 +17463,12 @@ function parseSumeragiLivenessStatus(value, context, active) { "oldest_age_ms", "service_debt", ]); - const unknownField = Object.keys(item).find((field) => !allowedFields.has(field)); + const unknownField = objectKeys(item).find((field) => !allowedFields.has(field)); if (unknownField !== undefined) { throw new TypeError(`${itemContext} contains unknown field ${unknownField}`); } for (const field of ["queue", "depth", "capacity", "service_debt"]) { - if (!Object.prototype.hasOwnProperty.call(item, field)) { + if (!objectHasOwn(item, field)) { throw new TypeError(`${itemContext} is missing required field ${field}`); } } @@ -17607,7 +17506,7 @@ function parseSumeragiLivenessStatus(value, context, active) { if (depth > capacity || ((depth === 0) !== (oldestAge === null))) { throw new RangeError(`${itemContext} has inconsistent occupancy and age`); } - return Object.freeze({ + return objectFreeze({ queue, depth, capacity, @@ -17634,7 +17533,7 @@ function parseSumeragiLivenessStatus(value, context, active) { if (progressGeneration > generation) { throw new RangeError(`${context}.last_progress.generation is from the future`); } - lastProgress = Object.freeze({ + lastProgress = objectFreeze({ generation: progressGeneration, round: checkedRound(progress.round, `${context}.last_progress.round`), transition: parseSumeragiTaggedUnit( @@ -17681,7 +17580,7 @@ function parseSumeragiLivenessStatus(value, context, active) { ); const ignoreReasons = new Set(); - const ignoreCounts = Object.freeze( + const ignoreCounts = objectFreeze( assertSumeragiArrayBound(record.ignore_counts, 12, `${context}.ignore_counts`).map( (raw, index) => { const itemContext = `${context}.ignore_counts[${index}]`; @@ -17709,7 +17608,7 @@ function parseSumeragiLivenessStatus(value, context, active) { throw new TypeError(`${itemContext}.reason is duplicated`); } ignoreReasons.add(reason.reason); - return Object.freeze({ + return objectFreeze({ reason, count: parseSumeragiUnsigned(item.count, `${itemContext}.count`), }); @@ -17717,7 +17616,7 @@ function parseSumeragiLivenessStatus(value, context, active) { ), ); - return Object.freeze({ + return objectFreeze({ generation, prepare_quorums: voteQuorums("prepare_quorums", "prepare"), commit_quorums: voteQuorums("commit_quorums", "commit"), @@ -17749,7 +17648,7 @@ function parseSumeragiSafetyHalt(value, context) { "conflicting_parent_state_root", "conflicting_post_state_root", ]); - const unknownField = Object.keys(record).find((field) => !allowedFields.has(field)); + const unknownField = objectKeys(record).find((field) => !allowedFields.has(field)); if (unknownField !== undefined) { throw new TypeError(`${context} contains unknown field ${unknownField}`); } @@ -17759,7 +17658,7 @@ function parseSumeragiSafetyHalt(value, context) { if (reason !== null && typeof reason !== "string") { throw new TypeError(`${context}.reason must be a string or null`); } - return Object.freeze({ + return objectFreeze({ active: parseSumeragiBoolean(record.active, `${context}.active`), reason, height: parseSumeragiUnsigned(record.height, `${context}.height`), @@ -17779,7 +17678,7 @@ function parseSumeragiUnsigned(value, context, options = {}) { if ( ( typeof value !== "number" || - !Number.isSafeInteger(value) || + !numberIsSafeInteger(value) || Object.is(value, -0) ) && typeof value !== "bigint" @@ -17821,7 +17720,7 @@ function sumeragiRoundsEqual(left, right) { } function parseSumeragiExactUnsigned(value, context, options = {}) { - if (typeof value !== "number" || !Number.isSafeInteger(value)) { + if (typeof value !== "number" || !numberIsSafeInteger(value)) { throw new TypeError(`${context} must be an unsigned integer`); } return parseSumeragiUnsigned(value, context, options); @@ -17876,12 +17775,12 @@ function parseSumeragiByte32(value, context) { } function parseSumeragiByteVector(value, length, context) { - if (!Array.isArray(value) || value.length !== length) { + if (!arrayIsArray(value) || value.length !== length) { throw new TypeError(`${context} must contain exactly ${length} byte values`); } - return Object.freeze( + return objectFreeze( value.map((byte, index) => { - if (!Number.isInteger(byte) || byte < 0 || byte > 0xff) { + if (!numberIsInteger(byte) || byte < 0 || byte > 0xff) { throw new TypeError(`${context}[${index}] must be an integer byte`); } return byte; @@ -17890,7 +17789,7 @@ function parseSumeragiByteVector(value, length, context) { } function assertSumeragiArrayBound(value, maximum, context, minimum = 0) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } if (value.length < minimum) { @@ -17905,13 +17804,13 @@ function assertSumeragiArrayBound(value, maximum, context, minimum = 0) { function assertExactSumeragiRecord(value, fields, context) { const record = ensureRecord(value, context); const expected = new Set(fields); - for (const field of Object.keys(record)) { + for (const field of objectKeys(record)) { if (!expected.has(field)) { throw new TypeError(`${context} contains unknown field ${field}`); } } for (const field of fields) { - if (!Object.prototype.hasOwnProperty.call(record, field)) { + if (!objectHasOwn(record, field)) { throw new TypeError(`${context} is missing required field ${field}`); } } @@ -17919,10 +17818,10 @@ function assertExactSumeragiRecord(value, fields, context) { } function parseSumeragiContextId(value, context) { - if (!Array.isArray(value) || value.length !== 1) { + if (!arrayIsArray(value) || value.length !== 1) { throw new TypeError(`${context} must be a one-element hash tuple`); } - return Object.freeze([parseSumeragiHash(value[0], `${context}[0]`)]); + return objectFreeze([parseSumeragiHash(value[0], `${context}[0]`)]); } function parseSumeragiTaggedUnit(value, tag, allowed, context) { @@ -17937,22 +17836,22 @@ function parseSumeragiTaggedUnit(value, tag, allowed, context) { function parseSumeragiTaggedUnitWithContent(value, tag, content, allowed, context) { const record = ensureRecord(value, context); - if (Object.keys(record).some((field) => field !== tag && field !== content)) { + if (objectKeys(record).some((field) => field !== tag && field !== content)) { throw new TypeError(`${context} contains an unknown tagged-enum field`); } const variant = requireNonEmptyString(record[tag], `${context}.${tag}`); if (!allowed.includes(variant)) { throw new TypeError(`${context}.${tag} is not a supported v2 variant`); } - if (!Object.prototype.hasOwnProperty.call(record, content) || record[content] !== null) { + if (!objectHasOwn(record, content) || record[content] !== null) { throw new TypeError(`${context}.${content} must be explicitly null`); } - return Object.freeze({ [tag]: variant, [content]: null }); + return objectFreeze({ [tag]: variant, [content]: null }); } function parseSumeragiRound(value, context) { const record = ensureRecord(value, context); - return Object.freeze({ + return objectFreeze({ context_id: parseSumeragiContextId(record.context_id, `${context}.context_id`), height: parseSumeragiUnsigned(record.height, `${context}.height`), view: parseSumeragiUnsigned(record.view, `${context}.view`), @@ -17973,7 +17872,7 @@ function validateSumeragiProposalRound(proposalRound, round, context) { function parseSumeragiBlockSubject(value, context) { const record = ensureRecord(value, context); - return Object.freeze({ + return objectFreeze({ parent_block_hash: record.parent_block_hash == null ? null @@ -18001,7 +17900,7 @@ function parseSumeragiExecutionCommitment(value, context) { "native_amx_application_manifest_count", "executed_block_wire_hash", ]); - const unknown = Object.keys(record).find((field) => !allowedFields.has(field)); + const unknown = objectKeys(record).find((field) => !allowedFields.has(field)); if (unknown !== undefined) { throw new TypeError(`${context} contains unknown field ${unknown}`); } @@ -18046,7 +17945,7 @@ function parseSumeragiExecutionCommitment(value, context) { `${context}.native_amx_application_manifest_count must be zero exactly for the canonical empty root`, ); } - return Object.freeze({ + return objectFreeze({ parent_state_root: parseSumeragiHash( record.parent_state_root, `${context}.parent_state_root`, @@ -18085,7 +17984,7 @@ function parseSumeragiQcReference(value, context) { `${context}.phase`, ); validateSumeragiProposalRound(proposalRound, round, context); - return Object.freeze({ + return objectFreeze({ round, proposal_round: proposalRound, phase, @@ -18099,7 +17998,7 @@ function parseSumeragiQcReference(value, context) { function parseSumeragiTimeoutReference(value, context) { const record = ensureRecord(value, context); - return Object.freeze({ + return objectFreeze({ round: parseSumeragiRound(record.round, `${context}.round`), highest_prepare_qc: record.highest_prepare_qc == null @@ -18123,7 +18022,7 @@ function parseSumeragiHeightContext(value, context) { { positive: true, max: 128 }, ); const quorumRecord = ensureRecord(record.quorum, `${context}.quorum`); - const quorum = Object.freeze({ + const quorum = objectFreeze({ min_signers: parseSumeragiUnsigned( quorumRecord.min_signers, `${context}.quorum.min_signers`, @@ -18149,7 +18048,7 @@ function parseSumeragiHeightContext(value, context) { throw new RangeError(`${context}.quorum.total_power must equal validator_count in permissioned mode`); } const epochSeed = parseSumeragiByte32(record.epoch_seed, `${context}.epoch_seed`); - return Object.freeze({ + return objectFreeze({ epoch: parseSumeragiUnsigned(record.epoch, `${context}.epoch`), epoch_end_height: parseSumeragiUnsigned( record.epoch_end_height, @@ -18198,7 +18097,7 @@ function parseSumeragiCommitQcStatus(value, context) { ) { throw new RangeError(`${context} does not satisfy its frozen dual quorum`); } - return Object.freeze({ + return objectFreeze({ certificate: parseSumeragiQcReference(record.certificate, `${context}.certificate`), validator_count: validatorCount, signer_count: signerCount, @@ -18211,7 +18110,7 @@ function parseSumeragiCommitQcStatus(value, context) { function parseSumeragiOperatorStatus(value, context) { const record = ensureRecord(value, context); const adapter = ensureRecord(record.adapter_queues, `${context}.adapter_queues`); - const adapterQueues = Object.freeze({ + const adapterQueues = objectFreeze({ ingress_keys: parseSumeragiUnsigned(adapter.ingress_keys, `${context}.adapter_queues.ingress_keys`), ingress_capacity: parseSumeragiUnsigned( adapter.ingress_capacity, @@ -18247,7 +18146,7 @@ function parseSumeragiOperatorStatus(value, context) { throw new RangeError(`${context}.adapter_queues occupancy exceeds capacity`); } const queue = ensureRecord(record.tx_queue, `${context}.tx_queue`); - const txQueue = Object.freeze({ + const txQueue = objectFreeze({ tracked_transactions: parseSumeragiUnsigned( queue.tracked_transactions, `${context}.tx_queue.tracked_transactions`, @@ -18292,7 +18191,7 @@ function parseSumeragiOperatorStatus(value, context) { ) { throw new RangeError(`${context}.tx_queue occupancy exceeds capacity`); } - return Object.freeze({ + return objectFreeze({ view_change_install_total: parseSumeragiUnsigned( record.view_change_install_total, `${context}.view_change_install_total`, @@ -18307,18 +18206,18 @@ function parseSumeragiOperatorStatus(value, context) { } function parseSumeragiRecordArray(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } - return Object.freeze( - value.map((entry, index) => Object.freeze({ ...ensureRecord(entry, `${context}[${index}]`) })), + return objectFreeze( + value.map((entry, index) => objectFreeze({ ...ensureRecord(entry, `${context}[${index}]`) })), ); } function parseSumeragiLanePayloadOwnerships(value) { const context = "status.lane_payload_ownerships"; assertSumeragiArrayBound(value, 128, context); - return Object.freeze(value.map((entry, index) => { + return objectFreeze(value.map((entry, index) => { const itemContext = `${context}[${index}]`; const record = assertExactSumeragiRecord( entry, @@ -18350,7 +18249,7 @@ function parseSumeragiLanePayloadOwnerships(value) { `${itemContext}.lane_block_height`, { positive: true }, ); - if (!Array.isArray(record.accepted_candidate_indices)) { + if (!arrayIsArray(record.accepted_candidate_indices)) { throw new TypeError(`${itemContext}.accepted_candidate_indices must be an array`); } const acceptedCandidateIndices = record.accepted_candidate_indices.map((candidate, offset) => @@ -18364,7 +18263,7 @@ function parseSumeragiLanePayloadOwnerships(value) { throw new TypeError(`${itemContext}.accepted_candidate_indices must be strictly ordered`); } } - if (!Array.isArray(record.accepted_transaction_hashes)) { + if (!arrayIsArray(record.accepted_transaction_hashes)) { throw new TypeError(`${itemContext}.accepted_transaction_hashes must be an array`); } const acceptedTransactionHashes = record.accepted_transaction_hashes.map((hash, offset) => @@ -18425,7 +18324,7 @@ function parseSumeragiLanePayloadOwnerships(value) { if (record.lane_block_descriptor_hash == null) { throw new TypeError(`${itemContext}.lane_block_descriptor_hash is required`); } - return Object.freeze({ + return objectFreeze({ proposal_height: parseSumeragiUnsigned(record.proposal_height, `${itemContext}.proposal_height`), proposal_view: parseSumeragiUnsigned(record.proposal_view, `${itemContext}.proposal_view`), lane_id: parseSumeragiUnsigned(record.lane_id, `${itemContext}.lane_id`, { max: 0xffffffff }), @@ -18435,15 +18334,15 @@ function parseSumeragiLanePayloadOwnerships(value) { lane_block_view: parseSumeragiUnsigned(record.lane_block_view, `${itemContext}.lane_block_view`), subject_hash: parseSumeragiHash(record.subject_hash, `${itemContext}.subject_hash`), qc_mode_tag: requireNonEmptyString(record.qc_mode_tag, `${itemContext}.qc_mode_tag`), - accepted_candidate_indices: Object.freeze(acceptedCandidateIndices), - accepted_transaction_hashes: Object.freeze(acceptedTransactionHashes), + accepted_candidate_indices: objectFreeze(acceptedCandidateIndices), + accepted_transaction_hashes: objectFreeze(acceptedTransactionHashes), previous_lane_block_height: previousHeight, previous_lane_block_descriptor_hash: previousDescriptor, lane_block_descriptor_hash: parseSumeragiHash( record.lane_block_descriptor_hash, `${itemContext}.lane_block_descriptor_hash`, ), - lane_block_descriptor_validator_set: Object.freeze(validators), + lane_block_descriptor_validator_set: objectFreeze(validators), lane_block_descriptor_validator_count: validatorCount, lane_block_descriptor_min_quorum: minQuorum, payload_ownership_hash: parseSumeragiHash( @@ -18461,7 +18360,7 @@ function parseSumeragiLanePayloadOwnerships(value) { function parseSumeragiCommittedLaneBlocks(value) { const context = "status.committed_lane_blocks"; assertSumeragiArrayBound(value, 128, context); - return Object.freeze(value.map((entry, index) => { + return objectFreeze(value.map((entry, index) => { const itemContext = `${context}[${index}]`; const record = assertExactSumeragiRecord( entry, @@ -18544,7 +18443,7 @@ function parseSumeragiCommittedLaneBlocks(value) { ) { throw new RangeError(`${itemContext} carries an impossible certified quorum`); } - return Object.freeze({ + return objectFreeze({ lane_id: parseSumeragiUnsigned(record.lane_id, `${itemContext}.lane_id`, { max: 0xffffffff }), dataspace_id: parseSumeragiUnsigned(record.dataspace_id, `${itemContext}.dataspace_id`), lane_incarnation: parseSumeragiNonzeroHash(record.lane_incarnation, `${itemContext}.lane_incarnation`), @@ -18569,7 +18468,7 @@ function parseSumeragiCommittedLaneBlocks(value) { function parseSumeragiLaneBlockSessions(value) { const context = "status.lane_block_sessions"; assertSumeragiArrayBound(value, 128, context); - return Object.freeze(value.map((entry, index) => { + return objectFreeze(value.map((entry, index) => { const itemContext = `${context}[${index}]`; const record = assertExactSumeragiRecord( entry, @@ -18625,7 +18524,7 @@ function parseSumeragiLaneBlockSessions(value) { ) { throw new RangeError(`${itemContext} carries impossible session quorum counts`); } - return Object.freeze({ + return objectFreeze({ lane_id: parseSumeragiUnsigned(record.lane_id, `${itemContext}.lane_id`, { max: 0xffffffff }), dataspace_id: parseSumeragiUnsigned(record.dataspace_id, `${itemContext}.dataspace_id`), lane_incarnation: parseSumeragiNonzeroHash(record.lane_incarnation, `${itemContext}.lane_incarnation`), @@ -18679,9 +18578,9 @@ function normalizeSumeragiCommitQcRecord(payload, context) { { allowScheme: true }, ); if (record.commit_qc == null) { - return Object.freeze({ subject_block_hash, commit_qc: null }); + return objectFreeze({ subject_block_hash, commit_qc: null }); } - return Object.freeze({ + return objectFreeze({ subject_block_hash, commit_qc: normalizeSumeragiCommitQcPayload(record.commit_qc, `${context}.commit_qc`), }); @@ -18689,7 +18588,7 @@ function normalizeSumeragiCommitQcRecord(payload, context) { function normalizeSumeragiCommitQcPayload(payload, context) { const record = ensureRecord(payload, context); - return Object.freeze({ + return objectFreeze({ phase: requireNonEmptyString(record.phase, `${context}.phase`), parent_state_root: normalizeHex32String( record.parent_state_root, @@ -18730,7 +18629,7 @@ function normalizeSumeragiCommitQcPayload(payload, context) { } function normalizeStringArray(payload, context) { - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError(`${context} must be an array`); } return payload.map((value, index) => @@ -18853,7 +18752,7 @@ function normalizeSumeragiPhasesEma(payload, context) { function normalizeSumeragiBlsKeysMap(payload) { const record = ensureRecord(payload, "sumeragi BLS keys payload"); const normalized = {}; - for (const [key, value] of Object.entries(record)) { + for (const [key, value] of objectEntries(record)) { const peerId = requireNonEmptyString(key, "sumeragi BLS key peer id"); if (value == null) { normalized[peerId] = null; @@ -18948,7 +18847,7 @@ function normalizeSumeragiTelemetryAvailabilityCollectors(payload, context) { if (payload == null) { return []; } - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError(`${context} must be an array`); } return payload.map((entry, index) => @@ -18969,7 +18868,7 @@ function normalizeSumeragiTelemetryQcLatencyList(payload, context) { if (payload == null) { return []; } - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError(`${context} must be an array`); } return payload.map((entry, index) => @@ -19053,7 +18952,7 @@ function normalizeSumeragiTelemetryNumericArray(payload, context) { if (payload == null) { return []; } - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError(`${context} must be an array`); } return payload.map((value, index) => coerceInteger(value, `${context}[${index}]`)); @@ -19063,7 +18962,7 @@ function normalizeSumeragiTelemetryVrfLateRevealList(payload, context) { if (payload == null) { return []; } - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError(`${context} must be an array`); } return payload.map((entry, index) => @@ -19121,7 +19020,7 @@ function parseGovernanceProposalRecord(payload) { } function parseGovernanceProposalKind(payload, context) { - const entries = Object.entries(payload); + const entries = objectEntries(payload); if (entries.length !== 1) { throw new TypeError(`${context} must contain exactly one variant entry`); } @@ -19139,7 +19038,7 @@ function parseGovernanceProposalKind(payload, context) { throw new TypeError("SccpRouteGovernance proposal kind expects an object payload"); } const proposal = ensureRecord(details, `${context}.SccpRouteGovernance`); - const fields = Object.keys(proposal); + const fields = objectKeys(proposal); if (fields.length !== 1 || fields[0] !== "action") { throw new TypeError( `${context}.SccpRouteGovernance must contain only \`action\``, @@ -19240,7 +19139,7 @@ function parseGovernanceLocksResult(payload) { throw new TypeError("governance locks payload `locks` must be an object"); } const locks = {}; - for (const [accountId, entry] of Object.entries(locksPayload)) { + for (const [accountId, entry] of objectEntries(locksPayload)) { if (typeof accountId !== "string" || !accountId) { throw new TypeError("governance locks keys must be non-empty account identifiers"); } @@ -19278,7 +19177,7 @@ function parseGovernanceLockRecord(payload, context) { }; } -const GOVERNANCE_LOCK_CUSTODY_KEYS = Object.freeze([ +const GOVERNANCE_LOCK_CUSTODY_KEYS = objectFreeze([ "escrowed", "asset_definition_id", "bond_escrow_account", @@ -19365,7 +19264,7 @@ function normalizeErrorPath(context) { } function normalizeGovernanceCouncilMembers(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, `${context} must be an array`, @@ -19395,7 +19294,7 @@ function normalizeProtectedNamespaceList(input) { if (input === undefined || input === null) { throw new TypeError("protected namespaces input is required"); } - const values = Array.isArray(input) ? input : [input]; + const values = arrayIsArray(input) ? input : [input]; if (values.length === 0) { throw new TypeError("protected namespaces list must not be empty"); } @@ -20115,7 +20014,7 @@ function requireVpnEnum(value, allowed, context) { } function requireVpnProfileExitClasses(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } const exits = value.map((entry, index) => @@ -20259,7 +20158,7 @@ function normalizeVpnOptionalTxInstruction(payload, context) { } function normalizeVpnTxInstructionList(payload, context, { min = 0, max } = {}) { - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError(`${context} must be an array`); } if (payload.length < min || (max !== undefined && payload.length > max)) { @@ -20577,7 +20476,7 @@ function normalizeVpnReceiptListResponse(payload) { VPN_RECEIPT_LIST_RESPONSE_FIELDS, "vpn receipts response", ); - if (!Array.isArray(record.items)) { + if (!arrayIsArray(record.items)) { throw new TypeError("vpn receipts response.items must be an array"); } if (record.items.length > 24) { @@ -20600,7 +20499,7 @@ function normalizeVpnReceiptListResponse(payload) { function assertVpnResponseFields(record, requiredFields, context) { assertSupportedOptionKeys(record, requiredFields, context); const missing = [...requiredFields].filter( - (field) => !Object.prototype.hasOwnProperty.call(record, field), + (field) => !objectHasOwn(record, field), ); if (missing.length > 0) { throw createValidationError( @@ -20662,11 +20561,11 @@ function normalizeSnsSuffixPolicy(payload) { "sns suffix policy.referral_cap_bps", { allowZero: true }, ); - const reservedLabels = Array.isArray(record.reserved_labels) + const reservedLabels = arrayIsArray(record.reserved_labels) ? record.reserved_labels.map((entry, index) => normalizeReservedLabel(entry, `sns suffix policy.reserved_labels[${index}]`)) : []; const paymentAssetId = requireNonEmptyString(record.payment_asset_id, "sns suffix policy.payment_asset_id"); - const pricing = Array.isArray(record.pricing) + const pricing = arrayIsArray(record.pricing) ? record.pricing.map((entry, index) => normalizeSnsPricingTier(entry, `sns suffix policy.pricing[${index}]`)) : []; const feeSplit = normalizeSnsFeeSplit(record.fee_split, "sns suffix policy.fee_split"); @@ -20795,7 +20694,7 @@ function normalizeSnsControllers(value, context) { if (value === undefined || value === null) { return []; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array of controllers`); } return value.map((entry, index) => normalizeSnsController(entry, `${context}[${index}]`)); @@ -20944,7 +20843,7 @@ function normalizeSnsNameStatus(payload, context) { } function normalizeStringList(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((entry, index) => requireNonEmptyString(entry, `${context}[${index}]`)); @@ -20967,7 +20866,7 @@ function normalizeExplorerNftRecord(payload, context) { function normalizeExplorerNftPage(payload) { const record = ensureRecord(payload ?? {}, "explorer nfts response"); const items = record.items; - if (!Array.isArray(items)) { + if (!arrayIsArray(items)) { throw new TypeError("explorer nfts response.items must be an array"); } return { @@ -21021,7 +20920,7 @@ function normalizeExplorerRwaRecord(payload, context) { function normalizeExplorerRwaPage(payload) { const record = ensureRecord(payload ?? {}, "explorer rwas response"); const items = record.items; - if (!Array.isArray(items)) { + if (!arrayIsArray(items)) { throw new TypeError("explorer rwas response.items must be an array"); } return { @@ -21038,7 +20937,7 @@ function normalizeExplorerRwaPage(payload) { function normalizeExplorerBlocksPage(payload) { const record = ensureRecord(payload ?? {}, "explorer blocks response"); const items = record.items; - if (!Array.isArray(items)) { + if (!arrayIsArray(items)) { throw new TypeError("explorer blocks response.items must be an array"); } return { @@ -21151,7 +21050,7 @@ function normalizeExplorerBlockRecord(payload, context) { function normalizeRuntimeUpgradesListResponse(payload) { const record = ensureRecord(payload, "runtime upgrades list response"); const items = record.items ?? []; - if (!Array.isArray(items)) { + if (!arrayIsArray(items)) { throw new TypeError("runtime upgrades list response.items must be an array"); } return items.map((item, index) => @@ -21229,7 +21128,7 @@ function normalizeRuntimeUpgradeManifest(value, context) { function normalizeRuntimeUpgradeStatus(value, context) { const record = ensureRecord(value, context); - const keys = Object.keys(record); + const keys = objectKeys(record); if (keys.length !== 1) { throw new TypeError(`${context} must contain exactly one status key`); } @@ -21338,7 +21237,7 @@ function parseIntegerArray(value, context) { if (value === undefined || value === null) { return []; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((entry, index) => { @@ -21443,7 +21342,7 @@ function parseStringArray(value, context) { if (value == null) { return []; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array of strings`); } return value.map((entry, index) => { @@ -21458,14 +21357,14 @@ function parseRecordArray(value, context) { if (value == null) { return []; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array of objects`); } return value.map((entry, index) => ensureRecord(entry, `${context}[${index}]`)); } function isPlainObject(value) { - if (value === null || typeof value !== "object" || Array.isArray(value)) { + if (value === null || typeof value !== "object" || arrayIsArray(value)) { return false; } const proto = Object.getPrototypeOf(value); @@ -21514,7 +21413,7 @@ function optionalStringArray(value, context) { if (value === undefined || value === null) { return null; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array when present`); } return value.map((entry, index) => { @@ -21526,7 +21425,7 @@ function optionalStringArray(value, context) { } function requireStringArray(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((entry, index) => { @@ -21538,7 +21437,7 @@ function requireStringArray(value, context) { } function requireUnsignedIntegerArray(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((entry, index) => @@ -21606,7 +21505,7 @@ function normalizeUaidPortfolioResponse(payload) { ), }; const dataspacesValue = record.dataspaces ?? []; - if (!Array.isArray(dataspacesValue)) { + if (!arrayIsArray(dataspacesValue)) { throw new TypeError("uaid portfolio response.dataspaces must be an array"); } const dataspaces = dataspacesValue.map((entry, index) => @@ -21621,7 +21520,7 @@ function normalizeUaidPortfolioResponse(payload) { function normalizeUaidPortfolioDataspace(value, context) { const record = ensureRecord(value, context); const accountsValue = record.accounts ?? []; - if (!Array.isArray(accountsValue)) { + if (!arrayIsArray(accountsValue)) { throw new TypeError(`${context}.accounts must be an array`); } return { @@ -21640,7 +21539,7 @@ function normalizeUaidPortfolioDataspace(value, context) { function normalizeUaidPortfolioAccount(value, context) { const record = ensureRecord(value, context); const assetsValue = record.assets ?? []; - if (!Array.isArray(assetsValue)) { + if (!arrayIsArray(assetsValue)) { throw new TypeError(`${context}.assets must be an array`); } return { @@ -21668,7 +21567,7 @@ function normalizeUaidBindingsResponse(payload) { const record = ensureRecord(payload, "uaid bindings response"); const uaid = normalizeUaidLiteral(record.uaid, "uaid bindings response.uaid"); const dataspacesValue = record.dataspaces ?? []; - if (!Array.isArray(dataspacesValue)) { + if (!arrayIsArray(dataspacesValue)) { throw new TypeError("uaid bindings response.dataspaces must be an array"); } const dataspaces = dataspacesValue.map((entry, index) => @@ -21697,7 +21596,7 @@ function normalizeUaidManifestsResponse(payload) { const record = ensureRecord(payload, "uaid manifests response"); const uaid = normalizeUaidLiteral(record.uaid, "uaid manifests response.uaid"); const manifestsValue = record.manifests ?? []; - if (!Array.isArray(manifestsValue)) { + if (!arrayIsArray(manifestsValue)) { throw new TypeError("uaid manifests response.manifests must be an array"); } const manifests = manifestsValue.map((entry, index) => @@ -21765,7 +21664,7 @@ function normalizeUaidManifestLifecycle(value, context) { function normalizeUaidManifest(value, context) { const record = ensureRecord(value, context); const entriesValue = record.entries ?? []; - if (!Array.isArray(entriesValue)) { + if (!arrayIsArray(entriesValue)) { throw new TypeError(`${context}.entries must be an array`); } return { @@ -21867,7 +21766,7 @@ function isTruthyFilter(filters, key) { function extractExtraFields(record, recognizedKeys) { const extra = {}; - for (const [key, value] of Object.entries(record)) { + for (const [key, value] of objectEntries(record)) { if (!recognizedKeys.has(key)) { extra[key] = value; } @@ -21971,9 +21870,9 @@ const PROVER_FILTER_DEFINITIONS = { const PROVER_FILTER_ALIAS_MAP = (() => { const map = new Map(); - for (const [key, spec] of Object.entries(PROVER_FILTER_DEFINITIONS)) { + for (const [key, spec] of objectEntries(PROVER_FILTER_DEFINITIONS)) { map.set(key, { key, spec }); - const aliases = Array.isArray(spec.aliases) ? spec.aliases : []; + const aliases = arrayIsArray(spec.aliases) ? spec.aliases : []; for (const alias of aliases) { map.set(alias, { key, spec }); } @@ -22049,7 +21948,7 @@ function toBuffer(value) { if (value instanceof ArrayBuffer) { return Buffer.from(value); } - if (Array.isArray(value)) { + if (arrayIsArray(value)) { if (value.length === 0) { return Buffer.alloc(0); } @@ -22060,7 +21959,7 @@ function toBuffer(value) { function normalizeByteArray(value, context) { const bytes = value.map((entry, index) => { - if (!Number.isInteger(entry) || entry < 0 || entry > 255) { + if (!numberIsInteger(entry) || entry < 0 || entry > 255) { throw createValidationError( ValidationErrorCode.VALUE_OUT_OF_RANGE, `${context}[${index}] must be an integer between 0 and 255`, @@ -22110,7 +22009,7 @@ function findHeaderKey(headers, name) { return null; } const target = String(name).toLowerCase(); - for (const key of Object.keys(headers)) { + for (const key of objectKeys(headers)) { if (key.toLowerCase() === target) { return key; } @@ -22142,7 +22041,7 @@ function hasHeader(headers, name) { function cloneHeadersForFetch(headers) { const clone = {}; if (headers && typeof headers === "object") { - for (const [key, value] of Object.entries(headers)) { + for (const [key, value] of objectEntries(headers)) { clone[key] = value; } } @@ -22436,7 +22335,7 @@ function requireExactJsonUnsignedInteger(value, name, options = {}) { const minimum = options.allowZero === false ? 1 : 0; if ( typeof value !== "number" || - !Number.isSafeInteger(value) || + !numberIsSafeInteger(value) || value < minimum ) { throw createValidationError( @@ -22550,14 +22449,14 @@ function normalizeStorageTicketHex(value, name) { function coerceIntegerLike(value, context) { if (typeof value === "number") { - if (!Number.isFinite(value) || !Number.isSafeInteger(value)) { + if (!numberIsFinite(value) || !numberIsSafeInteger(value)) { throw new RangeError(`${context} must be a safe integer`); } return value; } if (typeof value === "bigint") { const numeric = Number(value); - if (!Number.isSafeInteger(numeric)) { + if (!numberIsSafeInteger(numeric)) { throw new RangeError(`${context} must be a safe integer`); } return numeric; @@ -22568,7 +22467,7 @@ function coerceIntegerLike(value, context) { throw new TypeError(`${context} must be an integer`); } const numeric = Number(trimmed); - if (!Number.isFinite(numeric) || !Number.isSafeInteger(numeric)) { + if (!numberIsFinite(numeric) || !numberIsSafeInteger(numeric)) { throw new RangeError(`${context} must be a safe integer`); } return numeric; @@ -22592,7 +22491,7 @@ function requireExactPositiveIntegerLike(value, context) { throw new TypeError(`${context} is required`); } if (typeof value === "number") { - if (!Number.isFinite(value) || !Number.isSafeInteger(value) || value <= 0) { + if (!numberIsFinite(value) || !numberIsSafeInteger(value) || value <= 0) { throw new RangeError(`${context} must be a positive integer`); } if (value > MAX_SIGNED_INT32) { @@ -22660,10 +22559,10 @@ function pickOverride(source, snakeName, camelName) { if (!source || typeof source !== "object") { return undefined; } - if (Object.prototype.hasOwnProperty.call(source, snakeName)) { + if (objectHasOwn(source, snakeName)) { return source[snakeName]; } - if (Object.prototype.hasOwnProperty.call(source, camelName)) { + if (objectHasOwn(source, camelName)) { return source[camelName]; } return undefined; @@ -22676,7 +22575,7 @@ function rejectValidationFeeSnakeCaseInputs(source, context) { ["validation_fee_instruction_index", "validationFeeInstructionIndex"], ["validation_fee_transfer_entry_index", "validationFeeTransferEntryIndex"], ]) { - if (Object.prototype.hasOwnProperty.call(source, snakeName)) { + if (objectHasOwn(source, snakeName)) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, `${context} uses unsupported snake_case validation fee field ${snakeName}; use ${camelName}`, @@ -22819,7 +22718,7 @@ function assertExactManifestResponseValueType(value, context) { return; } const record = exactManifestResponseRecord(value, ["nodes"], context); - if (!Array.isArray(record.nodes)) { + if (!arrayIsArray(record.nodes)) { return; } record.nodes.forEach((node, index) => { @@ -22872,7 +22771,7 @@ function assertExactManifestResponseShape(value, context) { ["dynamic_reads", access.dynamic_reads], ["dynamic_writes", access.dynamic_writes], ]) { - if (!Array.isArray(hints)) { + if (!arrayIsArray(hints)) { continue; } hints.forEach((hint, index) => { @@ -22885,7 +22784,7 @@ function assertExactManifestResponseShape(value, context) { } } - if (Array.isArray(manifest.entrypoints)) { + if (arrayIsArray(manifest.entrypoints)) { manifest.entrypoints.forEach((entrypoint, index) => { const entrypointContext = `${context}.entrypoints[${index}]`; const entrypointRecord = exactManifestResponseRecord( @@ -22911,7 +22810,7 @@ function assertExactManifestResponseShape(value, context) { ["kind", "value"], `${entrypointContext}.kind`, ); - if (Array.isArray(entrypointRecord.params)) { + if (arrayIsArray(entrypointRecord.params)) { entrypointRecord.params.forEach((param, paramIndex) => { exactManifestResponseRecord( param, @@ -22929,7 +22828,7 @@ function assertExactManifestResponseShape(value, context) { ["fields"], `${entrypointContext}.argument_schema`, ); - if (Array.isArray(argumentSchema.fields)) { + if (arrayIsArray(argumentSchema.fields)) { argumentSchema.fields.forEach((field, fieldIndex) => { const fieldContext = `${entrypointContext}.argument_schema.fields[${fieldIndex}]`; @@ -22946,7 +22845,7 @@ function assertExactManifestResponseShape(value, context) { entrypointRecord.return_schema, `${entrypointContext}.return_schema`, ); - if (Array.isArray(entrypointRecord.triggers)) { + if (arrayIsArray(entrypointRecord.triggers)) { entrypointRecord.triggers.forEach((trigger, triggerIndex) => { const triggerContext = `${entrypointContext}.triggers[${triggerIndex}]`; const triggerRecord = exactManifestResponseRecord( @@ -22969,7 +22868,7 @@ function assertExactManifestResponseShape(value, context) { }); } - if (Array.isArray(manifest.states)) { + if (arrayIsArray(manifest.states)) { manifest.states.forEach((state, index) => { exactManifestResponseRecord( state, @@ -22978,7 +22877,7 @@ function assertExactManifestResponseShape(value, context) { ); }); } - if (Array.isArray(manifest.error_codes)) { + if (arrayIsArray(manifest.error_codes)) { manifest.error_codes.forEach((errorCode, index) => { exactManifestResponseRecord( errorCode, @@ -22987,7 +22886,7 @@ function assertExactManifestResponseShape(value, context) { ); }); } - if (Array.isArray(manifest.kotoba)) { + if (arrayIsArray(manifest.kotoba)) { manifest.kotoba.forEach((entry, index) => { const entryContext = `${context}.kotoba[${index}]`; const entryRecord = exactManifestResponseRecord( @@ -22995,7 +22894,7 @@ function assertExactManifestResponseShape(value, context) { ["msg_id", "translations"], entryContext, ); - if (Array.isArray(entryRecord.translations)) { + if (arrayIsArray(entryRecord.translations)) { entryRecord.translations.forEach((translation, translationIndex) => { exactManifestResponseRecord( translation, @@ -23041,17 +22940,17 @@ function normalizeManifestPayload(manifest, context) { "kotoba", "provenance", ]); - const unknownFields = Object.keys(manifest).filter((field) => !allowedFields.has(field)); + const unknownFields = objectKeys(manifest).filter((field) => !allowedFields.has(field)); if (unknownFields.length !== 0) { throw new TypeError( `${context} contains unsupported fields: ${unknownFields.sort().join(", ")}`, ); } const hasField = (...keys) => - keys.some((key) => Object.prototype.hasOwnProperty.call(manifest, key)); + keys.some((key) => objectHasOwn(manifest, key)); const getField = (...keys) => { const present = keys.filter((key) => - Object.prototype.hasOwnProperty.call(manifest, key), + objectHasOwn(manifest, key), ); if (present.length > 1) { throw new TypeError(`${context} contains conflicting aliases: ${present.join(", ")}`); @@ -23130,7 +23029,7 @@ function normalizeManifestPayload(manifest, context) { const entries = getField("entrypoints", "entryPoints"); if (entries === null) { normalized.entrypoints = null; - } else if (!Array.isArray(entries)) { + } else if (!arrayIsArray(entries)) { throw new TypeError(`${context}.entrypoints must be an array`); } else { normalized.entrypoints = entries.map((entry, index) => { @@ -23313,7 +23212,7 @@ function validateManifestDynamicAccessHintStateMaps(accessSetHints, states, cont } function normalizeManifestKotobaPayload(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((entry, index) => { @@ -23332,7 +23231,7 @@ function normalizeManifestKotobaPayload(value, context) { } function normalizeManifestKotobaTranslationsPayload(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((translation, index) => { @@ -23389,7 +23288,7 @@ function normalizeManifestSignaturePayload(value, context) { let body; if (Buffer.isBuffer(value) || value instanceof Uint8Array) { body = Buffer.from(value).toString("hex"); - } else if (Array.isArray(value)) { + } else if (arrayIsArray(value)) { body = normalizeByteArray(value, context).toString("hex"); } else { const literal = requireNonEmptyString(value, context).trim(); @@ -23422,7 +23321,7 @@ function normalizeAccessSetHintsPayload(payload, context) { if (value === undefined || value === null) { return []; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${name} must be an array of strings`); } return value.map((entry, index) => @@ -23433,7 +23332,7 @@ function normalizeAccessSetHintsPayload(payload, context) { if (value === undefined || value === null) { return []; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${name} must be an array of dynamic access hints`); } return value.map((entry, index) => { @@ -23520,8 +23419,8 @@ function normalizeAccessSetHintsPayload(payload, context) { } function selectEqualManifestAlias(record, snakeCase, camelCase, context) { - const hasSnakeCase = Object.prototype.hasOwnProperty.call(record, snakeCase); - const hasCamelCase = Object.prototype.hasOwnProperty.call(record, camelCase); + const hasSnakeCase = objectHasOwn(record, snakeCase); + const hasCamelCase = objectHasOwn(record, camelCase); if ( hasSnakeCase && hasCamelCase && @@ -23642,7 +23541,7 @@ function normalizeManifestEntrypointParams(value, context) { if (value === undefined || value === null) { return []; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } if (value.length > 13) { @@ -23679,7 +23578,7 @@ function normalizeManifestArgumentSchema(value, context) { return null; } const record = ensureRecord(value, context); - if (!Array.isArray(record.fields)) { + if (!arrayIsArray(record.fields)) { throw new TypeError(`${context}.fields must be an array`); } if (record.fields.length === 0 || record.fields.length > 13) { @@ -23719,7 +23618,7 @@ function normalizeManifestValueType(value, context) { function normalizeRequiredManifestValueType(value, context) { const record = ensureRecord(value, context); - if (!Array.isArray(record.nodes)) { + if (!arrayIsArray(record.nodes)) { throw new TypeError(`${context}.nodes must be an array`); } const normalized = { @@ -23765,7 +23664,7 @@ function normalizeManifestValueTypeNode(value, context) { return { kind, value: null }; case "List": { const list = ensureRecord(record.value, `${context}.value`); - const fields = Object.keys(list); + const fields = objectKeys(list); if (fields.length !== 1 || fields[0] !== "capacity") { throw new TypeError( `${context}.value must contain exactly capacity; the element subtree follows in the nodes tape`, @@ -23843,7 +23742,7 @@ function normalizeManifestStringArray(value, context) { if (value === undefined || value === null) { return []; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((entry, index) => @@ -23858,7 +23757,7 @@ function requireManifestNull(value, context) { } function normalizeManifestStatesPayload(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((state, index) => { @@ -23889,7 +23788,7 @@ function normalizeManifestStatesPayload(value, context) { } function normalizeManifestErrorCodesPayload(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((errorCode, index) => { @@ -23924,7 +23823,7 @@ function normalizeManifestTriggersPayload(value, context) { if (value === undefined || value === null) { return []; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((trigger, index) => { @@ -23962,7 +23861,7 @@ function normalizeManifestTriggersPayload(value, context) { function normalizeManifestRepeatsPayload(value, context) { const record = ensureRecord(value, context); - const keys = Object.keys(record); + const keys = objectKeys(record); if (keys.length !== 1) { throw new TypeError(`${context} must contain exactly one repeat variant`); } @@ -24141,7 +24040,7 @@ function normalizeHex32String(value, name, options = {}) { if (value instanceof ArrayBuffer) { return normalizeHex32String(Buffer.from(value).toString("hex"), name, options); } - if (Array.isArray(value)) { + if (arrayIsArray(value)) { return normalizeHex32String(normalizeByteArray(value, name).toString("hex"), name, options); } let normalized = requireNonEmptyString(value, name); @@ -24206,7 +24105,7 @@ function normalizeHexBytesString(value, name) { if (value instanceof ArrayBuffer) { return Buffer.from(value).toString("hex"); } - if (Array.isArray(value)) { + if (arrayIsArray(value)) { return normalizeByteArray(value, name).toString("hex"); } const normalized = requireHexString(value, name); @@ -24323,7 +24222,7 @@ function normalizeHashLike32(value, name, options = {}) { if (value instanceof ArrayBuffer) { return normalizeHex32String(Buffer.from(value).toString("hex"), name, options); } - if (Array.isArray(value)) { + if (arrayIsArray(value)) { return normalizeHex32String(normalizeByteArray(value, name).toString("hex"), name, options); } const normalized = requireNonEmptyString(value, name); @@ -24424,7 +24323,7 @@ function cloneJsonValueInternal(value, path, state, depth) { return value; } if (typeof value === "number") { - if (!Number.isFinite(value)) { + if (!numberIsFinite(value)) { throw new TypeError(`${path} must not contain non-finite numbers`); } return value; @@ -24440,10 +24339,10 @@ function cloneJsonValueInternal(value, path, state, depth) { } state.ancestors.add(value); try { - if (Array.isArray(value)) { - const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length"); + if (arrayIsArray(value)) { + const lengthDescriptor = objectGetOwnPropertyDescriptor(value, "length"); const length = lengthDescriptor?.value; - if (!Number.isSafeInteger(length) || length < 0) { + if (!numberIsSafeInteger(length) || length < 0) { throw new TypeError(`${path} must be an exact JSON array`); } if (length > JSON_CLONE_MAX_NODES) { @@ -24464,7 +24363,7 @@ function cloneJsonValueInternal(value, path, state, depth) { } const result = new Array(length); for (let index = 0; index < length; index += 1) { - const descriptor = Object.getOwnPropertyDescriptor(value, String(index)); + const descriptor = objectGetOwnPropertyDescriptor(value, String(index)); if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) { throw new TypeError(`${path}[${index}] must be an enumerable data property`); } @@ -24482,7 +24381,7 @@ function cloneJsonValueInternal(value, path, state, depth) { if (typeof key !== "string") { throw new TypeError(`${path} keys must be strings without symbols`); } - const descriptor = Object.getOwnPropertyDescriptor(value, key); + const descriptor = objectGetOwnPropertyDescriptor(value, key); if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) { throw new TypeError(`${path}.${key} must be an enumerable data property`); } @@ -24555,7 +24454,7 @@ function normalizeSpaceDirectoryManifestPayload(input, context) { ); } const entriesRaw = manifest.entries ?? manifest.Entries; - if (!Array.isArray(entriesRaw) || entriesRaw.length === 0) { + if (!arrayIsArray(entriesRaw) || entriesRaw.length === 0) { throw new TypeError(`${context}.entries must be a non-empty array`); } normalized.entries = entriesRaw.map((entry, index) => { @@ -24951,7 +24850,7 @@ function normalizeGovernanceDraftResponse( ) { const record = ensureRecord(payload, context); const instructionsValue = record.tx_instructions ?? []; - if (!Array.isArray(instructionsValue)) { + if (!arrayIsArray(instructionsValue)) { throw new TypeError(`${context}.tx_instructions must be an array`); } const txInstructions = instructionsValue.map((entry, index) => { @@ -25194,7 +25093,7 @@ function normalizeGovernancePublicInputs(value, name) { normalizeGovernancePublicInputHex(normalized, "nullifier", name); ensureGovernanceLockHintsComplete(normalized, name); if ( - Object.prototype.hasOwnProperty.call(normalized, "amount") && + objectHasOwn(normalized, "amount") && normalized.amount !== null ) { normalized.amount = requireCanonicalQuantity( @@ -25203,7 +25102,7 @@ function normalizeGovernancePublicInputs(value, name) { ); } if ( - Object.prototype.hasOwnProperty.call(normalized, "owner") && + objectHasOwn(normalized, "owner") && normalized.owner !== null ) { normalized.owner = ensureCanonicalAccountId(normalized.owner, `${name}.owner`); @@ -25212,7 +25111,7 @@ function normalizeGovernancePublicInputs(value, name) { } function normalizeGovernancePublicInputHex(target, key, name) { - if (!Object.prototype.hasOwnProperty.call(target, key)) { + if (!objectHasOwn(target, key)) { return; } const value = target[key]; @@ -25247,7 +25146,7 @@ function normalizeGovernancePublicInputHex(target, key, name) { } function rejectGovernancePublicInputKey(target, key, canonicalKey, name) { - if (!Object.prototype.hasOwnProperty.call(target, key)) { + if (!objectHasOwn(target, key)) { return; } throw createValidationError( @@ -25445,7 +25344,7 @@ function normalizeGovernanceZkBallotProofPayload(input) { "nullifier", ballotContext, ); - if (Object.prototype.hasOwnProperty.call(normalizedBallot, "root_hint")) { + if (objectHasOwn(normalizedBallot, "root_hint")) { const rootHint = normalizedBallot.root_hint; if (rootHint !== null) { normalizedBallot.root_hint = normalizeHex32String( @@ -25455,7 +25354,7 @@ function normalizeGovernanceZkBallotProofPayload(input) { ); } } - if (Object.prototype.hasOwnProperty.call(normalizedBallot, "nullifier")) { + if (objectHasOwn(normalizedBallot, "nullifier")) { const nullifier = normalizedBallot.nullifier; if (nullifier !== null) { normalizedBallot.nullifier = normalizeHex32String( @@ -25467,7 +25366,7 @@ function normalizeGovernanceZkBallotProofPayload(input) { } ensureGovernanceLockHintsComplete(normalizedBallot, ballotContext); if ( - Object.prototype.hasOwnProperty.call(normalizedBallot, "amount") && + objectHasOwn(normalizedBallot, "amount") && normalizedBallot.amount !== null ) { normalizedBallot.amount = normalizeQuantityInput( @@ -25476,7 +25375,7 @@ function normalizeGovernanceZkBallotProofPayload(input) { ); } if ( - Object.prototype.hasOwnProperty.call(normalizedBallot, "owner") && + objectHasOwn(normalizedBallot, "owner") && normalizedBallot.owner !== null ) { normalizedBallot.owner = ensureCanonicalAccountId( @@ -25883,7 +25782,7 @@ function normalizeContractCallSimulateResponse(payload) { "contractCall simulation response.gas_used", { allowZero: true }, ), - queued_instructions: Array.isArray(record.queued_instructions) + queued_instructions: arrayIsArray(record.queued_instructions) ? record.queued_instructions.map((instruction, index) => cloneJsonValue( instruction, @@ -25980,7 +25879,7 @@ function normalizeZkIvmProvedPayload(value, context) { record.bytecode, `${context}.bytecode`, ); - if (!Array.isArray(record.overlay)) { + if (!arrayIsArray(record.overlay)) { throw new TypeError(`${context}.overlay must be an array`); } const overlay = cloneJsonValue(record.overlay, `${context}.overlay`, { @@ -26014,7 +25913,7 @@ function exactEnumerableDataRecord(value, expectedKeys, context) { } const snapshot = {}; for (const key of expectedKeys) { - const descriptor = Object.getOwnPropertyDescriptor(record, key); + const descriptor = objectGetOwnPropertyDescriptor(record, key); if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) { throw new TypeError(`${context}.${key} must be an enumerable data property`); } @@ -26175,10 +26074,10 @@ function normalizeExactJsonByteArray( context, { exactLength = null, maxLength = null } = {}, ) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an exact byte array`); } - const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length"); + const lengthDescriptor = objectGetOwnPropertyDescriptor(value, "length"); if (!lengthDescriptor || !("value" in lengthDescriptor)) { throw new TypeError(`${context} must be an exact byte array`); } @@ -26198,18 +26097,18 @@ function normalizeExactJsonByteArray( const bytes = new Uint8ArrayIntrinsic(length); let enumerableKeys = 0; for (const key in value) { - if (!Object.prototype.hasOwnProperty.call(value, key)) { + if (!objectHasOwn(value, key)) { throw new TypeError(`${context} must not inherit enumerable fields`); } if (key !== String(enumerableKeys) || enumerableKeys >= length) { throw new TypeError(`${context} must be a dense exact byte array`); } - const descriptor = Object.getOwnPropertyDescriptor(value, key); + const descriptor = objectGetOwnPropertyDescriptor(value, key); const byte = descriptor && "value" in descriptor ? descriptor.value : null; if ( !descriptor?.enumerable || typeof byte !== "number" || - !Number.isInteger(byte) || + !numberIsInteger(byte) || byte < 0 || byte > 0xff ) { @@ -26258,7 +26157,7 @@ function normalizeZkIvmProveJobCreatedResponse(payload) { function normalizeZkIvmProveJobResponse(payload) { const candidate = ensureRecord(payload, "IVM prove job status response"); - const statusDescriptor = Object.getOwnPropertyDescriptor(candidate, "status"); + const statusDescriptor = objectGetOwnPropertyDescriptor(candidate, "status"); if ( !statusDescriptor || !("value" in statusDescriptor) || @@ -26402,7 +26301,7 @@ function normalizeMultisigProposalsQueryRequest(input, context) { const record = ensureRecord(input, context); const payload = normalizeMultisigAccountSelector(record, context); if (record.status !== undefined) { - if (!Array.isArray(record.status)) { + if (!arrayIsArray(record.status)) { throw new TypeError(`${context}.status must be an array`); } payload.status = record.status.map((status, index) => @@ -26428,7 +26327,7 @@ function normalizeMultisigProposeInstructionInput(value, context) { Buffer.isBuffer(value) || ArrayBuffer.isView(value) || value instanceof ArrayBuffer || - Array.isArray(value) + arrayIsArray(value) ) { return value; } @@ -26448,7 +26347,7 @@ function normalizeMultisigProposeRequest(input) { rejectRetiredFeeSelectionFields(record, "proposeMultisig request"); const selector = normalizeMultisigAccountSelector(record, "proposeMultisig request"); const instructionsValue = pickOverride(record, "instructions", "instructions"); - if (!Array.isArray(instructionsValue) || instructionsValue.length === 0) { + if (!arrayIsArray(instructionsValue) || instructionsValue.length === 0) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, "proposeMultisig request.instructions must be a non-empty array", @@ -26814,7 +26713,7 @@ function normalizeMultisigProposalsQueryResponse( ) { const record = ensureRecord(payload, context); const proposalsValue = record.proposals; - if (!Array.isArray(proposalsValue)) { + if (!arrayIsArray(proposalsValue)) { throw new TypeError(`${context}.proposals must be an array`); } return { @@ -26941,7 +26840,7 @@ function normalizeContractCodeBytesResponse(payload) { "contract code bytes response must contain exactly the code_b64 field", ); } - const descriptor = Object.getOwnPropertyDescriptor(record, "code_b64"); + const descriptor = objectGetOwnPropertyDescriptor(record, "code_b64"); if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) { throw new TypeError( "contract code bytes response code_b64 must be an enumerable data property", @@ -27092,7 +26991,7 @@ function normalizeManifestEntrypointsPayload(value, name) { if (value === undefined || value === null) { return null; } - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${name} must be an array of entrypoints`); } if (value.length === 0) { @@ -27229,7 +27128,7 @@ function normalizeAliasLookupByAccountResponse( ) { const record = ensureRecord(payload ?? {}, context); const accountId = ToriiClient._requireAccountId(record.account_id, `${context}.account_id`); - const rawItems = Array.isArray(record.items) ? record.items : []; + const rawItems = arrayIsArray(record.items) ? record.items : []; const items = rawItems.map((item, index) => { const aliasRecord = ensureRecord(item, `${context}.items[${index}]`); const alias = requireNonEmptyString(aliasRecord.alias, `${context}.items[${index}].alias`); @@ -27424,7 +27323,7 @@ function rejectRetiredFeeSelectionFields( retired.push(["gasLimit", "feePayment.value.gas_limit"]); } for (const [field, replacement] of retired) { - if (Object.prototype.hasOwnProperty.call(record, field)) { + if (objectHasOwn(record, field)) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, `${context}.${field} is retired; use ${replacement}`, @@ -27634,11 +27533,11 @@ function normalizeFeeQuoteResponse(payload, context = "fee quote response") { } function requireDenseArray(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } for (let index = 0; index < value.length; index += 1) { - if (!Object.prototype.hasOwnProperty.call(value, index)) { + if (!objectHasOwn(value, index)) { throw new TypeError(`${context} must be a dense array`); } } @@ -27959,7 +27858,7 @@ function requireBfvUint(value, name, options = {}) { if (typeof value === "bigint") { integer = value; } else if (typeof value === "number") { - if (!Number.isFinite(value) || !Number.isInteger(value) || !Number.isSafeInteger(value)) { + if (!numberIsFinite(value) || !numberIsInteger(value) || !numberIsSafeInteger(value)) { throw createValidationError( ValidationErrorCode.VALUE_OUT_OF_RANGE, `${name} must be a safe integer number, bigint, or decimal string`, @@ -28015,7 +27914,7 @@ function normalizeIdentifierBfvUint(value, name, options = {}) { } function normalizeIdentifierBfvUintArray(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((entry, index) => @@ -28478,7 +28377,7 @@ function normalizeIdentifierPolicyListResponse( ) { const record = ensureRecord(payload ?? {}, context); const itemsValue = record.items; - if (!Array.isArray(itemsValue)) { + if (!arrayIsArray(itemsValue)) { throw new Error(`${context}.items must be an array`); } return { @@ -28499,7 +28398,7 @@ function normalizeRamLfeProgramPolicyListResponse( ) { const record = ensureRecord(payload ?? {}, context); const itemsValue = record.items; - if (!Array.isArray(itemsValue)) { + if (!arrayIsArray(itemsValue)) { throw new Error(`${context}.items must be an array`); } return { @@ -29301,7 +29200,7 @@ function buildSorafsAliasListParams(options = {}) { { allowZero: true }, ); } - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } function buildSorafsPinListParams(options = {}) { @@ -29340,7 +29239,7 @@ function buildSorafsPinListParams(options = {}) { { allowZero: true }, ); } - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } function buildSorafsReplicationListParams(options = {}) { @@ -29385,7 +29284,7 @@ function buildSorafsReplicationListParams(options = {}) { { allowZero: true }, ); } - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } function normalizeSorafsReputationProviderId(value, context) { @@ -29414,6 +29313,49 @@ function normalizeSorafsReputationProviderId(value, context) { return providerId; } +async function getSorafsReputationJson( + client, + path, + options, + methodContext, + responseContext, + parser, + parserOptions, +) { + const { signal, rest } = ToriiClient._normalizeOptionsWithSignal( + options, + methodContext, + ); + assertSupportedOptionKeys( + rest, + SORAFS_REPUTATION_CACHE_OPTION_KEYS, + `${methodContext} options`, + ); + const auth = buildSorafsReputationRequestAuth( + rest, + client._config.defaultHeaders, + methodContext, + ); + const response = await client._request("GET", path, { + headers: auth.headers, + canonicalAuth: auth.canonicalAuth, + disableRetries: true, + redirect: "error", + signal, + }); + await client._expectStatus(response, [200, 304, 404]); + if (response.status === 304 || response.status === 404) { + return null; + } + const payload = await client._readBoundedLosslessIntegerJson( + response, + SORAFS_REPUTATION_JSON_MAX_BYTES, + responseContext, + { signal }, + ); + return parser(payload, responseContext, parserOptions); +} + function normalizeReputationSnapshotIdHex(value, context) { if (typeof value !== "string" || !/^[0-9a-f]{32}$/u.test(value)) { throw createValidationError( @@ -29447,7 +29389,7 @@ function normalizeSorafsHedgingBillingDigest(value, context) { function normalizeSorafsHedgingBillingLimit(value, context) { if ( typeof value !== "number" || - !Number.isSafeInteger(value) || + !numberIsSafeInteger(value) || value < 1 || value > 100 ) { @@ -29497,7 +29439,7 @@ function sorafsReputationCanonicalAuthEntries(headers, context) { return new Map(); } const entries = new Map(); - for (const [rawName, rawValue] of Object.entries(headers)) { + for (const [rawName, rawValue] of objectEntries(headers)) { const normalizedName = String(rawName).toLowerCase(); if (!SORAFS_REPUTATION_CANONICAL_AUTH_HEADERS.has(normalizedName)) { continue; @@ -29627,7 +29569,7 @@ function buildSorafsReputationHeaders( `${context}.headers`, ); } - for (const [key, value] of Object.entries(options.headers)) { + for (const [key, value] of objectEntries(options.headers)) { if (value !== undefined && value !== null) { headers[key] = SORAFS_REPUTATION_CANONICAL_AUTH_HEADERS.has( key.toLowerCase(), @@ -29666,7 +29608,7 @@ function normalizeSorafsReputationDecimal( ) { let integer; if (typeof value === "number") { - if (!Number.isSafeInteger(value)) { + if (!numberIsSafeInteger(value)) { throw createValidationError( ValidationErrorCode.INVALID_NUMERIC, `${context} must be a safe integer, bigint, or canonical decimal string`, @@ -29721,7 +29663,7 @@ function buildSorafsReputationEventsParams(options = {}, context) { { allowZero: false, max: 500n }, ); } - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } function buildSorafsOrderbookHeaders(options = {}, context, { cache = false } = {}) { @@ -29734,7 +29676,7 @@ function buildSorafsOrderbookHeaders(options = {}, context, { cache = false } = `${context}.headers`, ); } - for (const [key, value] of Object.entries(options.headers)) { + for (const [key, value] of objectEntries(options.headers)) { if (value !== undefined && value !== null) { headers[key] = String(value); } @@ -29804,7 +29746,7 @@ function buildSorafsOrderbookReadParams(options = {}, context) { `${context}.afterIdHex`, ); } - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } function appendSorafsOrderbookEventCursor(params, options, context) { @@ -29858,7 +29800,7 @@ function buildSorafsOrderbookEventsParams(options = {}, context) { ); } appendSorafsOrderbookEventCursor(params, options, context); - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } function normalizeSorafsOrderbookFinalizedSource(value, context) { @@ -29916,7 +29858,7 @@ function normalizeSorafsOrderbookLedgerStatus(payload, context) { } function normalizeSorafsOrderbookRecordArray(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value.map((entry, index) => ({ @@ -30062,7 +30004,7 @@ function normalizeSorafsOrderbookEventsResponse( ) { const record = ensureRecord(payload ?? {}, context); const page = ensureRecord(record.events, `${context}.events`); - if (!Array.isArray(page.events)) { + if (!arrayIsArray(page.events)) { throw new TypeError(`${context}.events.events must be an array`); } if (typeof page.has_more !== "boolean") { @@ -30150,7 +30092,7 @@ function normalizeSorafsXorQuantity(value, context) { function rejectRetiredSorafsMonetaryFields(record, retiredNames, context) { const present = retiredNames.filter((name) => - Object.prototype.hasOwnProperty.call(record, name), + objectHasOwn(record, name), ); if (present.length > 0) { throw createValidationError( @@ -30161,106 +30103,105 @@ function rejectRetiredSorafsMonetaryFields(record, retiredNames, context) { } } -const SORAFS_REPUTATION_SNAPSHOT_FIELDS = new Set([ - "snapshot_id_hex", - "generated_at_unix", - "previous_snapshot_id_hex", - "merkle_root_hex", - "provider_count", - "returned_provider_count", - "limit", - "truncated_providers", - "alpha_bps", - "current_score_weight_bps", - "weights", - "providers", -]); -const SORAFS_REPUTATION_PROVIDER_RESPONSE_FIELDS = new Set([ - "snapshot_id_hex", - "generated_at_unix", - "merkle_root_hex", - "provider", - "proof", -]); -const SORAFS_REPUTATION_WEIGHTS_RESPONSE_FIELDS = new Set([ - "snapshot_id_hex", - "generated_at_unix", - "alpha_bps", - "current_score_weight_bps", - "weights", -]); -const SORAFS_REPUTATION_WEIGHTS_FIELDS = new Set([ - "version", - "por_success_bps", - "pdp_success_bps", - "potr_success_bps", - "latency_bps", - "dispute_bps", - "token_violation_bps", - "repair_breach_bps", -]); -const SORAFS_REPUTATION_PROVIDER_FIELDS = new Set([ - "provider_id", - "score_bps", - "degradation_flags", - "raw_metrics", - "raw_metrics_hash_hex", -]); -const SORAFS_REPUTATION_PROVIDER_METRICS_FIELDS = new Set([ - "version", - "por_success_bps", - "pdp_success_bps", - "potr_success_bps", - "latency_health_bps", - "dispute_rate_bps", - "token_violation_rate_bps", - "repair_breach_rate_bps", -]); -const SORAFS_REPUTATION_DEGRADATION_FLAG_FIELDS = new Set(["flag", "value"]); -const SORAFS_REPUTATION_PROOF_FIELDS = new Set([ - "provider_id", - "leaf_index", - "leaf_count", - "siblings_hex", -]); -const SORAFS_REPUTATION_EVENT_FIELDS = new Set([ - "version", - "sequence", - "snapshot_id_hex", - "generated_at_unix", - "merkle_root_hex", - "provider_count", - "previous_snapshot_id_hex", -]); -const SORAFS_REPUTATION_EVENT_PAGE_FIELDS = new Set([ - "since", - "limit", - "count", - "next_since", - "events", -]); -const SORAFS_REPUTATION_DEGRADATION_FLAG_ORDER = Object.freeze([ - "reserve_warning", - "reserve_grace", - "reserve_delinquent", - "reserve_default", - "proof_success_below90", - "proof_success_below80", - "active_dispute", - "slashing_event", - "low_score", -]); -const SORAFS_REPUTATION_DEGRADATION_FLAG_INDEX = new Map( - SORAFS_REPUTATION_DEGRADATION_FLAG_ORDER.map((flag, index) => [flag, index]), -); - +const SORAFS_REPUTATION_SNAPSHOT_FIELDS = { + snapshot_id_hex: [normalizeReputationSnapshotIdHex], + generated_at_unix: [parseSorafsReputationU64, { minimum: 1n }], + previous_snapshot_id_hex: [parseSorafsReputationOptionalSnapshotId], + merkle_root_hex: [parseSorafsReputationDigest], + provider_count: [parseSorafsReputationBoundedInteger, 1, 65_536], + returned_provider_count: [parseSorafsReputationBoundedInteger, 1, 500], + limit: [parseSorafsReputationBoundedInteger, 1, 500], + truncated_providers: [parseSumeragiBoolean], + alpha_bps: [parseSorafsReputationExactInteger, 8_500], + current_score_weight_bps: [parseSorafsReputationExactInteger, 7_000], + weights: [parseSorafsReputationWeights], + providers: [parseSorafsReputationProviders], +}; +const SORAFS_REPUTATION_PROVIDER_RESPONSE_FIELDS = { + snapshot_id_hex: [normalizeReputationSnapshotIdHex], + generated_at_unix: [parseSorafsReputationU64, { minimum: 1n }], + merkle_root_hex: [parseSorafsReputationDigest], + provider: [parseSorafsReputationProvider], + proof: [parseSorafsReputationProof], +}; +const SORAFS_REPUTATION_WEIGHTS_RESPONSE_FIELDS = { + snapshot_id_hex: [normalizeReputationSnapshotIdHex], + generated_at_unix: [parseSorafsReputationU64, { minimum: 1n }], + alpha_bps: [parseSorafsReputationExactInteger, 8_500], + current_score_weight_bps: [parseSorafsReputationExactInteger, 7_000], + weights: [parseSorafsReputationWeights], +}; +const SORAFS_REPUTATION_WEIGHTS_FIELDS = { + version: 0, + por_success_bps: 0, + pdp_success_bps: 0, + potr_success_bps: 0, + latency_bps: 0, + dispute_bps: 0, + token_violation_bps: 0, + repair_breach_bps: 0, +}; +const SORAFS_REPUTATION_PROVIDER_FIELDS = { + provider_id: [normalizeSorafsReputationProviderId], + score_bps: [parseSorafsReputationBoundedInteger, 500, 9_900], + degradation_flags: [parseSorafsReputationDegradationFlags], + raw_metrics: [parseSorafsReputationProviderMetrics], + raw_metrics_hash_hex: [parseSorafsReputationDigest], +}; +const SORAFS_REPUTATION_PROVIDER_METRICS_FIELDS = { + version: 0, + por_success_bps: 0, + pdp_success_bps: 0, + potr_success_bps: 0, + latency_health_bps: 0, + dispute_rate_bps: 0, + token_violation_rate_bps: 0, + repair_breach_rate_bps: 0, +}; +const SORAFS_REPUTATION_DEGRADATION_FLAG_FIELDS = { flag: 0, value: 0 }; +const SORAFS_REPUTATION_PROOF_FIELDS = { + provider_id: [normalizeSorafsReputationProviderId], + leaf_index: [parseSorafsReputationBoundedInteger, 0, 65_535], + leaf_count: [parseSorafsReputationBoundedInteger, 1, 65_536], + siblings_hex: [parseSorafsReputationDigests], +}; +const SORAFS_REPUTATION_EVENT_FIELDS = { + version: [parseSorafsReputationExactInteger, 1], + sequence: [parseSorafsReputationU64, { minimum: 1n }], + snapshot_id_hex: [normalizeReputationSnapshotIdHex], + generated_at_unix: [parseSorafsReputationU64, { minimum: 1n }], + merkle_root_hex: [parseSorafsReputationDigest], + provider_count: [parseSorafsReputationBoundedInteger, 1, 65_536], + previous_snapshot_id_hex: [parseSorafsReputationOptionalSnapshotId], +}; +const SORAFS_REPUTATION_EVENT_PAGE_FIELDS = { + since: [parseSorafsReputationOptionalU64], + limit: [parseSorafsReputationBoundedInteger, 1, 500], + count: [parseSorafsReputationBoundedInteger, 0, 500], + next_since: [parseSorafsReputationOptionalU64, { minimum: 1n }], + events: [parseSorafsReputationEvents], +}; +const SORAFS_REPUTATION_DEGRADATION_FLAG_INDEX = objectFreeze({ + reserve_warning: 0, + reserve_grace: 1, + reserve_delinquent: 2, + reserve_default: 3, + proof_success_below90: 4, + proof_success_below80: 5, + active_dispute: 6, + slashing_event: 7, + low_score: 8, +}); function requireSorafsReputationExactObject(value, expectedFields, context) { const record = ensureRecord(value, context); - const actualFields = Object.keys(record); - const missing = [...expectedFields].filter( - (field) => !Object.prototype.hasOwnProperty.call(record, field), + const actualFields = objectKeys(record); + const canonicalFields = objectKeys(expectedFields); + const missing = canonicalFields.filter( + (field) => !objectHasOwn(record, field), + ); + const extra = actualFields.filter( + (field) => !objectHasOwn(expectedFields, field), ); - const extra = actualFields.filter((field) => !expectedFields.has(field)); if (missing.length !== 0 || extra.length !== 0) { throw new TypeError( `${context} fields are not canonical; missing=[${missing.join( @@ -30272,7 +30213,7 @@ function requireSorafsReputationExactObject(value, expectedFields, context) { } function requireSorafsReputationArray(value, context) { - if (!Array.isArray(value)) { + if (!arrayIsArray(value)) { throw new TypeError(`${context} must be an array`); } return value; @@ -30286,7 +30227,7 @@ function parseSorafsReputationU64( let integer; if ( typeof value === "number" && - Number.isSafeInteger(value) && + numberIsSafeInteger(value) && !Object.is(value, -0) ) { integer = BigInt(value); @@ -30315,24 +30256,16 @@ function parseSorafsReputationBoundedInteger(value, context, minimum, maximum) { } function parseSorafsReputationExactInteger(value, context, expected) { - const parsed = parseSorafsReputationBoundedInteger( + return parseSorafsReputationBoundedInteger( value, context, expected, expected, ); - if (parsed !== expected) { - throw new RangeError(`${context} must equal ${expected}`); - } - return parsed; -} - -function parseSorafsReputationSnapshotId(value, context) { - return normalizeReputationSnapshotIdHex(value, context); } function parseSorafsReputationOptionalSnapshotId(value, context) { - return value === null ? null : parseSorafsReputationSnapshotId(value, context); + return value === null ? null : normalizeReputationSnapshotIdHex(value, context); } function parseSorafsReputationDigest(value, context) { @@ -30344,70 +30277,61 @@ function parseSorafsReputationDigest(value, context) { return value; } -function parseSorafsReputationWeights(value, context) { - const weights = requireSorafsReputationExactObject( +function parseSorafsReputationRecordFields(record, context, schema) { + const parsed = {}; + for (const field of objectKeys(schema)) { + const rule = schema[field]; + parsed[field] = rule[0]( + record[field], + `${context}.${field}`, + rule[1], + rule[2], + ); + } + return parsed; +} + +function parseSorafsReputationRecord(value, context, schema) { + return parseSorafsReputationRecordFields( + requireSorafsReputationExactObject(value, schema, context), + context, + schema, + ); +} + +function parseSorafsReputationBpsRecord( + value, + context, + fields, + requireExactTotal, +) { + const record = requireSorafsReputationExactObject( value, - SORAFS_REPUTATION_WEIGHTS_FIELDS, + fields, context, ); - const parsed = { - version: parseSorafsReputationExactInteger( - weights.version, - `${context}.version`, - 1, - ), - por_success_bps: parseSorafsReputationBoundedInteger( - weights.por_success_bps, - `${context}.por_success_bps`, - 0, - 10_000, - ), - pdp_success_bps: parseSorafsReputationBoundedInteger( - weights.pdp_success_bps, - `${context}.pdp_success_bps`, - 0, - 10_000, - ), - potr_success_bps: parseSorafsReputationBoundedInteger( - weights.potr_success_bps, - `${context}.potr_success_bps`, - 0, - 10_000, - ), - latency_bps: parseSorafsReputationBoundedInteger( - weights.latency_bps, - `${context}.latency_bps`, - 0, - 10_000, - ), - dispute_bps: parseSorafsReputationBoundedInteger( - weights.dispute_bps, - `${context}.dispute_bps`, - 0, - 10_000, - ), - token_violation_bps: parseSorafsReputationBoundedInteger( - weights.token_violation_bps, - `${context}.token_violation_bps`, - 0, - 10_000, - ), - repair_breach_bps: parseSorafsReputationBoundedInteger( - weights.repair_breach_bps, - `${context}.repair_breach_bps`, - 0, - 10_000, - ), - }; - const total = - parsed.por_success_bps + - parsed.pdp_success_bps + - parsed.potr_success_bps + - parsed.latency_bps + - parsed.dispute_bps + - parsed.token_violation_bps + - parsed.repair_breach_bps; - if (total !== 10_000) { + const parsed = {}; + let total = 0; + for (const field of objectKeys(fields)) { + const parsedValue = + field === "version" + ? parseSorafsReputationExactInteger( + record[field], + `${context}.${field}`, + 1, + ) + : parseSorafsReputationBoundedInteger( + record[field], + `${context}.${field}`, + 0, + 10_000, + ); + parsed[field] = parsedValue; + if (field !== "version") { + total += parsedValue; + } + } + if (requireExactTotal && total !== 10_000) { throw new RangeError( `${context} basis-point fields must sum to exactly 10000`, ); @@ -30415,83 +30339,34 @@ function parseSorafsReputationWeights(value, context) { return parsed; } -function parseSorafsReputationProviderMetrics(value, context) { - const metrics = requireSorafsReputationExactObject( +function parseSorafsReputationWeights(value, context) { + return parseSorafsReputationBpsRecord( value, - SORAFS_REPUTATION_PROVIDER_METRICS_FIELDS, context, + SORAFS_REPUTATION_WEIGHTS_FIELDS, + true, ); - return { - version: parseSorafsReputationExactInteger( - metrics.version, - `${context}.version`, - 1, - ), - por_success_bps: parseSorafsReputationBoundedInteger( - metrics.por_success_bps, - `${context}.por_success_bps`, - 0, - 10_000, - ), - pdp_success_bps: parseSorafsReputationBoundedInteger( - metrics.pdp_success_bps, - `${context}.pdp_success_bps`, - 0, - 10_000, - ), - potr_success_bps: parseSorafsReputationBoundedInteger( - metrics.potr_success_bps, - `${context}.potr_success_bps`, - 0, - 10_000, - ), - latency_health_bps: parseSorafsReputationBoundedInteger( - metrics.latency_health_bps, - `${context}.latency_health_bps`, - 0, - 10_000, - ), - dispute_rate_bps: parseSorafsReputationBoundedInteger( - metrics.dispute_rate_bps, - `${context}.dispute_rate_bps`, - 0, - 10_000, - ), - token_violation_rate_bps: parseSorafsReputationBoundedInteger( - metrics.token_violation_rate_bps, - `${context}.token_violation_rate_bps`, - 0, - 10_000, - ), - repair_breach_rate_bps: parseSorafsReputationBoundedInteger( - metrics.repair_breach_rate_bps, - `${context}.repair_breach_rate_bps`, - 0, - 10_000, - ), - }; } -function parseSorafsReputationProvider(value, context) { - const provider = requireSorafsReputationExactObject( +function parseSorafsReputationProviderMetrics(value, context) { + return parseSorafsReputationBpsRecord( value, - SORAFS_REPUTATION_PROVIDER_FIELDS, context, + SORAFS_REPUTATION_PROVIDER_METRICS_FIELDS, + false, ); - const flags = requireSorafsReputationArray( - provider.degradation_flags, - `${context}.degradation_flags`, - ); +} + +function parseSorafsReputationDegradationFlags(value, context) { + const flags = requireSorafsReputationArray(value, context); if (flags.length > 5) { - throw new RangeError( - `${context}.degradation_flags must contain at most five entries`, - ); + throw new RangeError(`${context} must contain at most five entries`); } let previousFlagIndex = -1; - const parsedFlags = flags.map((value, index) => { - const flagContext = `${context}.degradation_flags[${index}]`; + return flags.map((entry, index) => { + const flagContext = `${context}[${index}]`; const flag = requireSorafsReputationExactObject( - value, + entry, SORAFS_REPUTATION_DEGRADATION_FLAG_FIELDS, flagContext, ); @@ -30501,39 +30376,26 @@ function parseSorafsReputationProvider(value, context) { if (typeof flag.flag !== "string") { throw new TypeError(`${flagContext}.flag must be a string`); } - const flagIndex = SORAFS_REPUTATION_DEGRADATION_FLAG_INDEX.get(flag.flag); - if (flagIndex === undefined) { + if (!objectHasOwn(SORAFS_REPUTATION_DEGRADATION_FLAG_INDEX, flag.flag)) { throw new TypeError(`${flagContext}.flag is unsupported`); } + const flagIndex = SORAFS_REPUTATION_DEGRADATION_FLAG_INDEX[flag.flag]; if (flagIndex <= previousFlagIndex) { throw new TypeError( - `${context}.degradation_flags must use canonical enum order without duplicates`, + `${context} must use canonical enum order without duplicates`, ); } previousFlagIndex = flagIndex; return { flag: flag.flag, value: null }; }); - return { - provider_id: normalizeSorafsReputationProviderId( - provider.provider_id, - `${context}.provider_id`, - ), - score_bps: parseSorafsReputationBoundedInteger( - provider.score_bps, - `${context}.score_bps`, - 500, - 9_900, - ), - degradation_flags: parsedFlags, - raw_metrics: parseSorafsReputationProviderMetrics( - provider.raw_metrics, - `${context}.raw_metrics`, - ), - raw_metrics_hash_hex: parseSorafsReputationDigest( - provider.raw_metrics_hash_hex, - `${context}.raw_metrics_hash_hex`, - ), - }; +} + +function parseSorafsReputationProvider(value, context) { + return parseSorafsReputationRecord( + value, + context, + SORAFS_REPUTATION_PROVIDER_FIELDS, + ); } function sorafsReputationMerkleDepth(leafCount) { @@ -30546,20 +30408,26 @@ function sorafsReputationMerkleDepth(leafCount) { return depth; } +function parseSorafsReputationDigests(value, context) { + return requireSorafsReputationArray(value, context).map((digest, index) => + parseSorafsReputationDigest(digest, `${context}[${index}]`), + ); +} + function parseSorafsReputationProof(value, context) { - const proof = requireSorafsReputationExactObject( + const record = requireSorafsReputationExactObject( value, SORAFS_REPUTATION_PROOF_FIELDS, context, ); const leafIndex = parseSorafsReputationBoundedInteger( - proof.leaf_index, + record.leaf_index, `${context}.leaf_index`, 0, 65_535, ); const leafCount = parseSorafsReputationBoundedInteger( - proof.leaf_count, + record.leaf_count, `${context}.leaf_count`, 1, 65_536, @@ -30567,87 +30435,50 @@ function parseSorafsReputationProof(value, context) { if (leafIndex >= leafCount) { throw new RangeError(`${context}.leaf_index must be less than leaf_count`); } - const siblings = requireSorafsReputationArray( - proof.siblings_hex, - `${context}.siblings_hex`, - ).map((sibling, index) => - parseSorafsReputationDigest( - sibling, - `${context}.siblings_hex[${index}]`, - ), + const proof = parseSorafsReputationRecordFields( + record, + context, + SORAFS_REPUTATION_PROOF_FIELDS, ); - if (siblings.length !== sorafsReputationMerkleDepth(leafCount)) { + if ( + proof.siblings_hex.length !== + sorafsReputationMerkleDepth(proof.leaf_count) + ) { throw new RangeError( `${context}.siblings_hex must have the exact Merkle depth for leaf_count`, ); } - return { - provider_id: normalizeSorafsReputationProviderId( - proof.provider_id, - `${context}.provider_id`, - ), - leaf_index: leafIndex, - leaf_count: leafCount, - siblings_hex: siblings, - }; + return proof; } function parseSorafsReputationEvent(value, context) { - const event = requireSorafsReputationExactObject( + const event = parseSorafsReputationRecord( value, - SORAFS_REPUTATION_EVENT_FIELDS, context, + SORAFS_REPUTATION_EVENT_FIELDS, ); - const snapshotId = parseSorafsReputationSnapshotId( - event.snapshot_id_hex, - `${context}.snapshot_id_hex`, - ); - const previousSnapshotId = parseSorafsReputationOptionalSnapshotId( - event.previous_snapshot_id_hex, - `${context}.previous_snapshot_id_hex`, - ); - if (previousSnapshotId === snapshotId) { + if (event.previous_snapshot_id_hex === event.snapshot_id_hex) { throw new TypeError( `${context}.previous_snapshot_id_hex must differ from snapshot_id_hex`, ); } - return { - version: parseSorafsReputationExactInteger( - event.version, - `${context}.version`, - 1, - ), - sequence: parseSorafsReputationU64(event.sequence, `${context}.sequence`, { - minimum: 1n, - }), - snapshot_id_hex: snapshotId, - generated_at_unix: parseSorafsReputationU64( - event.generated_at_unix, - `${context}.generated_at_unix`, - { minimum: 1n }, - ), - merkle_root_hex: parseSorafsReputationDigest( - event.merkle_root_hex, - `${context}.merkle_root_hex`, - ), - provider_count: parseSorafsReputationBoundedInteger( - event.provider_count, - `${context}.provider_count`, - 1, - 65_536, - ), - previous_snapshot_id_hex: previousSnapshotId, - }; + return event; +} + +function parseSorafsReputationProviders(value, context) { + return requireSorafsReputationArray(value, context).map((provider, index) => + parseSorafsReputationProvider(provider, `${context}[${index}]`), + ); } function parseSorafsReputationSnapshot(value, context, options = {}) { - const snapshot = requireSorafsReputationExactObject( + const record = requireSorafsReputationExactObject( value, SORAFS_REPUTATION_SNAPSHOT_FIELDS, context, ); - const snapshotId = parseSorafsReputationSnapshotId( - snapshot.snapshot_id_hex, + const snapshotId = normalizeReputationSnapshotIdHex( + record.snapshot_id_hex, `${context}.snapshot_id_hex`, ); if ( @@ -30657,7 +30488,7 @@ function parseSorafsReputationSnapshot(value, context, options = {}) { throw new TypeError(`${context} does not match the requested snapshot`); } const previousSnapshotId = parseSorafsReputationOptionalSnapshotId( - snapshot.previous_snapshot_id_hex, + record.previous_snapshot_id_hex, `${context}.previous_snapshot_id_hex`, ); if (previousSnapshotId === snapshotId) { @@ -30665,93 +30496,43 @@ function parseSorafsReputationSnapshot(value, context, options = {}) { `${context}.previous_snapshot_id_hex must differ from snapshot_id_hex`, ); } - const providerCount = parseSorafsReputationBoundedInteger( - snapshot.provider_count, - `${context}.provider_count`, - 1, - 65_536, - ); - const returnedProviderCount = parseSorafsReputationBoundedInteger( - snapshot.returned_provider_count, - `${context}.returned_provider_count`, - 1, - 500, - ); - const limit = parseSorafsReputationBoundedInteger( - snapshot.limit, - `${context}.limit`, - 1, - 500, - ); - const providers = requireSorafsReputationArray( - snapshot.providers, - `${context}.providers`, - ).map((provider, index) => - parseSorafsReputationProvider( - provider, - `${context}.providers[${index}]`, - ), + const snapshot = parseSorafsReputationRecordFields( + record, + context, + SORAFS_REPUTATION_SNAPSHOT_FIELDS, ); - if (providers.length !== returnedProviderCount) { + if (snapshot.providers.length !== snapshot.returned_provider_count) { throw new RangeError( `${context}.returned_provider_count must equal providers.length`, ); } - if (returnedProviderCount !== Math.min(providerCount, limit)) { + if ( + snapshot.returned_provider_count !== + Math.min(snapshot.provider_count, snapshot.limit) + ) { throw new RangeError( `${context}.returned_provider_count must equal min(provider_count, limit)`, ); } - for (let index = 1; index < providers.length; index += 1) { - if (providers[index - 1].provider_id >= providers[index].provider_id) { + for (let index = 1; index < snapshot.providers.length; index += 1) { + if ( + snapshot.providers[index - 1].provider_id >= + snapshot.providers[index].provider_id + ) { throw new TypeError( `${context}.providers must be strictly ordered by provider_id`, ); } } - if (typeof snapshot.truncated_providers !== "boolean") { - throw new TypeError(`${context}.truncated_providers must be a boolean`); - } if ( snapshot.truncated_providers !== - (providerCount > returnedProviderCount) + (snapshot.provider_count > snapshot.returned_provider_count) ) { throw new TypeError( `${context}.truncated_providers is inconsistent with provider counts`, ); } - return { - snapshot_id_hex: snapshotId, - generated_at_unix: parseSorafsReputationU64( - snapshot.generated_at_unix, - `${context}.generated_at_unix`, - { minimum: 1n }, - ), - previous_snapshot_id_hex: previousSnapshotId, - merkle_root_hex: parseSorafsReputationDigest( - snapshot.merkle_root_hex, - `${context}.merkle_root_hex`, - ), - provider_count: providerCount, - returned_provider_count: returnedProviderCount, - limit, - truncated_providers: snapshot.truncated_providers, - alpha_bps: parseSorafsReputationExactInteger( - snapshot.alpha_bps, - `${context}.alpha_bps`, - 8_500, - ), - current_score_weight_bps: parseSorafsReputationExactInteger( - snapshot.current_score_weight_bps, - `${context}.current_score_weight_bps`, - 7_000, - ), - weights: parseSorafsReputationWeights( - snapshot.weights, - `${context}.weights`, - ), - providers, - }; + return snapshot; } function parseSorafsReputationProviderResponse( @@ -30759,75 +30540,26 @@ function parseSorafsReputationProviderResponse( context, expectedProviderId, ) { - const response = requireSorafsReputationExactObject( + const response = parseSorafsReputationRecord( value, - SORAFS_REPUTATION_PROVIDER_RESPONSE_FIELDS, context, + SORAFS_REPUTATION_PROVIDER_RESPONSE_FIELDS, ); - const provider = parseSorafsReputationProvider( - response.provider, - `${context}.provider`, - ); - const proof = parseSorafsReputationProof( - response.proof, - `${context}.proof`, - ); - if (provider.provider_id !== proof.provider_id) { + if (response.provider.provider_id !== response.proof.provider_id) { throw new TypeError(`${context}.proof must reference the returned provider`); } - if (provider.provider_id !== expectedProviderId) { + if (response.provider.provider_id !== expectedProviderId) { throw new TypeError(`${context} does not match the requested provider`); } - return { - snapshot_id_hex: parseSorafsReputationSnapshotId( - response.snapshot_id_hex, - `${context}.snapshot_id_hex`, - ), - generated_at_unix: parseSorafsReputationU64( - response.generated_at_unix, - `${context}.generated_at_unix`, - { minimum: 1n }, - ), - merkle_root_hex: parseSorafsReputationDigest( - response.merkle_root_hex, - `${context}.merkle_root_hex`, - ), - provider, - proof, - }; + return response; } function parseSorafsReputationWeightsResponse(value, context) { - const response = requireSorafsReputationExactObject( + return parseSorafsReputationRecord( value, - SORAFS_REPUTATION_WEIGHTS_RESPONSE_FIELDS, context, + SORAFS_REPUTATION_WEIGHTS_RESPONSE_FIELDS, ); - return { - snapshot_id_hex: parseSorafsReputationSnapshotId( - response.snapshot_id_hex, - `${context}.snapshot_id_hex`, - ), - generated_at_unix: parseSorafsReputationU64( - response.generated_at_unix, - `${context}.generated_at_unix`, - { minimum: 1n }, - ), - alpha_bps: parseSorafsReputationExactInteger( - response.alpha_bps, - `${context}.alpha_bps`, - 8_500, - ), - current_score_weight_bps: parseSorafsReputationExactInteger( - response.current_score_weight_bps, - `${context}.current_score_weight_bps`, - 7_000, - ), - weights: parseSorafsReputationWeights( - response.weights, - `${context}.weights`, - ), - }; } function parseSorafsReputationOptionalU64(value, context, options = {}) { @@ -30840,14 +30572,20 @@ function sorafsReputationU64BigInt(value) { return typeof value === "bigint" ? value : BigInt(value); } +function parseSorafsReputationEvents(value, context) { + return requireSorafsReputationArray(value, context).map((event, index) => + parseSorafsReputationEvent(event, `${context}[${index}]`), + ); +} + function parseSorafsReputationEventPage(value, context, options = {}) { - const page = requireSorafsReputationExactObject( + const record = requireSorafsReputationExactObject( value, SORAFS_REPUTATION_EVENT_PAGE_FIELDS, context, ); const since = parseSorafsReputationOptionalU64( - page.since, + record.since, `${context}.since`, ); const expectedSince = @@ -30861,7 +30599,7 @@ function parseSorafsReputationEventPage(value, context, options = {}) { throw new TypeError(`${context}.since does not match the requested cursor`); } const limit = parseSorafsReputationBoundedInteger( - page.limit, + record.limit, `${context}.limit`, 1, 500, @@ -30872,43 +30610,32 @@ function parseSorafsReputationEventPage(value, context, options = {}) { ) { throw new TypeError(`${context}.limit does not match the requested limit`); } - const count = parseSorafsReputationBoundedInteger( - page.count, - `${context}.count`, - 0, - 500, - ); - const events = requireSorafsReputationArray( - page.events, - `${context}.events`, - ).map((event, index) => - parseSorafsReputationEvent(event, `${context}.events[${index}]`), + const page = parseSorafsReputationRecordFields( + record, + context, + SORAFS_REPUTATION_EVENT_PAGE_FIELDS, ); - if (count !== events.length) { + if (page.count !== page.events.length) { throw new RangeError(`${context}.count must equal events.length`); } - if (count > limit) { + if (page.count > page.limit) { throw new RangeError(`${context}.count must not exceed limit`); } - const nextSince = parseSorafsReputationOptionalU64( - page.next_since, - `${context}.next_since`, - { minimum: 1n }, - ); if ( - (events.length === 0 && nextSince !== null) || - (events.length !== 0 && - (nextSince === null || - sorafsReputationU64BigInt(nextSince) !== - sorafsReputationU64BigInt(events.at(-1).sequence))) + (page.events.length === 0 && page.next_since !== null) || + (page.events.length !== 0 && + (page.next_since === null || + sorafsReputationU64BigInt(page.next_since) !== + sorafsReputationU64BigInt(page.events.at(-1).sequence))) ) { throw new TypeError( `${context}.next_since must equal the last event sequence`, ); } - let previousSequence = since === null ? 0n : sorafsReputationU64BigInt(since); - for (let index = 0; index < events.length; index += 1) { - const sequence = sorafsReputationU64BigInt(events[index].sequence); + let previousSequence = + page.since === null ? 0n : sorafsReputationU64BigInt(page.since); + for (let index = 0; index < page.events.length; index += 1) { + const sequence = sorafsReputationU64BigInt(page.events[index].sequence); if ( (index === 0 && sequence <= previousSequence) || (index > 0 && sequence !== previousSequence + 1n) @@ -30919,9 +30646,9 @@ function parseSorafsReputationEventPage(value, context, options = {}) { } previousSequence = sequence; } - for (let index = 1; index < events.length; index += 1) { - const previous = events[index - 1]; - const current = events[index]; + for (let index = 1; index < page.events.length; index += 1) { + const previous = page.events[index - 1]; + const current = page.events[index]; if (current.previous_snapshot_id_hex !== previous.snapshot_id_hex) { throw new TypeError( `${context} previous_snapshot_id_hex must link adjacent events`, @@ -30936,7 +30663,7 @@ function parseSorafsReputationEventPage(value, context, options = {}) { ); } } - return { since, limit, count, next_since: nextSince, events }; + return page; } function parseSorafsReputationSseU64(raw, context) { @@ -31060,7 +30787,7 @@ function buildSorafsPorStatusParams(options = {}) { "sorafsPorStatus.pageTokenHex", ); } - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } function buildSorafsPorExportParams(options = {}) { @@ -31085,13 +30812,13 @@ function buildSorafsPorExportParams(options = {}) { { allowZero: false }, ); } - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } function normalizeSorafsPinListResponse(payload, context = "sorafs pin list response") { const record = ensureRecord(payload ?? {}, context); const manifestsValue = record.manifests; - if (!Array.isArray(manifestsValue)) { + if (!arrayIsArray(manifestsValue)) { throw new TypeError(`${context}.manifests must be an array`); } return { @@ -31124,11 +30851,11 @@ function normalizeSorafsPinManifestResponse( ) { const record = ensureRecord(payload ?? {}, context); const aliasesValue = record.aliases; - if (!Array.isArray(aliasesValue)) { + if (!arrayIsArray(aliasesValue)) { throw new TypeError(`${context}.aliases must be an array`); } const ordersValue = record.replication_orders; - if (!Array.isArray(ordersValue)) { + if (!arrayIsArray(ordersValue)) { throw new TypeError(`${context}.replication_orders must be an array`); } return { @@ -31176,7 +30903,7 @@ function normalizeSorafsManifestRecord(payload, context) { record.status_timestamp_unix, `${context}.status_timestamp_unix`, ), - governance_refs: Array.isArray(record.governance_refs) + governance_refs: arrayIsArray(record.governance_refs) ? record.governance_refs.map((entry, index) => normalizeSorafsGovernanceReference(entry, `${context}.governance_refs[${index}]`), ) @@ -31312,7 +31039,7 @@ function normalizeSorafsAliasListResponse( ) { const record = ensureRecord(payload ?? {}, context); const aliasesValue = record.aliases; - if (!Array.isArray(aliasesValue)) { + if (!arrayIsArray(aliasesValue)) { throw new TypeError(`${context}.aliases must be an array`); } return { @@ -31417,7 +31144,7 @@ function normalizeSorafsReplicationListResponse( ) { const record = ensureRecord(payload ?? {}, context); const ordersValue = record.replication_orders; - if (!Array.isArray(ordersValue)) { + if (!arrayIsArray(ordersValue)) { throw new TypeError(`${context}.replication_orders must be an array`); } return { @@ -31447,7 +31174,7 @@ function normalizeSorafsReplicationListResponse( function normalizeSorafsReplicationOrderRecord(payload, context) { const record = ensureRecord(payload ?? {}, context); const receiptsValue = record.receipts ?? []; - if (!Array.isArray(receiptsValue)) { + if (!arrayIsArray(receiptsValue)) { throw new TypeError(`${context}.receipts must be an array`); } return { @@ -31538,7 +31265,7 @@ function normalizePipelineTransactionStatus( payload, context = "pipeline transaction status response", ) { - if (!payload || typeof payload !== "object" || Array.isArray(payload)) { + if (!payload || typeof payload !== "object" || arrayIsArray(payload)) { throw new TypeError(`${context} must be an object`); } const record = ensureRecord(payload ?? {}, context); @@ -31560,14 +31287,14 @@ function normalizePipelineTransactionStatus( kind: statusKind, content: statusRecord.content === undefined - ? Object.keys(statusCompatContent).length > 0 + ? objectKeys(statusCompatContent).length > 0 ? statusCompatContent : null : statusRecord.content, }; return { ...record, - routes: Array.isArray(record.routes) ? record.routes : [], + routes: arrayIsArray(record.routes) ? record.routes : [], kind: record.kind == null ? "Transaction" : String(record.kind), status: normalizedStatus, content: { @@ -31617,7 +31344,7 @@ function normalizePipelineTransactionStatus( }; return { ...record, - ...(Array.isArray(record.routes) ? { routes: record.routes } : {}), + ...(arrayIsArray(record.routes) ? { routes: record.routes } : {}), kind, content: normalizedContent, }; @@ -31708,7 +31435,7 @@ function classifyPipelineTransactionStatusResolution( } if (kind === "Applied") { if ( - !Number.isSafeInteger(status.block_height) || + !numberIsSafeInteger(status.block_height) || status.block_height <= 0 ) { throw createValidationError( @@ -31843,9 +31570,9 @@ function normalizePipelinePreflight(payload, context = "pipeline preflight respo `${context}.fees.successful_claim_fee_exempt_authorities`, ), }, - raw: Object.freeze({ ...record }), + raw: objectFreeze({ ...record }), }; - return Object.freeze({ + return objectFreeze({ ...normalized, isStatusStalled(status) { return isStatusQueueStalled( @@ -31867,7 +31594,7 @@ function normalizePipelineRecoverySidecar(payload, context = "pipeline recovery }); const dag = normalizePipelineDagSnapshot(record.dag, `${context}.dag`); const rawTxs = record.txs ?? []; - if (!Array.isArray(rawTxs)) { + if (!arrayIsArray(rawTxs)) { throw new TypeError(`${context}.txs must be an array`); } return { @@ -31886,7 +31613,7 @@ function normalizePipelineRecoveryFastpqProofs( ) { const record = ensureRecord(payload ?? {}, context); const rawProofs = record.proofs ?? []; - if (!Array.isArray(rawProofs)) { + if (!arrayIsArray(rawProofs)) { throw new TypeError(`${context}.proofs must be an array`); } return { @@ -31937,7 +31664,7 @@ function normalizePipelineRecoveryFastpqProof(payload, context) { record.batch_reconstruction_error, `${context}.batch_reconstruction_error`, ), - raw: Object.freeze({ ...record }), + raw: objectFreeze({ ...record }), }; } @@ -32084,7 +31811,7 @@ const SORAFS_REGISTER_FIELD_MISSING = Symbol("sorafs-register-field-missing"); function pickSorafsRegisterField(record, aliases, context) { const present = aliases.filter( (alias) => - Object.prototype.hasOwnProperty.call(record, alias) && + objectHasOwn(record, alias) && record[alias] !== undefined, ); if (present.length > 1) { @@ -32289,7 +32016,7 @@ function normalizeChunkFetchPlanV1(plan, context) { if (!isPlainObject(plan)) { throw new TypeError(`${context} must be a canonical chunk fetch plan object`); } - for (const field of Object.keys(plan)) { + for (const field of objectKeys(plan)) { if (!CHUNK_FETCH_PLAN_V1_FIELDS.has(field)) { throw new TypeError(`${context} contains unsupported field ${field}`); } @@ -32306,7 +32033,7 @@ function normalizeChunkFetchPlanV1(plan, context) { `${context}.payload_digest_blake3_hex must be a non-zero canonical lowercase 32-byte hex digest`, ); } - if (!Array.isArray(plan.chunk_fetch_specs)) { + if (!arrayIsArray(plan.chunk_fetch_specs)) { throw new TypeError(`${context}.chunk_fetch_specs must be an array`); } return plan; @@ -32470,7 +32197,7 @@ function normalizeProofSummaryOption(value, context) { normalized.sampleSeed = sampleSeed; } if (leafIndexes !== undefined) { - if (!Array.isArray(leafIndexes)) { + if (!arrayIsArray(leafIndexes)) { throw new TypeError(`${context}.leafIndexes must be an array`); } normalized.leafIndexes = leafIndexes.slice(); @@ -32576,7 +32303,7 @@ function inferChunkerHandleFromManifest(manifestJson) { } function normalizeDaGatewayProviders(value, context) { - if (!Array.isArray(value) || value.length === 0) { + if (!arrayIsArray(value) || value.length === 0) { throw new TypeError(`${context} must be a non-empty array`); } return value.map((entry, index) => { @@ -32778,10 +32505,10 @@ function normalizeDaRentQuote(payload, context = "da rent quote") { } function decodeDaDigestTuple(value, expectedLength, name) { - if (!Array.isArray(value) || value.length === 0) { + if (!arrayIsArray(value) || value.length === 0) { throw new TypeError(`${name} must be an array`); } - const bytes = Array.isArray(value[0]) ? value[0] : value; + const bytes = arrayIsArray(value[0]) ? value[0] : value; if (bytes.length !== expectedLength) { throw new TypeError(`${name} must contain ${expectedLength} entries`); } @@ -32870,7 +32597,7 @@ function normalizeIsoWeekLabel(input, name) { } function normalizePeerListResponse(payload, context = "peer list response") { - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError(`${context} must be an array`); } return payload.map((entry, index) => { @@ -32895,7 +32622,7 @@ function normalizePeerListResponse(payload, context = "peer list response") { } function normalizeTelemetryPeersInfoList(payload) { - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError("telemetry peers response must be an array"); } return payload.map((entry, index) => @@ -32925,7 +32652,7 @@ function normalizeTelemetryPeerInfo(value, context) { result.location = normalizeTelemetryPeerLocation(locationValue, `${context}.location`); } if (record.connected_peers !== undefined && record.connected_peers !== null) { - if (!Array.isArray(record.connected_peers)) { + if (!arrayIsArray(record.connected_peers)) { throw new TypeError(`${context}.connected_peers must be an array`); } result.connectedPeers = record.connected_peers.map((entry, idx) => @@ -33005,7 +32732,7 @@ function normalizeExplorerDurationMs(value, context) { } function requireFiniteNumber(value, context) { - if (typeof value !== "number" || Number.isNaN(value) || !Number.isFinite(value)) { + if (typeof value !== "number" || Number.isNaN(value) || !numberIsFinite(value)) { throw new TypeError(`${context} must be a finite number`); } return value; @@ -33013,7 +32740,7 @@ function requireFiniteNumber(value, context) { function normalizeKaigiRelaySummaryList(payload) { const record = ensureRecord(payload ?? {}, "kaigi relay summary response"); - const rawItems = Array.isArray(record.items) ? record.items : []; + const rawItems = arrayIsArray(record.items) ? record.items : []; const items = rawItems.map((entry, index) => normalizeKaigiRelaySummary(entry, `kaigi relay summary response.items[${index}]`), ); @@ -33144,7 +32871,7 @@ function normalizeKaigiRelayDomainMetrics(payload, context) { function normalizeKaigiRelayHealthSnapshot(payload) { const record = ensureRecord(payload ?? {}, "kaigi relay health snapshot"); - const rawDomains = Array.isArray(record.domains) ? record.domains : []; + const rawDomains = arrayIsArray(record.domains) ? record.domains : []; const domains = rawDomains.map((entry, index) => normalizeKaigiRelayDomainMetrics(entry, `kaigi relay health snapshot.domains[${index}]`), ); @@ -33354,7 +33081,7 @@ function normalizeKaigiCallSignal(payload, context) { function normalizeKaigiCallSignalsList(payload) { const record = ensureRecord(payload ?? {}, "kaigi call signals"); - const rawItems = Array.isArray(record.items) ? record.items : []; + const rawItems = arrayIsArray(record.items) ? record.items : []; return { total: ToriiClient._normalizeUnsignedInteger( record.total ?? rawItems.length, @@ -33498,7 +33225,7 @@ function buildKaigiRelayEventParams(options = {}) { params.relay = requireNonEmptyString(normalizedOptions.relay, "kaigiRelayEvents.relay"); } if (normalizedOptions.kind !== undefined && normalizedOptions.kind !== null) { - const values = Array.isArray(normalizedOptions.kind) + const values = arrayIsArray(normalizedOptions.kind) ? normalizedOptions.kind : String(normalizedOptions.kind) .split(",") @@ -33516,7 +33243,7 @@ function buildKaigiRelayEventParams(options = {}) { params.kind = normalized.join(","); } } - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } function buildKaigiCallSignalsQuery(options = {}) { @@ -33561,7 +33288,7 @@ function buildKaigiCallSignalsQuery(options = {}) { { allowZero: true }, ); } - return { signal, params: Object.keys(params).length === 0 ? undefined : params }; + return { signal, params: objectKeys(params).length === 0 ? undefined : params }; } function buildKaigiCallEventParams(options = {}) { @@ -33573,7 +33300,7 @@ function buildKaigiCallEventParams(options = {}) { }); const params = {}; if (normalizedOptions.kind !== undefined && normalizedOptions.kind !== null) { - const values = Array.isArray(normalizedOptions.kind) + const values = arrayIsArray(normalizedOptions.kind) ? normalizedOptions.kind : String(normalizedOptions.kind) .split(",") @@ -33591,7 +33318,7 @@ function buildKaigiCallEventParams(options = {}) { params.kind = normalized.join(","); } } - return Object.keys(params).length === 0 ? undefined : params; + return objectKeys(params).length === 0 ? undefined : params; } function buildTriggerListQuery(options = {}) { @@ -33620,7 +33347,7 @@ function buildTriggerListQuery(options = {}) { allowZero: true, }); } - return { signal, params: Object.keys(params).length === 0 ? undefined : params }; + return { signal, params: objectKeys(params).length === 0 ? undefined : params }; } function buildSubscriptionPlanListQuery(options = {}) { @@ -33661,7 +33388,7 @@ function buildSubscriptionPlanListQuery(options = {}) { { allowZero: true }, ); } - return { signal, params: Object.keys(params).length === 0 ? undefined : params }; + return { signal, params: objectKeys(params).length === 0 ? undefined : params }; } function normalizeSubscriptionStatusFilter(value, context) { @@ -33719,7 +33446,7 @@ function buildSubscriptionListQuery(options = {}) { { allowZero: true }, ); } - return { signal, params: Object.keys(params).length === 0 ? undefined : params }; + return { signal, params: objectKeys(params).length === 0 ? undefined : params }; } function normalizeAccountListResponse(payload) { @@ -33771,7 +33498,7 @@ function normalizeSignalOption(options, context) { function normalizeSignalOnlyOption(options, context) { const { signal } = normalizeSignalOption(options, context); if (options !== undefined) { - const extras = Object.keys(options).filter((key) => key !== "signal"); + const extras = objectKeys(options).filter((key) => key !== "signal"); if (extras.length > 0) { throw createValidationError( ValidationErrorCode.INVALID_OBJECT, @@ -33831,12 +33558,12 @@ function normalizeSccpSoraOutboundMaterialRoute(value, context) { message: "must be a plain object", }); const expectedFields = ["sourceProfile", "routeId", "assetKey", "revision"]; - const unknown = Object.keys(record).find((field) => !expectedFields.includes(field)); + const unknown = objectKeys(record).find((field) => !expectedFields.includes(field)); if (unknown !== undefined) { throw new TypeError(`${context} contains unknown field \`${unknown}\``); } for (const field of expectedFields) { - if (!Object.prototype.hasOwnProperty.call(record, field)) { + if (!objectHasOwn(record, field)) { throw new TypeError(`${context} is missing required field \`${field}\``); } } @@ -33849,13 +33576,13 @@ function normalizeSccpSoraOutboundMaterialRoute(value, context) { } } if ( - !Number.isSafeInteger(record.revision) || + !numberIsSafeInteger(record.revision) || record.revision < 1 || record.revision > 0xffff_ffff ) { throw new TypeError(`${context}.revision must be a nonzero uint32`); } - return Object.freeze({ + return objectFreeze({ sourceProfile: record.sourceProfile, routeId: record.routeId, assetKey: record.assetKey, @@ -33867,7 +33594,7 @@ function normalizeSccpTypedReadOptions(options, context) { const record = requirePlainObjectOption(options, `${context}.options`, { message: "must be a plain object", }); - const unknown = Object.keys(record).find((key) => key !== "format" && key !== "signal"); + const unknown = objectKeys(record).find((key) => key !== "format" && key !== "signal"); if (unknown !== undefined) { throw new TypeError(`${context}.options contains unknown field \`${unknown}\``); } @@ -33919,7 +33646,7 @@ async function readSccpNoritoResponse( } async function readBoundedSccpResponseBytes(response, maximumBodyBytes, label) { - if (!Number.isSafeInteger(maximumBodyBytes) || maximumBodyBytes < 0) { + if (!numberIsSafeInteger(maximumBodyBytes) || maximumBodyBytes < 0) { throw new TypeError(`${label} response byte-size bound is invalid`); } @@ -33936,7 +33663,7 @@ async function readBoundedSccpResponseBytes(response, maximumBodyBytes, label) { throw error; } const declaredLength = Number(rawContentLength); - if (!Number.isSafeInteger(declaredLength) || declaredLength > maximumBodyBytes) { + if (!numberIsSafeInteger(declaredLength) || declaredLength > maximumBodyBytes) { const error = new TypeError( `${label} response exceeds its ${maximumBodyBytes}-byte size bound`, ); @@ -34050,7 +33777,7 @@ function requirePlainObjectOption(value, context, { message } = {}) { } function assertSupportedOptionKeys(record, allowedKeys, context) { - const extras = Object.keys(record).filter((key) => !allowedKeys.has(key)); + const extras = objectKeys(record).filter((key) => !allowedKeys.has(key)); if (extras.length > 0) { const path = typeof context === "string" ? context.replace(/\s+/g, ".") : context; throw createValidationError( @@ -34246,7 +33973,7 @@ function normalizeProductionEventFilterBackendPayload(filter, context) { if ( filter === null || typeof filter !== "object" || - Array.isArray(filter) + arrayIsArray(filter) ) { return filter; } @@ -34254,15 +33981,15 @@ function normalizeProductionEventFilterBackendPayload(filter, context) { let normalized = filter; for (const eventKind of ["VerifyingKey", "Proof"]) { const body = filter[eventKind]; - if (body === null || typeof body !== "object" || Array.isArray(body)) { + if (body === null || typeof body !== "object" || arrayIsArray(body)) { continue; } const matcher = body.id_matcher; if ( matcher === null || typeof matcher !== "object" || - Array.isArray(matcher) || - !Object.prototype.hasOwnProperty.call(matcher, "backend") + arrayIsArray(matcher) || + !objectHasOwn(matcher, "backend") ) { continue; } @@ -34275,19 +34002,19 @@ function normalizeProductionEventFilterBackendPayload(filter, context) { backend, }; if (eventKind === "Proof") { - if (Object.prototype.hasOwnProperty.call(matcher, "hash_hex")) { + if (objectHasOwn(matcher, "hash_hex")) { normalizedMatcher.hash_hex = normalizeHex32String( matcher.hash_hex, `${context}.${eventKind}.id_matcher.hash_hex`, ); } - if (Object.prototype.hasOwnProperty.call(matcher, "proof_hash_hex")) { + if (objectHasOwn(matcher, "proof_hash_hex")) { normalizedMatcher.proof_hash_hex = normalizeHex32String( matcher.proof_hash_hex, `${context}.${eventKind}.id_matcher.proof_hash_hex`, ); } - } else if (Object.prototype.hasOwnProperty.call(matcher, "name")) { + } else if (objectHasOwn(matcher, "name")) { normalizedMatcher.name = normalizeVerifyingKeyEventMatcherName( matcher.name, `${context}.${eventKind}.id_matcher.name`, @@ -34476,7 +34203,7 @@ function normalizeRepoGovernance(value, context) { } function normalizeAttachmentMetadataList(payload, context = "attachment list response") { - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError(`${context} must be an array`); } return payload.map((entry, index) => @@ -34492,7 +34219,7 @@ function normalizeAttachmentUploadPayload(value, context) { Buffer.isBuffer(value) || ArrayBuffer.isView(value) || value instanceof ArrayBuffer || - Array.isArray(value) + arrayIsArray(value) ) { return toBuffer(value); } @@ -34611,7 +34338,7 @@ function buildVerifyingKeyListQuery(options = {}) { "listVerifyingKeys.idsOnly", ); } - return { signal, params: Object.keys(params).length === 0 ? undefined : params }; + return { signal, params: objectKeys(params).length === 0 ? undefined : params }; } function normalizeVerifyingKeyListPayload( @@ -34621,13 +34348,13 @@ function normalizeVerifyingKeyListPayload( if (payload === undefined || payload === null) { return []; } - if (Array.isArray(payload)) { + if (arrayIsArray(payload)) { return payload.map((entry, index) => normalizeVerifyingKeyListItem(entry, `${context}[${index}]`), ); } const record = ensureRecord(payload, context); - if (!Array.isArray(record.items)) { + if (!arrayIsArray(record.items)) { throw new TypeError(`${context} must be an array or { items: [] } object`); } return record.items.map((entry, index) => @@ -35088,7 +34815,7 @@ function normalizeProverReportList(payload, filters, context) { if (payload == null) { return { kind: "reports", reports: [] }; } - if (!Array.isArray(payload)) { + if (!arrayIsArray(payload)) { throw new TypeError(`${context} must be an array`); } if (payload.length === 0) { @@ -35110,7 +34837,7 @@ function normalizeProverReportList(payload, filters, context) { } if ( isPlainObject(first) && - Object.keys(first).every((key) => key === "id" || key === "error") + objectKeys(first).every((key) => key === "id" || key === "error") ) { if (!messagesOnlyRequested) { throw new Error( @@ -35188,7 +34915,7 @@ function normalizeProverReportRecord(value, context) { function normalizeSumeragiEvidenceListResponse(payload) { const record = ensureRecord(payload, "sumeragi evidence response"); const rawItems = record.items; - if (!Array.isArray(rawItems)) { + if (!arrayIsArray(rawItems)) { throw new TypeError("sumeragi evidence response.items must be an array"); } const items = rawItems.map((item, index) => @@ -35388,7 +35115,7 @@ function normalizeAssetDefinitionListItem(value, context) { } function rejectAliasField(record, context, aliasKey, canonicalKey) { - if (Object.prototype.hasOwnProperty.call(record, aliasKey)) { + if (objectHasOwn(record, aliasKey)) { throw new TypeError( `${context}.${aliasKey} is not supported; use ${canonicalKey}`, ); @@ -35717,7 +35444,7 @@ function normalizeTriggerUpsertPayload(input) { } catch { throw new TypeError("registerTrigger.action must be a valid base64 string"); } - } else if (!Array.isArray(actionValue) && typeof actionValue === "object") { + } else if (!arrayIsArray(actionValue) && typeof actionValue === "object") { payload.action = cloneJsonValue(actionValue, "registerTrigger.action"); } else { throw new TypeError( @@ -35733,7 +35460,7 @@ function normalizeTriggerUpsertPayload(input) { delete payload.metadata; } else if ( typeof payload.metadata !== "object" || - Array.isArray(payload.metadata) + arrayIsArray(payload.metadata) ) { throw new TypeError("registerTrigger.metadata must be an object when provided"); } @@ -35879,7 +35606,7 @@ function normalizeTriggerRecord(payload, context) { function normalizeTriggerListResponse(payload, context) { const record = ensureRecord(payload ?? {}, context); const rawItems = record.items ?? []; - if (!Array.isArray(rawItems)) { + if (!arrayIsArray(rawItems)) { throw new TypeError(`${context}.items must be an array`); } const items = rawItems.map((entry, index) => @@ -35958,7 +35685,7 @@ function normalizeSubscriptionActionResponse(payload, context) { function normalizeSubscriptionPlanListResponse(payload) { const record = ensureRecord(payload ?? {}, "subscription plan list response"); const rawItems = record.items ?? []; - if (!Array.isArray(rawItems)) { + if (!arrayIsArray(rawItems)) { throw new TypeError("subscription plan list response.items must be an array"); } const items = rawItems.map((entry, index) => { @@ -36002,7 +35729,7 @@ function normalizeSubscriptionPlanListResponse(payload) { function normalizeSubscriptionListResponse(payload) { const record = ensureRecord(payload ?? {}, "subscription list response"); const rawItems = record.items ?? []; - if (!Array.isArray(rawItems)) { + if (!arrayIsArray(rawItems)) { throw new TypeError("subscription list response.items must be an array"); } const items = rawItems.map((entry, index) => @@ -36171,7 +35898,7 @@ function normalizeConnectAppRecord(payload, context) { function normalizeConnectAppRegistryPage(payload) { const record = ensureRecord(payload ?? {}, "connect app registry response"); const rawItems = record.items ?? []; - if (!Array.isArray(rawItems)) { + if (!arrayIsArray(rawItems)) { throw new TypeError("connect app registry response.items must be an array"); } const items = rawItems.map((entry, index) => @@ -36346,7 +36073,7 @@ function normalizeConnectAdmissionManifest(payload, context) { const record = ensureRecord(payload ?? {}, context); const manifestRecord = isPlainObject(record.manifest) ? record.manifest : record; const rawEntries = manifestRecord.entries ?? []; - if (!Array.isArray(rawEntries)) { + if (!arrayIsArray(rawEntries)) { throw new TypeError(`${context}.entries must be an array`); } const entries = rawEntries.map((entry, index) => @@ -36439,7 +36166,7 @@ function toConnectAdmissionManifestPayload(input, context) { function normalizeConnectStatusSnapshot(payload, context) { const record = ensureRecord(payload, context); - const perIpRaw = Array.isArray(record.per_ip_sessions) ? record.per_ip_sessions : []; + const perIpRaw = arrayIsArray(record.per_ip_sessions) ? record.per_ip_sessions : []; const perIpSessions = perIpRaw.map((entry, index) => normalizeConnectPerIpSessions(entry, `${context}.per_ip_sessions[${index}]`), ); @@ -36670,7 +36397,7 @@ function buildSorafsOrderbookEventsWebSocketUrlInternal(baseUrl, options, contex endpoint.protocol = mapHttpProtocolToWebSocket(endpoint.protocol, context); endpoint.search = ""; const query = buildSorafsOrderbookEventsParams(params, context) ?? {}; - for (const [key, value] of Object.entries(query)) { + for (const [key, value] of objectEntries(query)) { endpoint.searchParams.set(key, String(value)); } return endpoint.toString(); @@ -36809,7 +36536,7 @@ function extractWebSocketMessageData(args) { args.length === 1 && first && typeof first === "object" && - Object.prototype.hasOwnProperty.call(first, "data") + objectHasOwn(first, "data") ) { return first.data; } @@ -36995,13 +36722,13 @@ function openConnectWebSocketInternal(options, context) { const finalProtocols = supportsHeaders ? protocols : attachProtocolToken(protocols, buildConnectProtocolToken(token), context); - if (Object.keys(headerContainer).length > 0) { + if (objectKeys(headerContainer).length > 0) { resolvedOptions.headers = headerContainer; } else if (!websocketOptions) { delete resolvedOptions.headers; } const shouldPassOptions = - websocketOptions !== undefined || Object.keys(headerContainer).length > 0; + websocketOptions !== undefined || objectKeys(headerContainer).length > 0; if (shouldPassOptions) { if (finalProtocols !== undefined) { return new WebSocketClass(url, finalProtocols, resolvedOptions); @@ -37061,7 +36788,7 @@ function attachProtocolToken(protocols, tokenProtocol, context) { if (typeof protocols === "string") { return protocols === tokenProtocol ? protocols : [tokenProtocol, protocols]; } - if (Array.isArray(protocols)) { + if (arrayIsArray(protocols)) { if (protocols.includes(tokenProtocol)) { return [...protocols]; } @@ -37180,7 +36907,7 @@ function identifierNormalizeUnsignedBigInt(value, context) { return value; } if (typeof value === "number") { - if (!Number.isInteger(value) || value < 0 || !Number.isSafeInteger(value)) { + if (!numberIsInteger(value) || value < 0 || !numberIsSafeInteger(value)) { throw createValidationError( ValidationErrorCode.INVALID_NUMERIC, `${context} must be a non-negative safe integer`, @@ -37414,7 +37141,7 @@ function identifierMultisigMemberPayload(member, context) { function identifierCanonicalU16(value, context) { const integer = Number(identifierNormalizeUnsignedBigInt(value, context)); - if (!Number.isInteger(integer) || integer < 0 || integer > 0xffff) { + if (!numberIsInteger(integer) || integer < 0 || integer > 0xffff) { throw createValidationError( ValidationErrorCode.VALUE_OUT_OF_RANGE, `${context} must fit in u16`, @@ -37435,7 +37162,7 @@ function identifierNoritoVec(values, encode, context) { } function identifierMultisigPolicyPayload(policy, context) { - if (!Array.isArray(policy.members) || policy.members.length === 0) { + if (!arrayIsArray(policy.members) || policy.members.length === 0) { throw new Error(`${context} multisig policy must contain at least one member`); } return Buffer.concat([ @@ -37453,7 +37180,7 @@ function identifierMultisigPolicyPayload(policy, context) { function identifierCanonicalU8(value, context) { const integer = Number(identifierNormalizeUnsignedBigInt(value, context)); - if (!Number.isInteger(integer) || integer < 0 || integer > 0xff) { + if (!numberIsInteger(integer) || integer < 0 || integer > 0xff) { throw createValidationError( ValidationErrorCode.VALUE_OUT_OF_RANGE, `${context} must fit in u8`, diff --git a/javascript/iroha_js/test/toriiClient.test.js b/javascript/iroha_js/test/toriiClient.test.js index 14c45c4b85e..a9d0da61221 100644 --- a/javascript/iroha_js/test/toriiClient.test.js +++ b/javascript/iroha_js/test/toriiClient.test.js @@ -4432,11 +4432,40 @@ test("SoraFS reputation helpers reject noncanonical V1 responses", async () => { /siblings_hex must have the exact Merkle depth/, ); + const precedenceProof = { + ...providerMismatch, + provider: provider(), + proof: { + provider_id: providerId, + leaf_index: 1, + leaf_count: 1, + siblings_hex: ["not-a-digest"], + }, + }; + await assert.rejects( + () => + responseClient(precedenceProof).getSorafsReputationProvider( + providerId, + auth, + ), + /leaf_index must be less than leaf_count/, + ); + await assert.rejects( () => responseClient(snapshot(otherSnapshotIdHex)).getSorafsReputationSnapshot( snapshotIdHex, auth, + ), + /does not match the requested snapshot/, + ); + const precedenceSnapshot = snapshot(otherSnapshotIdHex); + precedenceSnapshot.generated_at_unix = -0; + await assert.rejects( + () => + responseClient(precedenceSnapshot).getSorafsReputationSnapshot( + snapshotIdHex, + auth, ), /does not match the requested snapshot/, ); @@ -4457,6 +4486,17 @@ test("SoraFS reputation helpers reject noncanonical V1 responses", async () => { next_since: 8, events: [event], }; + const precedencePage = structuredClone(mismatchedPage); + precedencePage.events[0].version = 2; + await assert.rejects( + () => + responseClient(precedencePage).listSorafsReputationEvents({ + ...auth, + since: 7, + limit: 2, + }), + /since does not match the requested cursor/, + ); await assert.rejects( () => responseClient(mismatchedPage).listSorafsReputationEvents({ @@ -4522,6 +4562,279 @@ test("SoraFS reputation helpers reject noncanonical V1 responses", async () => { ); }); +test("SoraFS reputation validation rejects adversarial shapes, bounds, and polluted fields", async () => { + const snapshotIdHex = "ab".repeat(16); + const merkleRootHex = "cd".repeat(32); + const witness = Buffer.from("canonical-witness", "utf8").toString("base64"); + const auth = { headers: { "X-Iroha-Witness": witness } }; + const snapshot = () => ({ + snapshot_id_hex: snapshotIdHex, + generated_at_unix: 1_800_000_000, + previous_snapshot_id_hex: null, + merkle_root_hex: merkleRootHex, + provider_count: 1, + returned_provider_count: 1, + limit: 50, + truncated_providers: false, + alpha_bps: 8500, + current_score_weight_bps: 7000, + weights: { + version: 1, + por_success_bps: 2200, + pdp_success_bps: 2000, + potr_success_bps: 1800, + latency_bps: 1500, + dispute_bps: 1000, + token_violation_bps: 500, + repair_breach_bps: 1000, + }, + providers: [ + { + provider_id: "provider:alpha", + score_bps: 9800, + degradation_flags: [], + raw_metrics: { + version: 1, + por_success_bps: 9900, + pdp_success_bps: 9800, + potr_success_bps: 9700, + latency_health_bps: 9600, + dispute_rate_bps: 100, + token_violation_rate_bps: 0, + repair_breach_rate_bps: 0, + }, + raw_metrics_hash_hex: "ef".repeat(32), + }, + ], + }); + const clientForText = (textBody) => + new ToriiClient(BASE_URL, { + fetchImpl: async () => + createResponse({ + status: 200, + textBody, + headers: { "content-type": "application/json" }, + }), + }); + const rejectSnapshot = async (payload, pattern) => { + await assert.rejects( + () => + clientForText( + typeof payload === "string" ? payload : JSON.stringify(payload), + ).getSorafsReputationLatest(auth), + pattern, + ); + }; + + await rejectSnapshot([], /latest endpoint must be an object/); + + const metricsArray = snapshot(); + metricsArray.providers[0].raw_metrics = []; + await rejectSnapshot(metricsArray, /raw_metrics must be an object/); + + const flagsObject = snapshot(); + flagsObject.providers[0].degradation_flags = {}; + await rejectSnapshot(flagsObject, /degradation_flags must be an array/); + + const unsupportedFlag = snapshot(); + unsupportedFlag.providers[0].degradation_flags = [ + { flag: "attacker_defined", value: null }, + ]; + const originalIndexOf = Array.prototype.indexOf; + try { + Array.prototype.indexOf = () => 0; + await rejectSnapshot( + unsupportedFlag, + /degradation_flags\[0\]\.flag is unsupported/, + ); + } finally { + Array.prototype.indexOf = originalIndexOf; + } + + const lowScore = snapshot(); + lowScore.providers[0].score_bps = 499; + await rejectSnapshot(lowScore, /score_bps must be between 500 and 9900/); + + const highMetric = snapshot(); + highMetric.providers[0].raw_metrics.por_success_bps = 10_001; + await rejectSnapshot( + highMetric, + /raw_metrics\.por_success_bps must be between 0 and 10000/, + ); + + const wrongVersion = snapshot(); + wrongVersion.weights.version = 2; + await rejectSnapshot( + wrongVersion, + /weights\.version must be between 1 and 1/, + ); + + const negativeZero = JSON.stringify(snapshot()).replace( + '"generated_at_unix":1800000000', + '"generated_at_unix":-0', + ); + await rejectSnapshot( + negativeZero, + /generated_at_unix must be a canonical unsigned integer/, + ); + + const aboveU64 = JSON.stringify(snapshot()).replace( + '"generated_at_unix":1800000000', + '"generated_at_unix":18446744073709551616', + ); + await rejectSnapshot( + aboveU64, + /generated_at_unix must be between 1 and 18446744073709551615/, + ); + + const extraPrototypeKey = snapshot(); + Object.defineProperty(extraPrototypeKey, "__proto__", { + value: { returned_provider_count: 1 }, + enumerable: true, + }); + await rejectSnapshot( + extraPrototypeKey, + /fields are not canonical.*extra=\[__proto__\]/, + ); + + const precedence = snapshot(); + delete precedence.returned_provider_count; + precedence.alpha_bps = 1; + await rejectSnapshot( + precedence, + /fields are not canonical.*missing=\[returned_provider_count\]/, + ); + + Object.prototype.returned_provider_count = 1; + try { + const inheritedField = snapshot(); + delete inheritedField.returned_provider_count; + await rejectSnapshot( + inheritedField, + /fields are not canonical.*missing=\[returned_provider_count\]/, + ); + } finally { + delete Object.prototype.returned_provider_count; + } + + Object.prototype["X-Iroha-Witness"] = witness; + try { + await assert.rejects( + () => + clientForText(JSON.stringify(snapshot())).getSorafsReputationLatest({ + headers: {}, + }), + /requires canonicalAuth or an exact X-Iroha-Witness header/, + ); + } finally { + delete Object.prototype["X-Iroha-Witness"]; + } +}); + +test("Torii validation captures intrinsic statics against later monkey-patching", async () => { + const snapshotIdHex = "ab".repeat(16); + const snapshot = { + snapshot_id_hex: snapshotIdHex, + generated_at_unix: 1_800_000_000, + previous_snapshot_id_hex: null, + merkle_root_hex: "cd".repeat(32), + provider_count: 1, + returned_provider_count: 1, + limit: 50, + truncated_providers: false, + alpha_bps: 8500, + current_score_weight_bps: 7000, + weights: { + version: 1, + por_success_bps: 2200, + pdp_success_bps: 2000, + potr_success_bps: 1800, + latency_bps: 1500, + dispute_bps: 1000, + token_violation_bps: 500, + repair_breach_bps: 1000, + }, + providers: [ + { + provider_id: "provider:alpha", + score_bps: 9800, + degradation_flags: [], + raw_metrics: { + version: 1, + por_success_bps: 9900, + pdp_success_bps: 9800, + potr_success_bps: 9700, + latency_health_bps: 9600, + dispute_rate_bps: 100, + token_violation_rate_bps: 0, + repair_breach_rate_bps: 0, + }, + raw_metrics_hash_hex: "ef".repeat(32), + }, + ], + }; + const bodyBytes = new TextEncoder().encode(JSON.stringify(snapshot)); + const response = { + status: 200, + body: new ReadableStream({ + start(controller) { + controller.enqueue(bodyBytes); + controller.close(); + }, + }), + headers: { + get(name) { + return name.toLowerCase() === "content-type" + ? "application/json" + : null; + }, + }, + }; + const client = new ToriiClient(BASE_URL, { + fetchImpl: async () => response, + }); + const witness = Buffer.from("canonical-witness", "utf8").toString("base64"); + const originals = { + arrayIsArray: Array.isArray, + numberIsFinite: Number.isFinite, + numberIsInteger: Number.isInteger, + numberIsSafeInteger: Number.isSafeInteger, + objectEntries: Object.entries, + objectFreeze: Object.freeze, + objectGetOwnPropertyDescriptor: Object.getOwnPropertyDescriptor, + objectHasOwn: Object.hasOwn, + objectKeys: Object.keys, + }; + const poisoned = () => { + throw new Error("poisoned intrinsic must not be called"); + }; + try { + Array.isArray = poisoned; + Number.isFinite = poisoned; + Number.isInteger = poisoned; + Number.isSafeInteger = poisoned; + Object.entries = poisoned; + Object.freeze = poisoned; + Object.getOwnPropertyDescriptor = poisoned; + Object.hasOwn = poisoned; + Object.keys = poisoned; + const parsed = await client.getSorafsReputationLatest({ + headers: { "X-Iroha-Witness": witness }, + }); + assert.equal(parsed?.snapshot_id_hex, snapshotIdHex); + } finally { + Array.isArray = originals.arrayIsArray; + Number.isFinite = originals.numberIsFinite; + Number.isInteger = originals.numberIsInteger; + Number.isSafeInteger = originals.numberIsSafeInteger; + Object.entries = originals.objectEntries; + Object.freeze = originals.objectFreeze; + Object.getOwnPropertyDescriptor = originals.objectGetOwnPropertyDescriptor; + Object.hasOwn = originals.objectHasOwn; + Object.keys = originals.objectKeys; + } +}); + test("SoraFS reputation helpers validate options and identifiers before fetch", async () => { const canonicalAuth = { accountId: "reputation-reader@sora",