@thru/programs 0.2.22 → 0.2.23

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.
Files changed (32) hide show
  1. package/dist/multicall/index.cjs +2579 -0
  2. package/dist/multicall/index.cjs.map +1 -0
  3. package/dist/multicall/index.d.cts +253 -0
  4. package/dist/multicall/index.d.ts +253 -0
  5. package/dist/multicall/index.js +2573 -0
  6. package/dist/multicall/index.js.map +1 -0
  7. package/dist/passkey-manager/index.cjs +582 -706
  8. package/dist/passkey-manager/index.cjs.map +1 -1
  9. package/dist/passkey-manager/index.d.cts +20 -14
  10. package/dist/passkey-manager/index.d.ts +20 -14
  11. package/dist/passkey-manager/index.js +551 -673
  12. package/dist/passkey-manager/index.js.map +1 -1
  13. package/package.json +7 -2
  14. package/src/multicall/abi/thru/common/primitives/types.ts +2265 -0
  15. package/src/multicall/abi/thru/program/multicall/types.ts +1232 -0
  16. package/src/multicall/index.test.ts +46 -0
  17. package/src/multicall/index.ts +81 -0
  18. package/src/passkey-manager/abi/thru/blockchain/state_proof/types.ts +95 -19
  19. package/src/passkey-manager/abi/thru/common/primitives/types.ts +111 -37
  20. package/src/passkey-manager/abi/thru/program/passkey_manager/types.ts +248 -660
  21. package/src/passkey-manager/challenge.ts +52 -12
  22. package/src/passkey-manager/constants.ts +0 -1
  23. package/src/passkey-manager/index.ts +4 -4
  24. package/src/passkey-manager/instructions/add-authority.ts +8 -2
  25. package/src/passkey-manager/instructions/remove-authority.ts +9 -2
  26. package/src/passkey-manager/instructions/validate.ts +60 -14
  27. package/src/passkey-manager/target-instruction.ts +29 -0
  28. package/src/passkey-manager/types.ts +16 -0
  29. package/src/passkey-manager/validate.test.ts +173 -0
  30. package/tsup.config.ts +1 -0
  31. package/src/passkey-manager/instructions/invoke.ts +0 -25
  32. package/src/passkey-manager/instructions/shared.ts +0 -12
@@ -0,0 +1,46 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import {
3
+ MULTICALL_PROGRAM_ADDRESS,
4
+ MULTICALL_PROGRAM_PUBKEY,
5
+ InstructionDataBuilder,
6
+ MulticallArgs,
7
+ buildMulticallInstruction,
8
+ } from './index';
9
+
10
+ function instructionData(programIdx: number, data: Uint8Array): number[] {
11
+ const builder = new InstructionDataBuilder();
12
+ builder.set_program_idx(programIdx);
13
+ builder.data().write(data).finish();
14
+ return Array.from(builder.build());
15
+ }
16
+
17
+ describe('multicall helpers', () => {
18
+ it('encodes calls with generated InstructionData views', () => {
19
+ expect(MULTICALL_PROGRAM_ADDRESS).toBe(
20
+ 'taAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJ'
21
+ );
22
+ expect(MULTICALL_PROGRAM_PUBKEY[31]).toBe(9);
23
+
24
+ const encoded = buildMulticallInstruction([
25
+ { programIdx: 2, instructionData: new Uint8Array([0xaa]) },
26
+ { programIdx: 5, instructionData: new Uint8Array([0xbb, 0xcc]) },
27
+ ]);
28
+
29
+ expect(encoded).toEqual(
30
+ new Uint8Array([
31
+ 0x02, 0x00,
32
+ ...instructionData(2, new Uint8Array([0xaa])),
33
+ ...instructionData(5, new Uint8Array([0xbb, 0xcc])),
34
+ ])
35
+ );
36
+
37
+ const validation = MulticallArgs.validate(encoded);
38
+ expect(validation).toMatchObject({ ok: true, consumed: encoded.length });
39
+
40
+ const view = MulticallArgs.from_array(encoded);
41
+ expect(view?.get_calls_count()).toBe(2);
42
+ const calls = view?.get_calls();
43
+ expect(calls?.map((call) => call.get_program_idx())).toEqual([2, 5]);
44
+ expect(calls?.map((call) => call.get_data())).toEqual([[0xaa], [0xbb, 0xcc]]);
45
+ });
46
+ });
@@ -0,0 +1,81 @@
1
+ import { encodeAddress } from '@thru/sdk/helpers';
2
+ import {
3
+ InstructionData,
4
+ InstructionDataBuilder,
5
+ } from './abi/thru/common/primitives/types';
6
+ import { MulticallArgs } from './abi/thru/program/multicall/types';
7
+
8
+ export {
9
+ InstructionData,
10
+ InstructionDataBuilder,
11
+ } from './abi/thru/common/primitives/types';
12
+ export {
13
+ MulticallArgs,
14
+ MulticallError,
15
+ } from './abi/thru/program/multicall/types';
16
+
17
+ export type MulticallCall = {
18
+ programIdx: number;
19
+ instructionData: Uint8Array;
20
+ };
21
+
22
+ export const MULTICALL_PROGRAM_PUBKEY = new Uint8Array([
23
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
24
+ ]);
25
+
26
+ export const MULTICALL_PROGRAM_ADDRESS = encodeAddress(MULTICALL_PROGRAM_PUBKEY);
27
+
28
+ function writeU16LE(target: Uint8Array, offset: number, value: number): void {
29
+ target[offset] = value & 0xff;
30
+ target[offset + 1] = (value >> 8) & 0xff;
31
+ }
32
+
33
+ function assertProgramIdx(programIdx: number): void {
34
+ if (!Number.isInteger(programIdx) || programIdx < 0 || programIdx > 0xffff) {
35
+ throw new Error('programIdx must be 0-65535');
36
+ }
37
+ }
38
+
39
+ function buildInstructionData(call: MulticallCall): Uint8Array {
40
+ assertProgramIdx(call.programIdx);
41
+ if (!(call.instructionData instanceof Uint8Array)) {
42
+ throw new Error('instructionData must be a Uint8Array');
43
+ }
44
+
45
+ const builder = new InstructionDataBuilder();
46
+ builder.set_program_idx(call.programIdx);
47
+ builder.data().write(call.instructionData).finish();
48
+ const buffer = builder.build();
49
+ const view = InstructionData.from_array(buffer);
50
+ if (!view) {
51
+ throw new Error('generated InstructionData failed validation');
52
+ }
53
+ return buffer;
54
+ }
55
+
56
+ export function buildMulticallInstruction(calls: MulticallCall[]): Uint8Array {
57
+ if (!Array.isArray(calls)) throw new Error('calls must be an array');
58
+ if (calls.length > 0xffff) throw new Error('calls length must be 0-65535');
59
+
60
+ const encodedCalls = calls.map(buildInstructionData);
61
+ const totalLength = 2 + encodedCalls.reduce((sum, call) => sum + call.length, 0);
62
+
63
+ const output = new Uint8Array(totalLength);
64
+ let offset = 0;
65
+ writeU16LE(output, offset, calls.length);
66
+ offset += 2;
67
+
68
+ for (const call of encodedCalls) {
69
+ output.set(call, offset);
70
+ offset += call.length;
71
+ }
72
+
73
+ const validation = MulticallArgs.validate(output);
74
+ if (!validation.ok || validation.consumed !== output.length) {
75
+ throw new Error(
76
+ `generated MulticallArgs failed validation (code=${validation.code ?? 'unknown'})`
77
+ );
78
+ }
79
+
80
+ return output;
81
+ }
@@ -32,6 +32,12 @@ type __TnIrNode =
32
32
  readonly op: "call";
33
33
  readonly typeName: string;
34
34
  readonly args: readonly { readonly name: string; readonly source: string }[];
35
+ }
36
+ | {
37
+ readonly op: "sumOverArray";
38
+ readonly count: __TnIrNode;
39
+ readonly elementTypeName: string;
40
+ readonly fieldName: string;
35
41
  };
36
42
 
37
43
  type __TnIrContext = {
@@ -517,6 +523,10 @@ const __tnValidateRegistry: Record<
517
523
  string,
518
524
  (buffer: Uint8Array, params: Record<string, bigint>) => __TnValidateResult
519
525
  > = {};
526
+ const __tnDynamicValidateRegistry: Record<
527
+ string,
528
+ (buffer: Uint8Array) => __TnValidateResult
529
+ > = {};
520
530
 
521
531
  function __tnRegisterFootprint(
522
532
  typeName: string,
@@ -532,6 +542,13 @@ function __tnRegisterValidate(
532
542
  __tnValidateRegistry[typeName] = fn;
533
543
  }
534
544
 
545
+ function __tnRegisterDynamicValidate(
546
+ typeName: string,
547
+ fn: (buffer: Uint8Array) => __TnValidateResult
548
+ ): void {
549
+ __tnDynamicValidateRegistry[typeName] = fn;
550
+ }
551
+
535
552
  function __tnInvokeFootprint(
536
553
  typeName: string,
537
554
  params: Record<string, bigint>
@@ -551,8 +568,17 @@ function __tnInvokeValidate(
551
568
  return fn(buffer, params);
552
569
  }
553
570
 
571
+ function __tnInvokeDynamicValidate(
572
+ typeName: string,
573
+ buffer: Uint8Array
574
+ ): __TnValidateResult {
575
+ const fn = __tnDynamicValidateRegistry[typeName];
576
+ if (!fn) throw new Error(`IR runtime missing dynamic validate helper for ${typeName}`);
577
+ return fn(buffer);
578
+ }
579
+
554
580
  function __tnEvalFootprint(node: __TnIrNode, ctx: __TnIrContext): bigint {
555
- return __tnEvalIrNode(node, ctx);
581
+ return __tnEvalIrNode(node, ctx, __tnToBigInt(0));
556
582
  }
557
583
 
558
584
  function __tnTryEvalFootprint(
@@ -567,7 +593,7 @@ function __tnTryEvalIr(
567
593
  ctx: __TnIrContext
568
594
  ): __TnEvalResult {
569
595
  try {
570
- return { ok: true, value: __tnEvalIrNode(node, ctx) };
596
+ return { ok: true, value: __tnEvalIrNode(node, ctx, __tnToBigInt(0)) };
571
597
  } catch (err) {
572
598
  return { ok: false, code: __tnNormalizeIrError(err) };
573
599
  }
@@ -598,7 +624,11 @@ function __tnValidateIrTree(
598
624
  return { ok: true, consumed: required };
599
625
  }
600
626
 
601
- function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
627
+ function __tnEvalIrNode(
628
+ node: __TnIrNode,
629
+ ctx: __TnIrContext,
630
+ baseOffset: bigint
631
+ ): bigint {
602
632
  switch (node.op) {
603
633
  case "zero":
604
634
  return __tnToBigInt(0);
@@ -616,17 +646,22 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
616
646
  return val;
617
647
  }
618
648
  case "add":
619
- return __tnCheckedAdd(
620
- __tnEvalIrNode(node.left, ctx),
621
- __tnEvalIrNode(node.right, ctx)
622
- );
649
+ {
650
+ const left = __tnEvalIrNode(node.left, ctx, baseOffset);
651
+ const right = __tnEvalIrNode(
652
+ node.right,
653
+ ctx,
654
+ __tnCheckedAdd(baseOffset, left)
655
+ );
656
+ return __tnCheckedAdd(left, right);
657
+ }
623
658
  case "mul":
624
659
  return __tnCheckedMul(
625
- __tnEvalIrNode(node.left, ctx),
626
- __tnEvalIrNode(node.right, ctx)
660
+ __tnEvalIrNode(node.left, ctx, baseOffset),
661
+ __tnEvalIrNode(node.right, ctx, baseOffset)
627
662
  );
628
663
  case "align":
629
- return __tnAlign(__tnEvalIrNode(node.node, ctx), node.alignment);
664
+ return __tnAlign(__tnEvalIrNode(node.node, ctx, baseOffset), node.alignment);
630
665
  case "switch": {
631
666
  const tagVal = ctx.params[node.tag];
632
667
  if (tagVal === undefined) {
@@ -639,10 +674,10 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
639
674
  const tagNumber = Number(tagVal);
640
675
  for (const caseNode of node.cases) {
641
676
  if (caseNode.value === tagNumber) {
642
- return __tnEvalIrNode(caseNode.node, ctx);
677
+ return __tnEvalIrNode(caseNode.node, ctx, baseOffset);
643
678
  }
644
679
  }
645
- if (node.default) return __tnEvalIrNode(node.default, ctx);
680
+ if (node.default) return __tnEvalIrNode(node.default, ctx, baseOffset);
646
681
  __tnRaiseIrError(
647
682
  "tn.ir.invalid_tag",
648
683
  `Unhandled IR switch value ${tagNumber} for '${node.tag}'`
@@ -662,9 +697,10 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
662
697
  nestedParams[arg.name] = val;
663
698
  }
664
699
  if (ctx.buffer) {
700
+ const nestedOffset = __tnBigIntToNumber(baseOffset, "IR nested offset");
665
701
  const nestedResult = __tnInvokeValidate(
666
702
  node.typeName,
667
- ctx.buffer,
703
+ ctx.buffer.subarray(nestedOffset),
668
704
  nestedParams
669
705
  );
670
706
  if (!nestedResult.ok) {
@@ -684,6 +720,36 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
684
720
  }
685
721
  return __tnInvokeFootprint(node.typeName, nestedParams);
686
722
  }
723
+ case "sumOverArray": {
724
+ if (!ctx.buffer) {
725
+ __tnRaiseIrError(
726
+ "tn.ir.missing_buffer",
727
+ `Jagged array '${node.fieldName}' requires buffer-backed validation`
728
+ );
729
+ }
730
+ const count = __tnBigIntToNumber(
731
+ __tnEvalIrNode(node.count, ctx, baseOffset),
732
+ `Jagged array '${node.fieldName}' count`
733
+ );
734
+ let cursor = __tnBigIntToNumber(baseOffset, "IR jagged array offset");
735
+ let total = __tnToBigInt(0);
736
+ for (let i = 0; i < count; i++) {
737
+ const result = __tnInvokeDynamicValidate(
738
+ node.elementTypeName,
739
+ ctx.buffer.subarray(cursor)
740
+ );
741
+ if (!result.ok || result.consumed === undefined) {
742
+ const code = result.code ?? "tn.ir.runtime_error";
743
+ __tnRaiseIrError(
744
+ code,
745
+ `Jagged array '${node.fieldName}' element ${i} failed validation`
746
+ );
747
+ }
748
+ cursor += __tnBigIntToNumber(result.consumed, "IR jagged element size");
749
+ total = __tnCheckedAdd(total, result.consumed);
750
+ }
751
+ return total;
752
+ }
687
753
  default:
688
754
  __tnRaiseIrError(
689
755
  "tn.ir.runtime_error",
@@ -718,6 +784,14 @@ function __tnNormalizeIrError(err: unknown): string {
718
784
  return "tn.ir.runtime_error";
719
785
  }
720
786
 
787
+ __tnRegisterFootprint("Hash", (params) => Hash.__tnInvokeFootprint(params));
788
+ __tnRegisterValidate("Hash", (buffer, params) => Hash.__tnInvokeValidate(buffer, params));
789
+ __tnRegisterDynamicValidate("Hash", (buffer) => { const result = Hash.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
790
+
791
+ __tnRegisterFootprint("Pubkey", (params) => Pubkey.__tnInvokeFootprint(params));
792
+ __tnRegisterValidate("Pubkey", (buffer, params) => Pubkey.__tnInvokeValidate(buffer, params));
793
+ __tnRegisterDynamicValidate("Pubkey", (buffer) => { const result = Pubkey.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
794
+
721
795
  /* ----- TYPE DEFINITION FOR StateProofHeader ----- */
722
796
 
723
797
  const __tn_ir_StateProofHeader = {
@@ -833,9 +907,6 @@ export class StateProofHeader {
833
907
 
834
908
  }
835
909
 
836
- __tnRegisterFootprint("StateProofHeader", (params) => StateProofHeader.__tnInvokeFootprint(params));
837
- __tnRegisterValidate("StateProofHeader", (buffer, params) => StateProofHeader.__tnInvokeValidate(buffer, params));
838
-
839
910
  export class StateProofHeaderBuilder {
840
911
  private buffer: Uint8Array;
841
912
  private view: DataView;
@@ -874,6 +945,10 @@ export class StateProofHeaderBuilder {
874
945
  }
875
946
  }
876
947
 
948
+ __tnRegisterFootprint("StateProofHeader", (params) => StateProofHeader.__tnInvokeFootprint(params));
949
+ __tnRegisterValidate("StateProofHeader", (buffer, params) => StateProofHeader.__tnInvokeValidate(buffer, params));
950
+ __tnRegisterDynamicValidate("StateProofHeader", (buffer) => { const result = StateProofHeader.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
951
+
877
952
  /* ----- TYPE DEFINITION FOR StateProof ----- */
878
953
 
879
954
  const __tn_ir_StateProof = {
@@ -1548,9 +1623,6 @@ export namespace StateProof {
1548
1623
  }
1549
1624
  }
1550
1625
 
1551
- __tnRegisterFootprint("StateProof", (params) => StateProof.__tnInvokeFootprint(params));
1552
- __tnRegisterValidate("StateProof", (buffer, params) => StateProof.__tnInvokeValidate(buffer, params));
1553
-
1554
1626
  export class StateProofBuilder {
1555
1627
  private __tnPrefixBuffer: Uint8Array;
1556
1628
  private __tnPrefixView: DataView;
@@ -1665,3 +1737,7 @@ export class StateProofBuilder {
1665
1737
  }
1666
1738
  }
1667
1739
 
1740
+ __tnRegisterFootprint("StateProof", (params) => StateProof.__tnInvokeFootprint(params));
1741
+ __tnRegisterValidate("StateProof", (buffer, params) => StateProof.__tnInvokeValidate(buffer, params));
1742
+ __tnRegisterDynamicValidate("StateProof", (buffer) => { const result = StateProof.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
1743
+
@@ -30,6 +30,12 @@ type __TnIrNode =
30
30
  readonly op: "call";
31
31
  readonly typeName: string;
32
32
  readonly args: readonly { readonly name: string; readonly source: string }[];
33
+ }
34
+ | {
35
+ readonly op: "sumOverArray";
36
+ readonly count: __TnIrNode;
37
+ readonly elementTypeName: string;
38
+ readonly fieldName: string;
33
39
  };
34
40
 
35
41
  type __TnIrContext = {
@@ -515,6 +521,10 @@ const __tnValidateRegistry: Record<
515
521
  string,
516
522
  (buffer: Uint8Array, params: Record<string, bigint>) => __TnValidateResult
517
523
  > = {};
524
+ const __tnDynamicValidateRegistry: Record<
525
+ string,
526
+ (buffer: Uint8Array) => __TnValidateResult
527
+ > = {};
518
528
 
519
529
  function __tnRegisterFootprint(
520
530
  typeName: string,
@@ -530,6 +540,13 @@ function __tnRegisterValidate(
530
540
  __tnValidateRegistry[typeName] = fn;
531
541
  }
532
542
 
543
+ function __tnRegisterDynamicValidate(
544
+ typeName: string,
545
+ fn: (buffer: Uint8Array) => __TnValidateResult
546
+ ): void {
547
+ __tnDynamicValidateRegistry[typeName] = fn;
548
+ }
549
+
533
550
  function __tnInvokeFootprint(
534
551
  typeName: string,
535
552
  params: Record<string, bigint>
@@ -549,8 +566,17 @@ function __tnInvokeValidate(
549
566
  return fn(buffer, params);
550
567
  }
551
568
 
569
+ function __tnInvokeDynamicValidate(
570
+ typeName: string,
571
+ buffer: Uint8Array
572
+ ): __TnValidateResult {
573
+ const fn = __tnDynamicValidateRegistry[typeName];
574
+ if (!fn) throw new Error(`IR runtime missing dynamic validate helper for ${typeName}`);
575
+ return fn(buffer);
576
+ }
577
+
552
578
  function __tnEvalFootprint(node: __TnIrNode, ctx: __TnIrContext): bigint {
553
- return __tnEvalIrNode(node, ctx);
579
+ return __tnEvalIrNode(node, ctx, __tnToBigInt(0));
554
580
  }
555
581
 
556
582
  function __tnTryEvalFootprint(
@@ -565,7 +591,7 @@ function __tnTryEvalIr(
565
591
  ctx: __TnIrContext
566
592
  ): __TnEvalResult {
567
593
  try {
568
- return { ok: true, value: __tnEvalIrNode(node, ctx) };
594
+ return { ok: true, value: __tnEvalIrNode(node, ctx, __tnToBigInt(0)) };
569
595
  } catch (err) {
570
596
  return { ok: false, code: __tnNormalizeIrError(err) };
571
597
  }
@@ -596,7 +622,11 @@ function __tnValidateIrTree(
596
622
  return { ok: true, consumed: required };
597
623
  }
598
624
 
599
- function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
625
+ function __tnEvalIrNode(
626
+ node: __TnIrNode,
627
+ ctx: __TnIrContext,
628
+ baseOffset: bigint
629
+ ): bigint {
600
630
  switch (node.op) {
601
631
  case "zero":
602
632
  return __tnToBigInt(0);
@@ -614,17 +644,22 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
614
644
  return val;
615
645
  }
616
646
  case "add":
617
- return __tnCheckedAdd(
618
- __tnEvalIrNode(node.left, ctx),
619
- __tnEvalIrNode(node.right, ctx)
620
- );
647
+ {
648
+ const left = __tnEvalIrNode(node.left, ctx, baseOffset);
649
+ const right = __tnEvalIrNode(
650
+ node.right,
651
+ ctx,
652
+ __tnCheckedAdd(baseOffset, left)
653
+ );
654
+ return __tnCheckedAdd(left, right);
655
+ }
621
656
  case "mul":
622
657
  return __tnCheckedMul(
623
- __tnEvalIrNode(node.left, ctx),
624
- __tnEvalIrNode(node.right, ctx)
658
+ __tnEvalIrNode(node.left, ctx, baseOffset),
659
+ __tnEvalIrNode(node.right, ctx, baseOffset)
625
660
  );
626
661
  case "align":
627
- return __tnAlign(__tnEvalIrNode(node.node, ctx), node.alignment);
662
+ return __tnAlign(__tnEvalIrNode(node.node, ctx, baseOffset), node.alignment);
628
663
  case "switch": {
629
664
  const tagVal = ctx.params[node.tag];
630
665
  if (tagVal === undefined) {
@@ -637,10 +672,10 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
637
672
  const tagNumber = Number(tagVal);
638
673
  for (const caseNode of node.cases) {
639
674
  if (caseNode.value === tagNumber) {
640
- return __tnEvalIrNode(caseNode.node, ctx);
675
+ return __tnEvalIrNode(caseNode.node, ctx, baseOffset);
641
676
  }
642
677
  }
643
- if (node.default) return __tnEvalIrNode(node.default, ctx);
678
+ if (node.default) return __tnEvalIrNode(node.default, ctx, baseOffset);
644
679
  __tnRaiseIrError(
645
680
  "tn.ir.invalid_tag",
646
681
  `Unhandled IR switch value ${tagNumber} for '${node.tag}'`
@@ -660,9 +695,10 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
660
695
  nestedParams[arg.name] = val;
661
696
  }
662
697
  if (ctx.buffer) {
698
+ const nestedOffset = __tnBigIntToNumber(baseOffset, "IR nested offset");
663
699
  const nestedResult = __tnInvokeValidate(
664
700
  node.typeName,
665
- ctx.buffer,
701
+ ctx.buffer.subarray(nestedOffset),
666
702
  nestedParams
667
703
  );
668
704
  if (!nestedResult.ok) {
@@ -682,6 +718,36 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
682
718
  }
683
719
  return __tnInvokeFootprint(node.typeName, nestedParams);
684
720
  }
721
+ case "sumOverArray": {
722
+ if (!ctx.buffer) {
723
+ __tnRaiseIrError(
724
+ "tn.ir.missing_buffer",
725
+ `Jagged array '${node.fieldName}' requires buffer-backed validation`
726
+ );
727
+ }
728
+ const count = __tnBigIntToNumber(
729
+ __tnEvalIrNode(node.count, ctx, baseOffset),
730
+ `Jagged array '${node.fieldName}' count`
731
+ );
732
+ let cursor = __tnBigIntToNumber(baseOffset, "IR jagged array offset");
733
+ let total = __tnToBigInt(0);
734
+ for (let i = 0; i < count; i++) {
735
+ const result = __tnInvokeDynamicValidate(
736
+ node.elementTypeName,
737
+ ctx.buffer.subarray(cursor)
738
+ );
739
+ if (!result.ok || result.consumed === undefined) {
740
+ const code = result.code ?? "tn.ir.runtime_error";
741
+ __tnRaiseIrError(
742
+ code,
743
+ `Jagged array '${node.fieldName}' element ${i} failed validation`
744
+ );
745
+ }
746
+ cursor += __tnBigIntToNumber(result.consumed, "IR jagged element size");
747
+ total = __tnCheckedAdd(total, result.consumed);
748
+ }
749
+ return total;
750
+ }
685
751
  default:
686
752
  __tnRaiseIrError(
687
753
  "tn.ir.runtime_error",
@@ -858,9 +924,6 @@ export class Date {
858
924
 
859
925
  }
860
926
 
861
- __tnRegisterFootprint("Date", (params) => Date.__tnInvokeFootprint(params));
862
- __tnRegisterValidate("Date", (buffer, params) => Date.__tnInvokeValidate(buffer, params));
863
-
864
927
  export class DateBuilder {
865
928
  private buffer: Uint8Array;
866
929
  private view: DataView;
@@ -902,6 +965,10 @@ export class DateBuilder {
902
965
  }
903
966
  }
904
967
 
968
+ __tnRegisterFootprint("Date", (params) => Date.__tnInvokeFootprint(params));
969
+ __tnRegisterValidate("Date", (buffer, params) => Date.__tnInvokeValidate(buffer, params));
970
+ __tnRegisterDynamicValidate("Date", (buffer) => { const result = Date.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
971
+
905
972
  /* ----- TYPE DEFINITION FOR Duration ----- */
906
973
 
907
974
  const __tn_ir_Duration = {
@@ -1025,9 +1092,6 @@ export class Duration {
1025
1092
 
1026
1093
  }
1027
1094
 
1028
- __tnRegisterFootprint("Duration", (params) => Duration.__tnInvokeFootprint(params));
1029
- __tnRegisterValidate("Duration", (buffer, params) => Duration.__tnInvokeValidate(buffer, params));
1030
-
1031
1095
  export class DurationBuilder {
1032
1096
  private buffer: Uint8Array;
1033
1097
  private view: DataView;
@@ -1065,6 +1129,10 @@ export class DurationBuilder {
1065
1129
  }
1066
1130
  }
1067
1131
 
1132
+ __tnRegisterFootprint("Duration", (params) => Duration.__tnInvokeFootprint(params));
1133
+ __tnRegisterValidate("Duration", (buffer, params) => Duration.__tnInvokeValidate(buffer, params));
1134
+ __tnRegisterDynamicValidate("Duration", (buffer) => { const result = Duration.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
1135
+
1068
1136
  /* ----- TYPE DEFINITION FOR FixedPoint ----- */
1069
1137
 
1070
1138
  const __tn_ir_FixedPoint = {
@@ -1188,9 +1256,6 @@ export class FixedPoint {
1188
1256
 
1189
1257
  }
1190
1258
 
1191
- __tnRegisterFootprint("FixedPoint", (params) => FixedPoint.__tnInvokeFootprint(params));
1192
- __tnRegisterValidate("FixedPoint", (buffer, params) => FixedPoint.__tnInvokeValidate(buffer, params));
1193
-
1194
1259
  export class FixedPointBuilder {
1195
1260
  private buffer: Uint8Array;
1196
1261
  private view: DataView;
@@ -1228,6 +1293,10 @@ export class FixedPointBuilder {
1228
1293
  }
1229
1294
  }
1230
1295
 
1296
+ __tnRegisterFootprint("FixedPoint", (params) => FixedPoint.__tnInvokeFootprint(params));
1297
+ __tnRegisterValidate("FixedPoint", (buffer, params) => FixedPoint.__tnInvokeValidate(buffer, params));
1298
+ __tnRegisterDynamicValidate("FixedPoint", (buffer) => { const result = FixedPoint.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
1299
+
1231
1300
  /* ----- TYPE DEFINITION FOR Hash ----- */
1232
1301
 
1233
1302
  const __tn_ir_Hash = {
@@ -1331,9 +1400,6 @@ export class Hash {
1331
1400
 
1332
1401
  }
1333
1402
 
1334
- __tnRegisterFootprint("Hash", (params) => Hash.__tnInvokeFootprint(params));
1335
- __tnRegisterValidate("Hash", (buffer, params) => Hash.__tnInvokeValidate(buffer, params));
1336
-
1337
1403
  export class HashBuilder {
1338
1404
  private buffer: Uint8Array;
1339
1405
  private view: DataView;
@@ -1369,6 +1435,10 @@ export class HashBuilder {
1369
1435
  }
1370
1436
  }
1371
1437
 
1438
+ __tnRegisterFootprint("Hash", (params) => Hash.__tnInvokeFootprint(params));
1439
+ __tnRegisterValidate("Hash", (buffer, params) => Hash.__tnInvokeValidate(buffer, params));
1440
+ __tnRegisterDynamicValidate("Hash", (buffer) => { const result = Hash.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
1441
+
1372
1442
  /* ----- TYPE DEFINITION FOR InstructionData ----- */
1373
1443
 
1374
1444
  const __tn_ir_InstructionData = {
@@ -1654,9 +1724,6 @@ export namespace InstructionData {
1654
1724
  }
1655
1725
  }
1656
1726
 
1657
- __tnRegisterFootprint("InstructionData", (params) => InstructionData.__tnInvokeFootprint(params));
1658
- __tnRegisterValidate("InstructionData", (buffer, params) => InstructionData.__tnInvokeValidate(buffer, params));
1659
-
1660
1727
  export class InstructionDataBuilder {
1661
1728
  private buffer: Uint8Array;
1662
1729
  private view: DataView;
@@ -1768,6 +1835,10 @@ export class InstructionDataBuilder {
1768
1835
  }
1769
1836
  }
1770
1837
 
1838
+ __tnRegisterFootprint("InstructionData", (params) => InstructionData.__tnInvokeFootprint(params));
1839
+ __tnRegisterValidate("InstructionData", (buffer, params) => InstructionData.__tnInvokeValidate(buffer, params));
1840
+ __tnRegisterDynamicValidate("InstructionData", (buffer) => { const result = InstructionData.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
1841
+
1771
1842
  /* ----- TYPE DEFINITION FOR Pubkey ----- */
1772
1843
 
1773
1844
  const __tn_ir_Pubkey = {
@@ -1871,9 +1942,6 @@ export class Pubkey {
1871
1942
 
1872
1943
  }
1873
1944
 
1874
- __tnRegisterFootprint("Pubkey", (params) => Pubkey.__tnInvokeFootprint(params));
1875
- __tnRegisterValidate("Pubkey", (buffer, params) => Pubkey.__tnInvokeValidate(buffer, params));
1876
-
1877
1945
  export class PubkeyBuilder {
1878
1946
  private buffer: Uint8Array;
1879
1947
  private view: DataView;
@@ -1909,6 +1977,10 @@ export class PubkeyBuilder {
1909
1977
  }
1910
1978
  }
1911
1979
 
1980
+ __tnRegisterFootprint("Pubkey", (params) => Pubkey.__tnInvokeFootprint(params));
1981
+ __tnRegisterValidate("Pubkey", (buffer, params) => Pubkey.__tnInvokeValidate(buffer, params));
1982
+ __tnRegisterDynamicValidate("Pubkey", (buffer) => { const result = Pubkey.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
1983
+
1912
1984
  /* ----- TYPE DEFINITION FOR Signature ----- */
1913
1985
 
1914
1986
  const __tn_ir_Signature = {
@@ -2012,9 +2084,6 @@ export class Signature {
2012
2084
 
2013
2085
  }
2014
2086
 
2015
- __tnRegisterFootprint("Signature", (params) => Signature.__tnInvokeFootprint(params));
2016
- __tnRegisterValidate("Signature", (buffer, params) => Signature.__tnInvokeValidate(buffer, params));
2017
-
2018
2087
  export class SignatureBuilder {
2019
2088
  private buffer: Uint8Array;
2020
2089
  private view: DataView;
@@ -2050,6 +2119,10 @@ export class SignatureBuilder {
2050
2119
  }
2051
2120
  }
2052
2121
 
2122
+ __tnRegisterFootprint("Signature", (params) => Signature.__tnInvokeFootprint(params));
2123
+ __tnRegisterValidate("Signature", (buffer, params) => Signature.__tnInvokeValidate(buffer, params));
2124
+ __tnRegisterDynamicValidate("Signature", (buffer) => { const result = Signature.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
2125
+
2053
2126
  /* ----- TYPE DEFINITION FOR Timestamp ----- */
2054
2127
 
2055
2128
  const __tn_ir_Timestamp = {
@@ -2154,9 +2227,6 @@ export class Timestamp {
2154
2227
 
2155
2228
  }
2156
2229
 
2157
- __tnRegisterFootprint("Timestamp", (params) => Timestamp.__tnInvokeFootprint(params));
2158
- __tnRegisterValidate("Timestamp", (buffer, params) => Timestamp.__tnInvokeValidate(buffer, params));
2159
-
2160
2230
  export class TimestampBuilder {
2161
2231
  private buffer: Uint8Array;
2162
2232
  private view: DataView;
@@ -2189,3 +2259,7 @@ export class TimestampBuilder {
2189
2259
  }
2190
2260
  }
2191
2261
 
2262
+ __tnRegisterFootprint("Timestamp", (params) => Timestamp.__tnInvokeFootprint(params));
2263
+ __tnRegisterValidate("Timestamp", (buffer, params) => Timestamp.__tnInvokeValidate(buffer, params));
2264
+ __tnRegisterDynamicValidate("Timestamp", (buffer) => { const result = Timestamp.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
2265
+