@polkadot-api/metadata-builders 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as scale from '@polkadot-api/substrate-bindings';
2
- import { StringRecord, V15, Codec } from '@polkadot-api/substrate-bindings';
2
+ import { StringRecord, V14, V15, Codec } from '@polkadot-api/substrate-bindings';
3
3
 
4
4
  type MetadataPrimitives = "bool" | "char" | "str" | "u8" | "u16" | "u32" | "u64" | "u128" | "u256" | "i8" | "i16" | "i32" | "i64" | "i128" | "i256";
5
5
  type PrimitiveVar = {
@@ -38,7 +38,7 @@ type EnumVar = {
38
38
  value: StringRecord<({
39
39
  type: "lookupEntry";
40
40
  value: LookupEntry;
41
- } | VoidVar | TupleVar | StructVar) & {
41
+ } | VoidVar | TupleVar | StructVar | ArrayVar) & {
42
42
  idx: number;
43
43
  }>;
44
44
  innerDocs: StringRecord<string[]>;
@@ -169,7 +169,7 @@ declare const getLookupFn: (lookupData: {
169
169
  docs: string[];
170
170
  }[]) => (id: number) => LookupEntry;
171
171
 
172
- declare const getDynamicBuilder: (metadata: V15) => {
172
+ declare const getDynamicBuilder: (metadata: V14 | V15) => {
173
173
  buildDefinition: (id: number) => Codec<any>;
174
174
  buildStorage: (pallet: string, entry: string) => {
175
175
  len: number;
@@ -207,7 +207,7 @@ declare const getDynamicBuilder: (metadata: V15) => {
207
207
  ss58Prefix: number | undefined;
208
208
  };
209
209
 
210
- declare const getChecksumBuilder: (metadata: V15) => {
210
+ declare const getChecksumBuilder: (metadata: V14 | V15) => {
211
211
  buildDefinition: (id: number) => string | null;
212
212
  buildRuntimeCall: (api: string, method: string) => string | null;
213
213
  buildStorage: (pallet: string, entry: string) => string | null;
@@ -215,7 +215,7 @@ declare const getChecksumBuilder: (metadata: V15) => {
215
215
  buildEvent: (pallet: string, name: string) => string | null;
216
216
  buildError: (pallet: string, name: string) => string | null;
217
217
  buildConstant: (pallet: string, constantName: string) => string | null;
218
- buildComposite: (input: VoidVar | TupleVar | StructVar) => string | null;
218
+ buildComposite: (input: VoidVar | TupleVar | StructVar | ArrayVar) => string | null;
219
219
  buildNamedTuple: (input: StructVar) => string | null;
220
220
  getAllGeneratedChecksums: () => string[];
221
221
  };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as scale from '@polkadot-api/substrate-bindings';
2
- import { StringRecord, V15, Codec } from '@polkadot-api/substrate-bindings';
2
+ import { StringRecord, V14, V15, Codec } from '@polkadot-api/substrate-bindings';
3
3
 
4
4
  type MetadataPrimitives = "bool" | "char" | "str" | "u8" | "u16" | "u32" | "u64" | "u128" | "u256" | "i8" | "i16" | "i32" | "i64" | "i128" | "i256";
5
5
  type PrimitiveVar = {
@@ -38,7 +38,7 @@ type EnumVar = {
38
38
  value: StringRecord<({
39
39
  type: "lookupEntry";
40
40
  value: LookupEntry;
41
- } | VoidVar | TupleVar | StructVar) & {
41
+ } | VoidVar | TupleVar | StructVar | ArrayVar) & {
42
42
  idx: number;
43
43
  }>;
44
44
  innerDocs: StringRecord<string[]>;
@@ -169,7 +169,7 @@ declare const getLookupFn: (lookupData: {
169
169
  docs: string[];
170
170
  }[]) => (id: number) => LookupEntry;
171
171
 
172
- declare const getDynamicBuilder: (metadata: V15) => {
172
+ declare const getDynamicBuilder: (metadata: V14 | V15) => {
173
173
  buildDefinition: (id: number) => Codec<any>;
174
174
  buildStorage: (pallet: string, entry: string) => {
175
175
  len: number;
@@ -207,7 +207,7 @@ declare const getDynamicBuilder: (metadata: V15) => {
207
207
  ss58Prefix: number | undefined;
208
208
  };
209
209
 
210
- declare const getChecksumBuilder: (metadata: V15) => {
210
+ declare const getChecksumBuilder: (metadata: V14 | V15) => {
211
211
  buildDefinition: (id: number) => string | null;
212
212
  buildRuntimeCall: (api: string, method: string) => string | null;
213
213
  buildStorage: (pallet: string, entry: string) => string | null;
@@ -215,7 +215,7 @@ declare const getChecksumBuilder: (metadata: V15) => {
215
215
  buildEvent: (pallet: string, name: string) => string | null;
216
216
  buildError: (pallet: string, name: string) => string | null;
217
217
  buildConstant: (pallet: string, constantName: string) => string | null;
218
- buildComposite: (input: VoidVar | TupleVar | StructVar) => string | null;
218
+ buildComposite: (input: VoidVar | TupleVar | StructVar | ArrayVar) => string | null;
219
219
  buildNamedTuple: (input: StructVar) => string | null;
220
220
  getAllGeneratedChecksums: () => string[];
221
221
  };
package/dist/index.js CHANGED
@@ -156,17 +156,29 @@ var getLookupFn = (lookupData) => {
156
156
  values[key2] = getLookupEntryDef(x2.type);
157
157
  innerDocs[key2] = x2.docs;
158
158
  });
159
- enumValue[key] = allKey ? {
160
- type: "struct",
161
- value: values,
162
- innerDocs,
163
- idx: x.index
164
- } : {
165
- type: "tuple",
166
- value: Object.values(values),
167
- innerDocs: Object.values(innerDocs),
168
- idx: x.index
169
- };
159
+ if (allKey) {
160
+ enumValue[key] = {
161
+ type: "struct",
162
+ value: values,
163
+ innerDocs,
164
+ idx: x.index
165
+ };
166
+ } else {
167
+ const valuesArr = Object.values(values);
168
+ const innerDocsArr = Object.values(innerDocs);
169
+ const areAllSame = valuesArr.every((v) => v.id === valuesArr[0].id);
170
+ enumValue[key] = areAllSame && innerDocsArr.every((doc) => doc.length === 0) ? {
171
+ type: "array",
172
+ value: valuesArr[0],
173
+ len: valuesArr.length,
174
+ idx: x.index
175
+ } : {
176
+ type: "tuple",
177
+ value: valuesArr,
178
+ innerDocs: innerDocsArr,
179
+ idx: x.index
180
+ };
181
+ }
170
182
  });
171
183
  return {
172
184
  type: "enum",
@@ -310,11 +322,18 @@ var _buildCodec = (input, cache, stack, _accountId) => {
310
322
  buildNextCodec(input.value.ko)
311
323
  );
312
324
  const dependencies = Object.values(input.value).map((v) => {
313
- if (v.type === "void")
314
- return scale._void;
315
- if (v.type === "lookupEntry")
316
- return buildNextCodec(v.value);
317
- return v.type === "tuple" ? buildTuple(v.value) : buildStruct(v.value);
325
+ switch (v.type) {
326
+ case "void":
327
+ return scale._void;
328
+ case "lookupEntry":
329
+ return buildNextCodec(v.value);
330
+ case "tuple":
331
+ return buildTuple(v.value);
332
+ case "struct":
333
+ return buildStruct(v.value);
334
+ case "array":
335
+ return buildVector(v.value, v.len);
336
+ }
318
337
  });
319
338
  const inner = Object.fromEntries(
320
339
  Object.keys(input.value).map((key, idx) => {
@@ -376,15 +395,22 @@ var getDynamicBuilder = (metadata) => {
376
395
  return storageWithFallback(hashes.length, entry, val.dec, ...hashArgs);
377
396
  };
378
397
  const buildEnumEntry = (entry) => {
379
- if (entry.type === "void")
380
- return scale._void;
381
- if (entry.type === "lookupEntry")
382
- return buildDefinition(entry.value.id);
383
- return entry.type === "tuple" ? scale.Tuple(
384
- ...Object.values(entry.value).map((l) => buildDefinition(l.id))
385
- ) : scale.Struct(
386
- (0, import_utils.mapObject)(entry.value, (x) => buildDefinition(x.id))
387
- );
398
+ switch (entry.type) {
399
+ case "void":
400
+ return scale._void;
401
+ case "lookupEntry":
402
+ return buildDefinition(entry.value.id);
403
+ case "tuple":
404
+ return scale.Tuple(
405
+ ...Object.values(entry.value).map((l) => buildDefinition(l.id))
406
+ );
407
+ case "struct":
408
+ return scale.Struct(
409
+ (0, import_utils.mapObject)(entry.value, (x) => buildDefinition(x.id))
410
+ );
411
+ case "array":
412
+ return scale.Vector(buildDefinition(entry.value.id), entry.len);
413
+ }
388
414
  };
389
415
  const buildConstant = (pallet, constantName) => {
390
416
  const storageEntry = metadata.pallets.find((x) => x.name === pallet).constants.find((s) => s.name === constantName);
@@ -424,6 +450,173 @@ var getDynamicBuilder = (metadata) => {
424
450
 
425
451
  // src/checksum-builder.ts
426
452
  var import_substrate_bindings = require("@polkadot-api/substrate-bindings");
453
+
454
+ // src/lookup-graph.ts
455
+ function buildLookupGraph(lookupFn, lookupLength) {
456
+ const result = /* @__PURE__ */ new Map();
457
+ const visited = /* @__PURE__ */ new Set();
458
+ const addEdge = (from, to) => {
459
+ if (!result.has(from))
460
+ result.set(from, {
461
+ entry: lookupFn(from),
462
+ backRefs: /* @__PURE__ */ new Set(),
463
+ refs: /* @__PURE__ */ new Set()
464
+ });
465
+ if (!result.has(to))
466
+ result.set(to, {
467
+ entry: lookupFn(to),
468
+ backRefs: /* @__PURE__ */ new Set(),
469
+ refs: /* @__PURE__ */ new Set()
470
+ });
471
+ result.get(from).refs.add(to);
472
+ result.get(to).backRefs.add(from);
473
+ };
474
+ for (let i = 0; i < lookupLength; i++) {
475
+ const entry = lookupFn(i);
476
+ if (i !== entry.id) {
477
+ addEdge(i, entry.id);
478
+ }
479
+ if (visited.has(entry.id))
480
+ continue;
481
+ visited.add(entry.id);
482
+ switch (entry.type) {
483
+ case "array":
484
+ case "option":
485
+ case "sequence":
486
+ addEdge(entry.id, entry.value.id);
487
+ break;
488
+ case "enum":
489
+ Object.values(entry.value).forEach((enumEntry) => {
490
+ switch (enumEntry.type) {
491
+ case "array":
492
+ case "lookupEntry":
493
+ addEdge(entry.id, enumEntry.value.id);
494
+ break;
495
+ case "struct":
496
+ case "tuple":
497
+ Object.values(enumEntry.value).forEach(
498
+ (v) => addEdge(entry.id, v.id)
499
+ );
500
+ break;
501
+ }
502
+ });
503
+ break;
504
+ case "result":
505
+ addEdge(entry.id, entry.value.ok.id);
506
+ addEdge(entry.id, entry.value.ko.id);
507
+ break;
508
+ case "struct":
509
+ case "tuple":
510
+ Object.values(entry.value).forEach((v) => addEdge(entry.id, v.id));
511
+ break;
512
+ }
513
+ if (!result.has(entry.id)) {
514
+ result.set(entry.id, {
515
+ backRefs: /* @__PURE__ */ new Set(),
516
+ refs: /* @__PURE__ */ new Set(),
517
+ entry
518
+ });
519
+ }
520
+ }
521
+ return result;
522
+ }
523
+ var subgraphCache = /* @__PURE__ */ new WeakMap();
524
+ function _getSubgraph(id, graph, result, cache) {
525
+ if (result.has(id))
526
+ return;
527
+ const node = graph.get(id);
528
+ result.set(id, node);
529
+ cache.set(id, result);
530
+ node.refs.forEach((ref) => _getSubgraph(ref, graph, result, cache));
531
+ node.backRefs.forEach((ref) => _getSubgraph(ref, graph, result, cache));
532
+ }
533
+ function getSubgraph(id, graph) {
534
+ if (!subgraphCache.has(graph)) {
535
+ subgraphCache.set(graph, /* @__PURE__ */ new Map());
536
+ }
537
+ const cache = subgraphCache.get(graph);
538
+ if (cache.has(id))
539
+ return cache.get(id);
540
+ const result = /* @__PURE__ */ new Map();
541
+ _getSubgraph(id, graph, result, cache);
542
+ return result;
543
+ }
544
+ function getStronglyConnectedComponents(graph) {
545
+ const tarjanState = /* @__PURE__ */ new Map();
546
+ let index = 0;
547
+ const stack = [];
548
+ const result = [];
549
+ function strongConnect(v) {
550
+ const state = {
551
+ index,
552
+ lowLink: index,
553
+ onStack: true
554
+ };
555
+ tarjanState.set(v, state);
556
+ index++;
557
+ stack.push(v);
558
+ const edges = graph.get(v).refs;
559
+ for (let w of edges) {
560
+ const edgeState = tarjanState.get(w);
561
+ if (!edgeState) {
562
+ strongConnect(w);
563
+ state.lowLink = Math.min(state.lowLink, tarjanState.get(w).lowLink);
564
+ } else if (edgeState.onStack) {
565
+ state.lowLink = Math.min(state.lowLink, edgeState.index);
566
+ }
567
+ }
568
+ if (state.lowLink === state.index) {
569
+ const component = /* @__PURE__ */ new Set();
570
+ let poppedNode = -1;
571
+ do {
572
+ poppedNode = stack.pop();
573
+ tarjanState.get(poppedNode).onStack = false;
574
+ component.add(poppedNode);
575
+ } while (poppedNode !== v);
576
+ if (component.size > 1)
577
+ result.push(component);
578
+ }
579
+ }
580
+ for (const node of graph.keys()) {
581
+ if (!tarjanState.has(node)) {
582
+ strongConnect(node);
583
+ }
584
+ }
585
+ return result;
586
+ }
587
+ function mergeSCCsWithCommonNodes(stronglyConnectedComponents) {
588
+ const scc = stronglyConnectedComponents;
589
+ const ungroupedCycles = new Set(scc.map((_, i) => i));
590
+ const edges = new Map(scc.map((_, i) => [i, /* @__PURE__ */ new Set()]));
591
+ scc.forEach((cycle, i) => {
592
+ scc.slice(i + 1).forEach((otherCycle, _j) => {
593
+ const j = _j + i + 1;
594
+ const combined = /* @__PURE__ */ new Set([...cycle, ...otherCycle]);
595
+ if (combined.size !== cycle.size + otherCycle.size) {
596
+ edges.get(i).add(j);
597
+ edges.get(j).add(i);
598
+ }
599
+ });
600
+ });
601
+ const groups = [];
602
+ while (ungroupedCycles.size) {
603
+ const group = /* @__PURE__ */ new Set();
604
+ const toVisit = [ungroupedCycles.values().next().value];
605
+ while (toVisit.length) {
606
+ const idx = toVisit.pop();
607
+ if (!ungroupedCycles.has(idx))
608
+ continue;
609
+ ungroupedCycles.delete(idx);
610
+ const cycle = scc[idx];
611
+ cycle.forEach((v) => group.add(Number(v)));
612
+ edges.get(idx).forEach((n) => toVisit.push(n));
613
+ }
614
+ groups.push(group);
615
+ }
616
+ return groups;
617
+ }
618
+
619
+ // src/checksum-builder.ts
427
620
  var textEncoder = new TextEncoder();
428
621
  var encodeText = textEncoder.encode.bind(textEncoder);
429
622
  var getChecksum = (values) => {
@@ -486,56 +679,6 @@ var structLikeBuilder = (shapeId, input, innerChecksum) => {
486
679
  );
487
680
  return getChecksum([shapeId, keysChecksum, valuesChecksum]);
488
681
  };
489
- var buildGraph = (entry, result = /* @__PURE__ */ new Map()) => {
490
- if (result.has(entry.id))
491
- return result;
492
- switch (entry.type) {
493
- case "array":
494
- case "option":
495
- case "sequence":
496
- result.set(entry.id, [entry, /* @__PURE__ */ new Set([entry.value.id])]);
497
- buildGraph(entry.value, result);
498
- break;
499
- case "enum": {
500
- const children = Object.values(entry.value).flatMap((value) => {
501
- if (value.type === "void")
502
- return [];
503
- if (value.type === "lookupEntry")
504
- return value.value;
505
- if (value.type === "struct")
506
- return Object.values(value.value);
507
- return value.value;
508
- });
509
- result.set(entry.id, [entry, new Set(children.map((child) => child.id))]);
510
- children.forEach((child) => buildGraph(child, result));
511
- break;
512
- }
513
- case "result":
514
- result.set(entry.id, [
515
- entry,
516
- /* @__PURE__ */ new Set([entry.value.ok.id, entry.value.ko.id])
517
- ]);
518
- buildGraph(entry.value.ok, result);
519
- buildGraph(entry.value.ko, result);
520
- break;
521
- case "struct": {
522
- const children = Object.values(entry.value);
523
- result.set(entry.id, [entry, new Set(children.map((child) => child.id))]);
524
- children.forEach((child) => buildGraph(child, result));
525
- break;
526
- }
527
- case "tuple":
528
- result.set(entry.id, [
529
- entry,
530
- new Set(entry.value.map((child) => child.id))
531
- ]);
532
- entry.value.forEach((child) => buildGraph(child, result));
533
- break;
534
- default:
535
- result.set(entry.id, [entry, /* @__PURE__ */ new Set()]);
536
- }
537
- return result;
538
- };
539
682
  var _buildChecksum = (input, buildNextChecksum) => {
540
683
  if (input.type === "primitive")
541
684
  return getChecksum([shapeIds.primitive, metadataPrimitiveIds[input.value]]);
@@ -554,6 +697,12 @@ var _buildChecksum = (input, buildNextChecksum) => {
554
697
  if (input.type === "AccountId20") {
555
698
  return getChecksum([shapeIds.primitive, runtimePrimitiveIds.accountId20]);
556
699
  }
700
+ const buildVector = (entry, length) => {
701
+ const innerChecksum = buildNextChecksum(entry);
702
+ return getChecksum(
703
+ length !== void 0 ? [shapeIds.vector, innerChecksum, BigInt(length)] : [shapeIds.vector, innerChecksum]
704
+ );
705
+ };
557
706
  if (input.type === "array") {
558
707
  const innerValue = input.value;
559
708
  if (innerValue.type === "primitive" && innerValue.value === "u8") {
@@ -563,16 +712,14 @@ var _buildChecksum = (input, buildNextChecksum) => {
563
712
  BigInt(input.len)
564
713
  ]);
565
714
  }
566
- const innerChecksum = buildNextChecksum(innerValue);
567
- return getChecksum([shapeIds.vector, innerChecksum, BigInt(input.len)]);
715
+ return buildVector(innerValue, input.len);
568
716
  }
569
717
  if (input.type === "sequence") {
570
718
  const innerValue = input.value;
571
719
  if (innerValue.type === "primitive" && innerValue.value === "u8") {
572
720
  return getChecksum([shapeIds.primitive, runtimePrimitiveIds.byteSequence]);
573
721
  }
574
- const innerChecksum = buildNextChecksum(innerValue);
575
- return getChecksum([shapeIds.vector, innerChecksum]);
722
+ return buildVector(innerValue);
576
723
  }
577
724
  const buildTuple = (entries) => getChecksum([shapeIds.tuple, ...entries.map(buildNextChecksum)]);
578
725
  const buildStruct = (entries) => structLikeBuilder(shapeIds.struct, entries, buildNextChecksum);
@@ -598,87 +745,23 @@ var _buildChecksum = (input, buildNextChecksum) => {
598
745
  return buildTuple(entry.value);
599
746
  case "struct":
600
747
  return buildStruct(entry.value);
748
+ case "array":
749
+ return buildVector(entry.value, entry.len);
601
750
  }
602
751
  });
603
752
  };
604
- var getCycles = (graph) => {
605
- const tarjanState = /* @__PURE__ */ new Map();
606
- let index = 0;
607
- const stack = [];
608
- const result = [];
609
- function strongConnect(v) {
610
- const state = {
611
- index,
612
- lowLink: index,
613
- onStack: true
614
- };
615
- tarjanState.set(v, state);
616
- index++;
617
- stack.push(v);
618
- const edges = graph.get(v)[1];
619
- for (let w of edges) {
620
- const edgeState = tarjanState.get(w);
621
- if (!edgeState) {
622
- strongConnect(w);
623
- state.lowLink = Math.min(state.lowLink, tarjanState.get(w).lowLink);
624
- } else if (edgeState.onStack) {
625
- state.lowLink = Math.min(state.lowLink, edgeState.index);
626
- }
627
- }
628
- if (state.lowLink === state.index) {
629
- const component = /* @__PURE__ */ new Set();
630
- let poppedNode = -1;
631
- do {
632
- poppedNode = stack.pop();
633
- tarjanState.get(poppedNode).onStack = false;
634
- component.add(poppedNode);
635
- } while (poppedNode !== v);
636
- if (component.size > 1)
637
- result.push(component);
638
- }
639
- }
640
- for (const node of graph.keys()) {
641
- if (!tarjanState.has(node)) {
642
- strongConnect(node);
643
- }
644
- }
645
- return result;
646
- };
647
- var getCyclicGroups = (cycles) => {
648
- const ungroupedCycles = new Set(cycles.map((_, i) => i));
649
- const edges = new Map(cycles.map((_, i) => [i, /* @__PURE__ */ new Set()]));
650
- cycles.forEach((cycle, i) => {
651
- cycles.slice(i + 1).forEach((otherCycle, _j) => {
652
- const j = _j + i + 1;
653
- const combined = /* @__PURE__ */ new Set([...cycle, ...otherCycle]);
654
- if (combined.size !== cycle.size + otherCycle.size) {
655
- edges.get(i).add(j);
656
- edges.get(j).add(i);
657
- }
658
- });
659
- });
660
- const groups = [];
661
- while (ungroupedCycles.size) {
662
- const group = /* @__PURE__ */ new Set();
663
- const toVisit = [ungroupedCycles.values().next().value];
753
+ var sortCyclicGroups = (groups, graph) => {
754
+ const getReachableNodes = (group) => {
755
+ const result2 = /* @__PURE__ */ new Set();
756
+ const toVisit = Array.from(group);
664
757
  while (toVisit.length) {
665
- const idx = toVisit.pop();
666
- if (!ungroupedCycles.has(idx))
758
+ const id = toVisit.pop();
759
+ if (result2.has(id))
667
760
  continue;
668
- ungroupedCycles.delete(idx);
669
- const cycle = cycles[idx];
670
- cycle.forEach((v) => group.add(Number(v)));
671
- edges.get(idx).forEach((n) => toVisit.push(n));
761
+ result2.add(id);
762
+ graph.get(id)?.refs.forEach((id2) => toVisit.push(id2));
672
763
  }
673
- groups.push(group);
674
- }
675
- return groups;
676
- };
677
- var sortCyclicGroups = (groups, graph) => {
678
- const getReachableNodes = (group) => {
679
- const first = group.values().next().value;
680
- const entry = graph.get(first)[0];
681
- return Array.from(buildGraph(entry).keys());
764
+ return Array.from(result2);
682
765
  };
683
766
  const result = new Array();
684
767
  function dependentsFirst(group) {
@@ -695,50 +778,102 @@ var sortCyclicGroups = (groups, graph) => {
695
778
  groups.forEach((group) => dependentsFirst(group));
696
779
  return result;
697
780
  };
698
- var buildChecksum = (entry, cache) => {
699
- if (cache.has(entry.id))
700
- return cache.get(entry.id);
701
- const graph = buildGraph(entry);
702
- const cycles = getCycles(graph);
703
- const cyclicGroups = getCyclicGroups(cycles);
704
- const sortedCyclicGroups = sortCyclicGroups(cyclicGroups, graph);
705
- const recursiveBuildChecksum = (entry2, writeCache, skipCache = false) => {
706
- if (!skipCache && cache.has(entry2.id)) {
707
- return cache.get(entry2.id);
781
+ function iterateChecksums(group, iterations, cache, graph) {
782
+ const groupReadCache = new Map([...group].map((id) => [id, 0n]));
783
+ const groupWriteCache = /* @__PURE__ */ new Map();
784
+ const recursiveBuildChecksum = (entry, skipCache = true) => {
785
+ if (!skipCache && (groupReadCache.has(entry.id) || cache.has(entry.id))) {
786
+ return groupReadCache.get(entry.id) ?? cache.get(entry.id);
708
787
  }
709
788
  const result = _buildChecksum(
710
- entry2,
711
- (nextEntry) => recursiveBuildChecksum(nextEntry, writeCache)
789
+ entry,
790
+ (nextEntry) => recursiveBuildChecksum(nextEntry, false)
712
791
  );
713
- writeCache(entry2.id, result);
792
+ if (group.has(entry.id)) {
793
+ groupWriteCache.set(entry.id, result);
794
+ } else {
795
+ cache.set(entry.id, result);
796
+ }
714
797
  return result;
715
798
  };
799
+ for (let i = 0; i < iterations; i++) {
800
+ group.forEach((id) => recursiveBuildChecksum(graph.get(id).entry));
801
+ group.forEach((id) => groupReadCache.set(id, groupWriteCache.get(id)));
802
+ }
803
+ return groupReadCache;
804
+ }
805
+ function getMirroredNodes(cyclicGroups, graph) {
806
+ const maxSize = cyclicGroups.reduce(
807
+ (acc, group) => Math.max(acc, group.size),
808
+ 0
809
+ );
810
+ const allEntries = new Set([...graph.values()].map((v) => v.entry.id));
811
+ const resultingChecksums = iterateChecksums(
812
+ allEntries,
813
+ maxSize,
814
+ // Cache won't be used, since it's using the internal one for every node.
815
+ /* @__PURE__ */ new Map(),
816
+ graph
817
+ );
818
+ const checksumToNodes = /* @__PURE__ */ new Map();
819
+ for (const id of allEntries) {
820
+ const checksum = resultingChecksums.get(id);
821
+ if (checksum == void 0)
822
+ throw new Error("Unreachable");
823
+ if (!checksumToNodes.has(checksum)) {
824
+ checksumToNodes.set(checksum, []);
825
+ }
826
+ checksumToNodes.get(checksum).push(id);
827
+ }
828
+ const checksumsWithDuplicates = [...checksumToNodes.entries()].filter(
829
+ ([, nodes]) => nodes.length > 1
830
+ );
831
+ const duplicatesMap = {};
832
+ checksumsWithDuplicates.forEach(([, nodes]) => {
833
+ nodes.forEach((n) => duplicatesMap[n] = nodes);
834
+ });
835
+ return duplicatesMap;
836
+ }
837
+ var buildChecksum = (entry, cache, graph) => {
838
+ if (cache.has(entry.id))
839
+ return cache.get(entry.id);
840
+ const subGraph = getSubgraph(entry.id, graph);
841
+ const cycles = getStronglyConnectedComponents(subGraph);
842
+ const cyclicGroups = mergeSCCsWithCommonNodes(cycles).filter((group) => {
843
+ return !cache.has(group.values().next().value);
844
+ });
845
+ const mirrored = getMirroredNodes(cyclicGroups, subGraph);
846
+ const sortedCyclicGroups = sortCyclicGroups(
847
+ cyclicGroups.filter((group) => group.size > 1),
848
+ subGraph
849
+ );
716
850
  sortedCyclicGroups.forEach((group) => {
717
- group.forEach((id) => cache.set(id, 0n));
718
- for (let i = 0; i < group.size; i++) {
719
- const results = /* @__PURE__ */ new Map();
720
- group.forEach(
721
- (id) => recursiveBuildChecksum(
722
- graph.get(id)[0],
723
- (id2, value) => {
724
- const writeCache = group.has(id2) ? results : cache;
725
- writeCache.set(id2, value);
726
- },
727
- true
728
- )
729
- );
730
- Array.from(results.entries()).forEach(
731
- ([id, checksum]) => cache.set(id, checksum)
732
- );
851
+ if (cache.has(group.values().next().value)) {
852
+ return;
733
853
  }
854
+ const result = iterateChecksums(group, group.size, cache, graph);
855
+ group.forEach((id) => {
856
+ const checksum = result.get(id);
857
+ if (id in mirrored) {
858
+ mirrored[id].forEach((id2) => cache.set(id2, checksum));
859
+ } else {
860
+ cache.set(id, checksum);
861
+ }
862
+ });
734
863
  });
735
- return recursiveBuildChecksum(entry, (id, value) => cache.set(id, value));
864
+ const getChecksum2 = (entry2) => {
865
+ if (cache.has(entry2.id))
866
+ return cache.get(entry2.id);
867
+ return _buildChecksum(entry2, getChecksum2);
868
+ };
869
+ return getChecksum2(entry);
736
870
  };
737
871
  var getChecksumBuilder = (metadata) => {
738
872
  const lookupData = metadata.lookup;
739
873
  const getLookupEntryDef = getLookupFn(lookupData);
874
+ const graph = buildLookupGraph(getLookupEntryDef, lookupData.length);
740
875
  const cache = /* @__PURE__ */ new Map();
741
- const buildDefinition = (id) => buildChecksum(getLookupEntryDef(id), cache);
876
+ const buildDefinition = (id) => buildChecksum(getLookupEntryDef(id), cache, graph);
742
877
  const buildStorage = (pallet, entry) => {
743
878
  try {
744
879
  const storageEntry = metadata.pallets.find((x) => x.name === pallet).storage.items.find((s) => s.name === entry);
@@ -778,6 +913,13 @@ var getChecksumBuilder = (metadata) => {
778
913
  );
779
914
  return getChecksum([shapeIds.tuple, ...values]);
780
915
  }
916
+ if (input.type === "array") {
917
+ return getChecksum([
918
+ shapeIds.vector,
919
+ buildDefinition(input.value.id),
920
+ BigInt(input.len)
921
+ ]);
922
+ }
781
923
  return structLikeBuilder(
782
924
  shapeIds.struct,
783
925
  input.value,