'use strict'; var scale = require('@pezkuwi/bizinikiwi-bindings'); var utils = require('@pezkuwi/papi-utils'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var scale__namespace = /*#__PURE__*/_interopNamespaceDefault(scale); const isBytes = (value, nBytes) => value.type === "array" && value.len === nBytes && value.value.type === "primitive" && value.value.value === "u8"; const _void = { type: "void" }; const _denormalizeLookup = (lookupData, customMap = () => null) => { const lookups = /* @__PURE__ */ new Map(); const from = /* @__PURE__ */ new Set(); const withCache = (fn) => { return (id) => { let entry = lookups.get(id); if (entry) return entry; if (from.has(id)) { const entry2 = { id }; lookups.set(id, entry2); return entry2; } from.add(id); const value = fn(id); entry = lookups.get(id); if (entry) { Object.assign(entry, value); } else { entry = { id, ...value }; lookups.set(id, entry); } from.delete(id); return entry; }; }; let isAccountId32SearchOn = true; let isAccountId20SearchOn = true; const getLookupEntryDef = withCache((id) => { const custom = customMap(lookupData[id]); if (custom) return custom; const { def, path, params } = lookupData[id]; if (def.tag === "composite") { if (def.value.length === 0) return _void; if (def.value.length === 1) { const inner = getLookupEntryDef(def.value[0].type); if (isAccountId32SearchOn && path.at(-1) === "AccountId32" && isBytes(inner, 32)) { isAccountId32SearchOn = false; return { type: "AccountId32" }; } if (isAccountId20SearchOn && path.at(-1) === "AccountId20" && isBytes(inner, 20)) { isAccountId20SearchOn = false; return { type: "AccountId20" }; } return inner; } return getComplexVar(def.value); } if (def.tag === "variant") { if (path.length === 1 && path[0] === "Option" && params.length === 1 && params[0].name === "T") { const value = getLookupEntryDef(params[0].type); return value.type === "void" ? ( // Option would return a Codec which makes no sense // Therefore, we better treat it as a bool { type: "primitive", value: "bool" } ) : { type: "option", value }; } if (path.length === 1 && path[0] === "Result" && params.length === 2 && params[0].name === "T" && params[1].name === "E") { return { type: "result", value: { ok: getLookupEntryDef(params[0].type), ko: getLookupEntryDef(params[1].type) } }; } if (def.value.length === 0) return _void; const enumValue = {}; const enumDocs = {}; def.value.forEach((x) => { const key = x.name; enumDocs[key] = x.docs; if (x.fields.length === 0) { enumValue[key] = { ..._void, idx: x.index }; return; } if (x.fields.length === 1 && !x.fields[0].name) { enumValue[key] = { type: "lookupEntry", value: getLookupEntryDef(x.fields[0].type), idx: x.index }; return; } enumValue[key] = { ...getComplexVar(x.fields), idx: x.index }; }); return { type: "enum", value: enumValue, innerDocs: enumDocs }; } if (def.tag === "sequence") return { type: "sequence", value: getLookupEntryDef(def.value) }; if (def.tag === "array") { const { len } = def.value; const value = getLookupEntryDef(def.value.type); return !len || value.type === "void" ? _void : len > 1 ? { type: "array", value, len: def.value.len } : value; } if (def.tag === "tuple") { if (def.value.length === 0) return _void; return def.value.length > 1 ? getArrayOrTuple( def.value.map((x) => getLookupEntryDef(x)), def.value.map((x) => lookupData[x].docs) ) : getLookupEntryDef(def.value[0]); } if (def.tag === "primitive") { return { type: "primitive", value: def.value.tag }; } if (def.tag === "compact") { const translated = getLookupEntryDef(def.value); if (translated.type === "void") return _void; const isBig = Number(translated.value.slice(1)) > 32; return { type: "compact", isBig, size: translated.value }; } return { type: def.tag, isLSB: (lookupData[def.value.bitOrderType].path.at(-1) ?? "LSB").toUpperCase().startsWith("LSB") }; }); const getComplexVar = (input) => { let allKey = true; const values = {}; const innerDocs = {}; input.forEach((x, idx) => { allKey = allKey && !!x.name; const key = x.name || idx; const value = getLookupEntryDef(x.type); if (value.type !== "void") { values[key] = value; innerDocs[key] = x.docs; } }); return allKey ? { type: "struct", value: values, innerDocs } : getArrayOrTuple(Object.values(values), Object.values(innerDocs)); }; const getArrayOrTuple = (values, innerDocs) => { if (values.every((v) => v.id === values[0].id) && innerDocs.every((doc) => !doc.length)) { const [value] = values; return value.type === "void" ? _void : { type: "array", value: values[0], len: values.length }; } return { type: "tuple", value: values, innerDocs }; }; return getLookupEntryDef; }; const denormalizeLookup = (lookupData) => _denormalizeLookup(lookupData); const getLookupFn = (metadata) => { const getLookupEntryDef = _denormalizeLookup(metadata.lookup, ({ def }) => { if (def.tag === "composite") { const moduleErrorLength = getModuleErrorLength(def); if (moduleErrorLength) { return { type: "enum", innerDocs: {}, value: Object.fromEntries( metadata.pallets.map((p) => [ p.name, p.errors == null ? { ..._void, idx: p.index } : { type: "lookupEntry", value: getLookupEntryDef(p.errors.type), idx: p.index } ]) ), byteLength: moduleErrorLength }; } } return null; }); function getModuleErrorLength(def) { const preChecks = def.value.length === 2 && def.value[0].name === "index" && def.value[1].name === "error"; if (!preChecks) return null; const index = getLookupEntryDef(def.value[0].type); const error = getLookupEntryDef(def.value[1].type); return index.type === "primitive" && index.value === "u8" && error.type === "array" && error.value.type === "primitive" && error.value.value === "u8" ? 1 + error.len : null; } const getCall = () => { if ("call" in metadata.extrinsic) { return metadata.extrinsic.call; } const extrinsic = metadata.lookup[metadata.extrinsic.type]; const call = extrinsic?.params.find((p) => p.name === "Call"); return call?.type ?? null; }; return Object.assign(getLookupEntryDef, { metadata, call: getCall() }); }; const withCache = (fn, onEnterCircular, onExitCircular) => (input, cache, stack, ...rest) => { const { id } = input; if (cache.has(id)) return cache.get(id); if (stack.has(id)) { const res = onEnterCircular(() => cache.get(id), input, ...rest); cache.set(id, res); return res; } stack.add(id); let result = fn(input, cache, stack, ...rest); stack.delete(id); if (cache.has(id)) result = onExitCircular(result, cache.get(id), input, ...rest); cache.set(id, result); return result; }; const _bytes = scale__namespace.Bin(); const _buildCodec = (input, cache, stack, _accountId) => { if (input.type === "primitive") return scale__namespace[input.value]; if (input.type === "void") return scale__namespace._void; if (input.type === "AccountId32") return _accountId; if (input.type === "AccountId20") return scale__namespace.ethAccount; if (input.type === "compact") return input.isBig ? scale__namespace.compactBn : scale__namespace.compactNumber; if (input.type === "bitSequence") return scale__namespace.BitSeq(input.isLSB); const buildNextCodec = (nextInput) => buildCodec(nextInput, cache, stack, _accountId); const buildVector = (inner2, len) => { const innerCodec = buildNextCodec(inner2); return len ? scale__namespace.Vector(innerCodec, len) : scale__namespace.Vector(innerCodec); }; const buildTuple = (value) => scale__namespace.Tuple(...value.map(buildNextCodec)); const buildStruct = (value) => { const inner2 = Object.fromEntries( Object.entries(value).map(([key, value2]) => [key, buildNextCodec(value2)]) ); return scale__namespace.Struct(inner2); }; if (input.type === "sequence" && input.value.type === "primitive" && input.value.value === "u8") { return _bytes; } if (input.type === "array") { if (input.value.type === "primitive" && input.value.value === "u8") return scale__namespace.Bin(input.len); return buildVector(input.value, input.len); } if (input.type === "sequence") return buildVector(input.value); if (input.type === "tuple") return buildTuple(input.value); if (input.type === "struct") return buildStruct(input.value); if (input.type === "option") return scale__namespace.Option(buildNextCodec(input.value)); if (input.type === "result") return scale__namespace.Result( buildNextCodec(input.value.ok), buildNextCodec(input.value.ko) ); const dependencies = Object.values(input.value).map((v) => { switch (v.type) { case "void": return scale__namespace._void; case "lookupEntry": return buildNextCodec(v.value); case "tuple": return buildTuple(v.value); case "struct": return buildStruct(v.value); case "array": return buildVector(v.value, v.len); } }); const inner = Object.fromEntries( Object.keys(input.value).map((key, idx) => { return [key, dependencies[idx]]; }) ); const indexes = Object.values(input.value).map((x) => x.idx); const areIndexesSorted = indexes.every((idx, i) => idx === i); const variantCodec = areIndexesSorted ? scale__namespace.Variant(inner) : scale__namespace.Variant(inner, indexes); return input.byteLength ? fixedSizeCodec(variantCodec, input.byteLength) : variantCodec; }; const buildCodec = withCache(_buildCodec, scale__namespace.Self, (res) => res); const getLookupCodecBuilder = (lookup, accountId = scale__namespace.AccountId()) => { const cache = /* @__PURE__ */ new Map(); const buildDefinition = (id) => buildCodec(lookup(id), cache, /* @__PURE__ */ new Set(), accountId); return (id) => buildDefinition(id); }; const fixedSizeCodec = (codec, size) => { const allBytes = scale__namespace.Bytes(size); return scale__namespace.createCodec( (value) => allBytes.enc(codec.enc(value)), (data) => codec.dec(allBytes.dec(data)) ); }; const nullCodec = scale__namespace.enhanceCodec( scale__namespace._void, () => void 0, () => null ); const getDynamicBuilder = (getLookupEntryDef) => { const { metadata } = getLookupEntryDef; let buildDefinition = getLookupCodecBuilder(getLookupEntryDef); const prefix = metadata.pallets.find((x) => x.name === "System")?.constants.find((x) => x.name === "SS58Prefix"); let ss58Prefix; if (prefix) { try { const prefixVal = buildDefinition(prefix.type).dec(prefix.value); if (typeof prefixVal === "number") { ss58Prefix = prefixVal; buildDefinition = getLookupCodecBuilder( getLookupEntryDef, scale__namespace.AccountId(prefixVal) ); } } catch (_) { } } const storagePallets = /* @__PURE__ */ new Map(); const buildStorage = (pallet, entry) => { let storagePallet = storagePallets.get(pallet); if (!storagePallet) storagePallets.set(pallet, storagePallet = scale__namespace.Storage(pallet)); const storageEntry = metadata.pallets.find((x) => x.name === pallet).storage.items.find((s) => s.name === entry); const withNullVoid = (codec) => codec === scale__namespace._void ? nullCodec : codec; const storageWithFallback = (len, value2, ...args) => { const keys = storagePallet(...args); const [, ...encodersWithHash] = args; return { args: scale__namespace.Tuple(...encodersWithHash.map(([codec]) => codec)), keys, value: value2, len, fallback: storageEntry.modifier === 1 ? value2.dec(storageEntry.fallback) : void 0 }; }; if (storageEntry.type.tag === "plain") return storageWithFallback( 0, withNullVoid(buildDefinition(storageEntry.type.value)), entry ); const { key, value, hashers } = storageEntry.type.value; const val = withNullVoid(buildDefinition(value)); const hashes = hashers.map((x) => scale__namespace[x.tag]); const hashArgs = (() => { if (hashes.length === 1) { return [[buildDefinition(key), hashes[0]]]; } const keyDef = getLookupEntryDef(key); switch (keyDef.type) { case "array": return hashes.map((hash) => [buildDefinition(keyDef.value.id), hash]); case "tuple": return keyDef.value.map((x, idx) => [ buildDefinition(x.id), hashes[idx] ]); default: throw new Error("Invalid key type"); } })(); return storageWithFallback(hashes.length, val, entry, ...hashArgs); }; const buildEnumEntry = (entry) => { switch (entry.type) { case "void": return scale__namespace._void; case "lookupEntry": return buildDefinition(entry.value.id); case "tuple": return scale__namespace.Tuple( ...Object.values(entry.value).map((l) => buildDefinition(l.id)) ); case "struct": return scale__namespace.Struct( utils.mapObject(entry.value, (x) => buildDefinition(x.id)) ); case "array": return scale__namespace.Vector(buildDefinition(entry.value.id), entry.len); } }; const buildConstant = (pallet, constantName) => { const storageEntry = metadata.pallets.find((x) => x.name === pallet).constants.find((s) => s.name === constantName); return buildDefinition(storageEntry.type); }; const buildVariant = (type) => (pallet, name) => { const palletEntry = metadata.pallets.find((x) => x.name === pallet); const lookup = getLookupEntryDef(palletEntry[type].type); if (lookup.type !== "enum") throw null; const entry = lookup.value[name]; return { location: [palletEntry.index, entry.idx], codec: buildEnumEntry(lookup.value[name]) }; }; const buildViewFn = (pallet, entry) => { const fn = metadata.pallets.find((x) => x.name === pallet)?.viewFns.find((x) => x.name === entry); if (!fn) throw null; return { args: scale__namespace.Tuple(...fn.inputs.map((x) => buildDefinition(x.type))), value: buildDefinition(fn.output) }; }; const buildRuntimeCall = (api, method) => { const entry = metadata.apis.find((x) => x.name === api)?.methods.find((x) => x.name === method); if (!entry) throw null; return { args: scale__namespace.Tuple(...entry.inputs.map((x) => buildDefinition(x.type))), value: buildDefinition(entry.output) }; }; return { buildDefinition, buildStorage, buildEvent: buildVariant("events"), buildError: buildVariant("errors"), buildViewFn, buildRuntimeCall, buildCall: buildVariant("calls"), buildConstant, ss58Prefix }; }; function buildLookupGraph(lookupFn, lookupLength) { const result = /* @__PURE__ */ new Map(); const visited = /* @__PURE__ */ new Set(); const addEdge = (from, to) => { if (!result.has(from)) result.set(from, { entry: lookupFn(from), backRefs: /* @__PURE__ */ new Set(), refs: /* @__PURE__ */ new Set() }); if (!result.has(to)) result.set(to, { entry: lookupFn(to), backRefs: /* @__PURE__ */ new Set(), refs: /* @__PURE__ */ new Set() }); result.get(from).refs.add(to); result.get(to).backRefs.add(from); }; for (let i = 0; i < lookupLength; i++) { const entry = lookupFn(i); if (i !== entry.id) { addEdge(i, entry.id); } if (visited.has(entry.id)) continue; visited.add(entry.id); switch (entry.type) { case "array": case "option": case "sequence": addEdge(entry.id, entry.value.id); break; case "enum": Object.values(entry.value).forEach((enumEntry) => { switch (enumEntry.type) { case "array": case "lookupEntry": addEdge(entry.id, enumEntry.value.id); break; case "struct": case "tuple": Object.values(enumEntry.value).forEach( (v) => addEdge(entry.id, v.id) ); break; } }); break; case "result": addEdge(entry.id, entry.value.ok.id); addEdge(entry.id, entry.value.ko.id); break; case "struct": case "tuple": Object.values(entry.value).forEach((v) => addEdge(entry.id, v.id)); break; } if (!result.has(entry.id)) { result.set(entry.id, { backRefs: /* @__PURE__ */ new Set(), refs: /* @__PURE__ */ new Set(), entry }); } } return result; } const subgraphCache = /* @__PURE__ */ new WeakMap(); function _getSubgraph(id, graph, result, cache) { if (result.has(id)) return; const node = graph.get(id); result.set(id, node); cache.set(id, result); node.refs.forEach((ref) => _getSubgraph(ref, graph, result, cache)); node.backRefs.forEach((ref) => _getSubgraph(ref, graph, result, cache)); } function getSubgraph(id, graph) { if (!subgraphCache.has(graph)) { subgraphCache.set(graph, /* @__PURE__ */ new Map()); } const cache = subgraphCache.get(graph); if (cache.has(id)) return cache.get(id); const result = /* @__PURE__ */ new Map(); _getSubgraph(id, graph, result, cache); return result; } function getStronglyConnectedComponents(graph) { const tarjanState = /* @__PURE__ */ new Map(); let index = 0; const stack = []; const result = []; function strongConnect(v) { const state = { index, lowLink: index, onStack: true }; tarjanState.set(v, state); index++; stack.push(v); const edges = graph.get(v).refs; for (let w of edges) { const edgeState = tarjanState.get(w); if (!edgeState) { strongConnect(w); state.lowLink = Math.min(state.lowLink, tarjanState.get(w).lowLink); } else if (edgeState.onStack) { state.lowLink = Math.min(state.lowLink, edgeState.index); } } if (state.lowLink === state.index) { const component = /* @__PURE__ */ new Set(); let poppedNode = -1; do { poppedNode = stack.pop(); tarjanState.get(poppedNode).onStack = false; component.add(poppedNode); } while (poppedNode !== v); result.push(component); } } for (const node of graph.keys()) { if (!tarjanState.has(node)) { strongConnect(node); } } return result; } function mergeSCCsWithCommonNodes(stronglyConnectedComponents) { const scc = stronglyConnectedComponents; const ungroupedCycles = new Set(scc.map((_, i) => i)); const edges = new Map(scc.map((_, i) => [i, /* @__PURE__ */ new Set()])); scc.forEach((cycle, i) => { scc.slice(i + 1).forEach((otherCycle, _j) => { const j = _j + i + 1; const combined = /* @__PURE__ */ new Set([...cycle, ...otherCycle]); if (combined.size !== cycle.size + otherCycle.size) { edges.get(i).add(j); edges.get(j).add(i); } }); }); const groups = []; while (ungroupedCycles.size) { const group = /* @__PURE__ */ new Set(); const toVisit = [ungroupedCycles.values().next().value]; while (toVisit.length) { const idx = toVisit.pop(); if (!ungroupedCycles.has(idx)) continue; ungroupedCycles.delete(idx); const cycle = scc[idx]; cycle.forEach((v) => group.add(Number(v))); edges.get(idx).forEach((n) => toVisit.push(n)); } groups.push(group); } return groups; } const textEncoder = new TextEncoder(); const encodeText = textEncoder.encode.bind(textEncoder); const getChecksum = (values) => { const res = new Uint8Array(values.length * 8); const dv = new DataView(res.buffer); for (let i = 0; i < values.length; i++) dv.setBigUint64(i * 8, values[i]); return scale.h64(res); }; const getStringChecksum = (values) => getChecksum(values.map((v) => scale.h64(encodeText(v)))); const shapeIds = { primitive: 0n, vector: 1n, tuple: 2n, struct: 3n, option: 4n, result: 5n, enum: 6n, void: 7n }; const runtimePrimitiveIds = { undefined: 0n, number: 1n, string: 2n, bigint: 3n, boolean: 4n, bitSequence: 5n, // {bitsLen: number, bytes: Uint8Array} byteSequence: 6n, // Binary accountId32: 7n, // SS58String accountId20: 8n // EthAccount }; const metadataPrimitiveIds = { bool: runtimePrimitiveIds.boolean, char: runtimePrimitiveIds.string, str: runtimePrimitiveIds.string, u8: runtimePrimitiveIds.number, u16: runtimePrimitiveIds.number, u32: runtimePrimitiveIds.number, u64: runtimePrimitiveIds.bigint, u128: runtimePrimitiveIds.bigint, u256: runtimePrimitiveIds.bigint, i8: runtimePrimitiveIds.number, i16: runtimePrimitiveIds.number, i32: runtimePrimitiveIds.number, i64: runtimePrimitiveIds.bigint, i128: runtimePrimitiveIds.bigint, i256: runtimePrimitiveIds.bigint }; const structLikeBuilder = (shapeId, input, innerChecksum) => { const sortedEntries = Object.entries(input).sort( ([a], [b]) => a.localeCompare(b) ); const keysChecksum = getStringChecksum(sortedEntries.map(([key]) => key)); const valuesChecksum = getChecksum( sortedEntries.map(([, entry]) => innerChecksum(entry)) ); return getChecksum([shapeId, keysChecksum, valuesChecksum]); }; const _buildChecksum = (input, buildNextChecksum) => { if (input.type === "primitive") return getChecksum([shapeIds.primitive, metadataPrimitiveIds[input.value]]); if (input.type === "void") return getChecksum([shapeIds.void]); if (input.type === "compact") return getChecksum([ shapeIds.primitive, runtimePrimitiveIds[input.isBig ? "bigint" : "number"] ]); if (input.type === "bitSequence") return getChecksum([shapeIds.primitive, runtimePrimitiveIds.bitSequence]); if (input.type === "AccountId32") { return getChecksum([shapeIds.primitive, runtimePrimitiveIds.accountId32]); } if (input.type === "AccountId20") { return getChecksum([shapeIds.primitive, runtimePrimitiveIds.accountId20]); } const buildVector = (entry, length) => { const innerChecksum = buildNextChecksum(entry); return getChecksum( length !== void 0 ? [shapeIds.vector, innerChecksum, BigInt(length)] : [shapeIds.vector, innerChecksum] ); }; if (input.type === "array") { const innerValue = input.value; if (innerValue.type === "primitive" && innerValue.value === "u8") { return getChecksum([ shapeIds.primitive, runtimePrimitiveIds.byteSequence, BigInt(input.len) ]); } return buildVector(innerValue, input.len); } if (input.type === "sequence") { const innerValue = input.value; if (innerValue.type === "primitive" && innerValue.value === "u8") { return getChecksum([shapeIds.primitive, runtimePrimitiveIds.byteSequence]); } return buildVector(innerValue); } const buildTuple = (entries) => getChecksum([shapeIds.tuple, ...entries.map(buildNextChecksum)]); const buildStruct = (entries) => structLikeBuilder(shapeIds.struct, entries, buildNextChecksum); if (input.type === "tuple") return buildTuple(input.value); if (input.type === "struct") return buildStruct(input.value); if (input.type === "option") return getChecksum([shapeIds.option, buildNextChecksum(input.value)]); if (input.type === "result") return getChecksum([ shapeIds.result, buildNextChecksum(input.value.ok), buildNextChecksum(input.value.ko) ]); return structLikeBuilder(shapeIds.enum, input.value, (entry) => { if (entry.type === "lookupEntry") return buildNextChecksum(entry.value); switch (entry.type) { case "void": return getChecksum([shapeIds.void]); case "tuple": return buildTuple(entry.value); case "struct": return buildStruct(entry.value); case "array": return buildVector(entry.value, entry.len); } }); }; const sortCyclicGroups = (groups, graph) => { const getReachableNodes = (group) => { const result2 = /* @__PURE__ */ new Set(); const toVisit = Array.from(group); while (toVisit.length) { const id = toVisit.pop(); if (result2.has(id)) continue; result2.add(id); graph.get(id)?.refs.forEach((id2) => toVisit.push(id2)); } return Array.from(result2); }; const result = new Array(); function dependentsFirst(group) { if (result.includes(group)) return; const dependents = groups.filter( (candidate) => candidate !== group && getReachableNodes(group).some((node) => candidate.has(node)) ); dependents.forEach((group2) => dependentsFirst(group2)); if (result.includes(group)) return; result.push(group); } groups.forEach((group) => dependentsFirst(group)); return result; }; function iterateChecksums(group, iterations, cache, graph) { const groupReadCache = new Map([...group].map((id) => [id, 0n])); const groupWriteCache = /* @__PURE__ */ new Map(); const recursiveBuildChecksum = (entry, skipCache = true) => { if (!skipCache && (groupReadCache.has(entry.id) || cache.has(entry.id))) { return groupReadCache.get(entry.id) ?? cache.get(entry.id); } const result = _buildChecksum( entry, (nextEntry) => recursiveBuildChecksum(nextEntry, false) ); if (group.has(entry.id)) { groupWriteCache.set(entry.id, result); } else { cache.set(entry.id, result); } return result; }; for (let i = 0; i < iterations; i++) { group.forEach((id) => recursiveBuildChecksum(graph.get(id).entry)); group.forEach((id) => groupReadCache.set(id, groupWriteCache.get(id))); } return groupReadCache; } function getMirroredNodes(cyclicGroups, graph) { const maxSize = cyclicGroups.reduce( (acc, group) => Math.max(acc, group.size), 0 ); const allEntries = new Set([...graph.values()].map((v) => v.entry.id)); const resultingChecksums = iterateChecksums( allEntries, maxSize, // Cache won't be used, since it's using the internal one for every node. /* @__PURE__ */ new Map(), graph ); const checksumToNodes = /* @__PURE__ */ new Map(); for (const id of allEntries) { const checksum = resultingChecksums.get(id); if (checksum == void 0) throw new Error("Unreachable"); if (!checksumToNodes.has(checksum)) { checksumToNodes.set(checksum, []); } checksumToNodes.get(checksum).push(id); } const checksumsWithDuplicates = [...checksumToNodes.entries()].filter( ([, nodes]) => nodes.length > 1 ); const duplicatesMap = {}; checksumsWithDuplicates.forEach(([, nodes]) => { nodes.forEach((n) => duplicatesMap[n] = nodes); }); return duplicatesMap; } const buildChecksum = (entry, cache, graph) => { if (cache.has(entry.id)) return cache.get(entry.id); const subGraph = getSubgraph(entry.id, graph); const cycles = getStronglyConnectedComponents(subGraph).filter( // SCCs can be of length=1, but for those we're only interested with those that are circular with themselves (group) => group.size > 1 || isSelfCircular(group, subGraph) ); const cyclicGroups = mergeSCCsWithCommonNodes(cycles).filter((group) => { return !cache.has(group.values().next().value); }); const mirrored = getMirroredNodes(cyclicGroups, subGraph); const sortedCyclicGroups = sortCyclicGroups(cyclicGroups, subGraph); sortedCyclicGroups.forEach((group) => { if (cache.has(group.values().next().value)) { return; } const result = iterateChecksums(group, group.size, cache, graph); group.forEach((id) => { const checksum = result.get(id); if (id in mirrored) { mirrored[id].forEach((id2) => cache.set(id2, checksum)); } else { cache.set(id, checksum); } }); }); const getChecksum2 = (entry2) => { if (cache.has(entry2.id)) return cache.get(entry2.id); return _buildChecksum(entry2, getChecksum2); }; return getChecksum2(entry); }; const isSelfCircular = (group, graph) => { if (group.size !== 1) return false; const [id] = group; return graph.get(id).refs.has(id); }; const getChecksumBuilder = (getLookupEntryDef) => { const { metadata } = getLookupEntryDef; const graph = buildLookupGraph(getLookupEntryDef, metadata.lookup.length); const cache = /* @__PURE__ */ new Map(); const buildDefinition = (id) => buildChecksum(getLookupEntryDef(id), cache, graph); const buildStorage = (pallet, entry) => { try { const storageEntry = metadata.pallets.find((x) => x.name === pallet).storage.items.find((s) => s.name === entry); if (storageEntry.type.tag === "plain") return buildDefinition(storageEntry.type.value); const { key, value } = storageEntry.type.value; const val = buildDefinition(value); const returnKey = buildDefinition(key); return getChecksum([val, returnKey]); } catch (_) { return null; } }; const buildViewFns = (pallet, entry) => { try { const viewFn = metadata.pallets.find((x) => x.name === pallet)?.viewFns.find((x) => x.name === entry); if (!viewFn) throw null; const argNamesChecksum = getStringChecksum( viewFn.inputs.map((x) => x.name) ); const argValuesChecksum = getChecksum( viewFn.inputs.map((x) => buildDefinition(x.type)) ); const outputChecksum = buildDefinition(viewFn.output); return getChecksum([argNamesChecksum, argValuesChecksum, outputChecksum]); } catch (_) { return null; } }; const buildRuntimeCall = (api, method) => { try { const entry = metadata.apis.find((x) => x.name === api)?.methods.find((x) => x.name === method); if (!entry) throw null; const argNamesChecksum = getStringChecksum( entry.inputs.map((x) => x.name) ); const argValuesChecksum = getChecksum( entry.inputs.map((x) => buildDefinition(x.type)) ); const outputChecksum = buildDefinition(entry.output); return getChecksum([argNamesChecksum, argValuesChecksum, outputChecksum]); } catch (_) { return null; } }; const buildComposite = (input) => { if (input.type === "void") return getChecksum([0n]); if (input.type === "tuple") { const values = Object.values(input.value).map( (entry) => buildDefinition(entry.id) ); return getChecksum([shapeIds.tuple, ...values]); } if (input.type === "array") { return getChecksum([ shapeIds.vector, buildDefinition(input.value.id), BigInt(input.len) ]); } return structLikeBuilder( shapeIds.struct, input.value, (entry) => buildDefinition(entry.id) ); }; const buildNamedTuple = (input) => { return structLikeBuilder( shapeIds.tuple, input.value, (entry) => buildDefinition(entry.id) ); }; const variantShapeId = { errors: 1n, events: 2n, calls: 3n }; const buildVariant = (variantType) => (pallet, name) => { try { const palletEntry = metadata.pallets.find((x) => x.name === pallet); const enumLookup = getLookupEntryDef(palletEntry[variantType].type); buildDefinition(enumLookup.id); if (enumLookup.type !== "enum") throw null; const entry = enumLookup.value[name]; const valueChecksum = entry.type === "lookupEntry" ? buildDefinition(entry.value.id) : buildComposite(entry); return getChecksum([variantShapeId[variantType], valueChecksum]); } catch (_) { return null; } }; const buildConstant = (pallet, constantName) => { try { const storageEntry = metadata.pallets.find((x) => x.name === pallet).constants.find((s) => s.name === constantName); return buildDefinition(storageEntry.type); } catch (_) { return null; } }; const toStringEnhancer = (fn) => (...args) => fn(...args)?.toString(32) ?? null; return { buildDefinition: toStringEnhancer(buildDefinition), buildRuntimeCall: toStringEnhancer(buildRuntimeCall), buildStorage: toStringEnhancer(buildStorage), buildViewFns: toStringEnhancer(buildViewFns), buildCall: toStringEnhancer(buildVariant("calls")), buildEvent: toStringEnhancer(buildVariant("events")), buildError: toStringEnhancer(buildVariant("errors")), buildConstant: toStringEnhancer(buildConstant), buildComposite: toStringEnhancer(buildComposite), buildNamedTuple: toStringEnhancer(buildNamedTuple), getAllGeneratedChecksums: () => Array.from(cache.values()).map((v) => v.toString(32)) }; }; exports.denormalizeLookup = denormalizeLookup; exports.getChecksumBuilder = getChecksumBuilder; exports.getDynamicBuilder = getDynamicBuilder; exports.getLookupCodecBuilder = getLookupCodecBuilder; exports.getLookupFn = getLookupFn; //# sourceMappingURL=index.js.map