ox 0.14.38 → 0.14.40

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 (69) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/_cjs/tempo/MultisigConfig.js +71 -15
  3. package/_cjs/tempo/MultisigConfig.js.map +1 -1
  4. package/_cjs/tempo/MultisigOperation.js +43 -35
  5. package/_cjs/tempo/MultisigOperation.js.map +1 -1
  6. package/_cjs/tempo/MultisigWitness.js +92 -0
  7. package/_cjs/tempo/MultisigWitness.js.map +1 -0
  8. package/_cjs/tempo/SignatureEnvelope.js +71 -108
  9. package/_cjs/tempo/SignatureEnvelope.js.map +1 -1
  10. package/_cjs/tempo/TransactionRequest.js +7 -1
  11. package/_cjs/tempo/TransactionRequest.js.map +1 -1
  12. package/_cjs/tempo/index.js +2 -1
  13. package/_cjs/tempo/index.js.map +1 -1
  14. package/_cjs/version.js +1 -1
  15. package/_esm/tempo/MultisigConfig.js +140 -71
  16. package/_esm/tempo/MultisigConfig.js.map +1 -1
  17. package/_esm/tempo/MultisigOperation.js +43 -36
  18. package/_esm/tempo/MultisigOperation.js.map +1 -1
  19. package/_esm/tempo/MultisigWitness.js +123 -0
  20. package/_esm/tempo/MultisigWitness.js.map +1 -0
  21. package/_esm/tempo/SignatureEnvelope.js +84 -143
  22. package/_esm/tempo/SignatureEnvelope.js.map +1 -1
  23. package/_esm/tempo/TransactionRequest.js +7 -1
  24. package/_esm/tempo/TransactionRequest.js.map +1 -1
  25. package/_esm/tempo/index.js +9 -0
  26. package/_esm/tempo/index.js.map +1 -1
  27. package/_esm/version.js +1 -1
  28. package/_types/tempo/KeyAuthorization.d.ts +1 -1
  29. package/_types/tempo/KeyAuthorization.d.ts.map +1 -1
  30. package/_types/tempo/MultisigConfig.d.ts +137 -73
  31. package/_types/tempo/MultisigConfig.d.ts.map +1 -1
  32. package/_types/tempo/MultisigOperation.d.ts +1 -1
  33. package/_types/tempo/MultisigOperation.d.ts.map +1 -1
  34. package/_types/tempo/MultisigWitness.d.ts +106 -0
  35. package/_types/tempo/MultisigWitness.d.ts.map +1 -0
  36. package/_types/tempo/SignatureEnvelope.d.ts +81 -75
  37. package/_types/tempo/SignatureEnvelope.d.ts.map +1 -1
  38. package/_types/tempo/TransactionRequest.d.ts +6 -3
  39. package/_types/tempo/TransactionRequest.d.ts.map +1 -1
  40. package/_types/tempo/index.d.ts +9 -0
  41. package/_types/tempo/index.d.ts.map +1 -1
  42. package/_types/version.d.ts +1 -1
  43. package/package.json +21 -1
  44. package/tempo/KeyAuthorization.test-d.ts +12 -0
  45. package/tempo/KeyAuthorization.test.ts +54 -0
  46. package/tempo/KeyAuthorization.ts +1 -1
  47. package/tempo/MultisigConfig.test-d/package.json +6 -0
  48. package/tempo/MultisigConfig.test-d.ts +52 -0
  49. package/tempo/MultisigConfig.test.ts +291 -263
  50. package/tempo/MultisigConfig.ts +250 -95
  51. package/tempo/MultisigOperation.test-d.ts +6 -0
  52. package/tempo/MultisigOperation.test.ts +200 -81
  53. package/tempo/MultisigOperation.ts +42 -34
  54. package/tempo/MultisigWitness/package.json +6 -0
  55. package/tempo/MultisigWitness.test-d/package.json +6 -0
  56. package/tempo/MultisigWitness.test-d.ts +42 -0
  57. package/tempo/MultisigWitness.test.ts +289 -0
  58. package/tempo/MultisigWitness.ts +210 -0
  59. package/tempo/RpcSchemaTempo.test-d.ts +25 -0
  60. package/tempo/SignatureEnvelope.test-d.ts +57 -40
  61. package/tempo/SignatureEnvelope.test.ts +523 -480
  62. package/tempo/SignatureEnvelope.ts +250 -257
  63. package/tempo/TransactionRequest.test-d/package.json +6 -0
  64. package/tempo/TransactionRequest.test-d.ts +24 -0
  65. package/tempo/TransactionRequest.test.ts +102 -1
  66. package/tempo/TransactionRequest.ts +12 -2
  67. package/tempo/index.ts +9 -0
  68. package/tempo/multisig.e2e.test.ts +113 -86
  69. package/version.ts +1 -1
@@ -36,6 +36,7 @@ const config = MultisigConfig.from({
36
36
  ],
37
37
  threshold: 2,
38
38
  })
39
+ const initializedConfig = MultisigConfig.from({ ...config, version: 1n })
39
40
  const account = MultisigConfig.getAddress(config)
40
41
  const ownerSignature_1 = owners[0]!.signature
41
42
  const approval_1 = SignatureEnvelope.serialize(ownerSignature_1)
@@ -62,23 +63,23 @@ const keyAuthorization = KeyAuthorization.serialize(
62
63
 
63
64
  const transactionHash_ = MultisigConfig.getSignPayload({
64
65
  account,
66
+ config: initializedConfig,
65
67
  payload: TxEnvelopeTempo.getSignPayload(
66
68
  TxEnvelopeTempo.deserialize(transaction),
67
69
  ),
68
- version: 1n,
69
70
  })
70
71
  const keyAuthorizationHash = MultisigConfig.getSignPayload({
71
72
  account,
73
+ config: initializedConfig,
72
74
  payload: KeyAuthorization.getSignPayload(
73
75
  KeyAuthorization.deserialize(keyAuthorization),
74
76
  ),
75
- version: 1n,
76
77
  })
77
78
 
78
79
  const base = {
79
80
  account,
80
81
  approvals: [approval_1],
81
- config,
82
+ config: initializedConfig,
82
83
  configVersion: 1n,
83
84
  createdAt: 1,
84
85
  init: false,
@@ -249,8 +250,8 @@ describe('selectApprovals', () => {
249
250
  })
250
251
  const childHash = MultisigConfig.getSignPayload({
251
252
  account: child,
253
+ config: { version: 2n },
252
254
  payload: hash,
253
- version: 2n,
254
255
  })
255
256
  const childApprovals = [
256
257
  signApproval(owners[1]!, childHash),
@@ -261,7 +262,10 @@ describe('selectApprovals', () => {
261
262
  account,
262
263
  }) => {
263
264
  if (!Address.isEqual(account, child)) throw new Error('unknown account')
264
- return { config: childConfig, version: 2n }
265
+ return {
266
+ config: MultisigConfig.from({ ...childConfig, version: 2n }),
267
+ version: 2n,
268
+ }
265
269
  }
266
270
  const partial = await MultisigOperation.selectApprovals({
267
271
  account,
@@ -269,6 +273,7 @@ describe('selectApprovals', () => {
269
273
  rootApproval,
270
274
  SignatureEnvelope.serialize({
271
275
  account: child,
276
+ config: MultisigConfig.from({ ...childConfig, version: 2n }),
272
277
  signatures: [SignatureEnvelope.deserialize(childApprovals[0]!)],
273
278
  type: 'multisig',
274
279
  }),
@@ -283,6 +288,7 @@ describe('selectApprovals', () => {
283
288
  rootApproval,
284
289
  SignatureEnvelope.serialize({
285
290
  account: child,
291
+ config: MultisigConfig.from({ ...childConfig, version: 2n }),
286
292
  signatures: childApprovals.map((approval) =>
287
293
  SignatureEnvelope.deserialize(approval),
288
294
  ),
@@ -335,6 +341,57 @@ describe('selectApprovals', () => {
335
341
  `)
336
342
  })
337
343
 
344
+ test('rejects mismatched nested config versions', async () => {
345
+ const childConfig = MultisigConfig.from({
346
+ owners: [{ owner: owners[1]!.address, weight: 1 }],
347
+ threshold: 1,
348
+ })
349
+ const child = MultisigConfig.getAddress(childConfig)
350
+ const config = MultisigConfig.from({
351
+ owners: [{ owner: child, weight: 1 }],
352
+ threshold: 1,
353
+ })
354
+ const account = MultisigConfig.getAddress(config)
355
+ const hash = MultisigOperation.getHash({
356
+ account,
357
+ configVersion: 1n,
358
+ transaction,
359
+ type: 'transaction',
360
+ })
361
+ const resolvedConfig = MultisigConfig.from({
362
+ ...childConfig,
363
+ version: 2n,
364
+ })
365
+ const childHash = MultisigConfig.getSignPayload({
366
+ account: child,
367
+ config: resolvedConfig,
368
+ payload: hash,
369
+ })
370
+
371
+ await expect(
372
+ MultisigOperation.selectApprovals({
373
+ account,
374
+ approvals: [
375
+ SignatureEnvelope.serialize({
376
+ account: child,
377
+ config: resolvedConfig,
378
+ signatures: [
379
+ SignatureEnvelope.deserialize(
380
+ signApproval(owners[1]!, childHash),
381
+ ),
382
+ ],
383
+ type: 'multisig',
384
+ }),
385
+ ],
386
+ config,
387
+ hash,
388
+ resolveConfig: () => ({ config: childConfig, version: 2n }),
389
+ }),
390
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
391
+ `[MultisigOperation.InvalidApprovalError: Invalid multisig approval: resolved config.version must equal version for nested multisig owner 0x7888d60e9cc26c8569d394fce435c248f1e49c3b.]`,
392
+ )
393
+ })
394
+
338
395
  test('rejects invalid and non-owner approvals', async () => {
339
396
  const hash = MultisigOperation.getHash({
340
397
  account,
@@ -389,8 +446,8 @@ describe('selectApprovals', () => {
389
446
  })
390
447
  const childHash = MultisigConfig.getSignPayload({
391
448
  account: child,
449
+ config: { version: 1n },
392
450
  payload: hash,
393
- version: 1n,
394
451
  })
395
452
 
396
453
  await expect(
@@ -399,6 +456,7 @@ describe('selectApprovals', () => {
399
456
  approvals: [
400
457
  SignatureEnvelope.serialize({
401
458
  account: child,
459
+ config: MultisigConfig.from({ ...childConfig, version: 1n }),
402
460
  signatures: [
403
461
  SignatureEnvelope.deserialize(
404
462
  signApproval(owners[1]!, childHash),
@@ -415,7 +473,7 @@ describe('selectApprovals', () => {
415
473
  )
416
474
  })
417
475
 
418
- test('rejects keychain and bootstrap nested approvals', async () => {
476
+ test('rejects keychain and accepts initial nested approvals', async () => {
419
477
  const childConfig = MultisigConfig.from({
420
478
  owners: [{ owner: owners[1]!.address, weight: 1 }],
421
479
  threshold: 1,
@@ -437,8 +495,8 @@ describe('selectApprovals', () => {
437
495
  })
438
496
  const childHash = MultisigConfig.getSignPayload({
439
497
  account: child,
498
+ config: childConfig,
440
499
  payload: hash,
441
- version: 0n,
442
500
  })
443
501
 
444
502
  await expect(
@@ -459,31 +517,36 @@ describe('selectApprovals', () => {
459
517
  ).rejects.toThrowErrorMatchingInlineSnapshot(
460
518
  `[MultisigOperation.InvalidApprovalError: Invalid multisig approval: keychain signatures cannot approve a multisig operation.]`,
461
519
  )
462
- await expect(
463
- MultisigOperation.selectApprovals({
464
- account,
465
- approvals: [
466
- SignatureEnvelope.serialize({
467
- account: child,
468
- init: childConfig,
469
- signatures: [
470
- SignatureEnvelope.deserialize(
471
- signApproval(owners[1]!, childHash),
472
- ),
473
- ],
474
- type: 'multisig',
475
- }),
476
- ],
477
- config,
478
- hash,
479
- resolveConfig: () => ({ config: childConfig, version: 0n }),
480
- }),
481
- ).rejects.toThrowErrorMatchingInlineSnapshot(
482
- `[MultisigOperation.InvalidApprovalError: Invalid multisig approval: nested multisig owner 0x7888d60e9cc26c8569d394fce435c248f1e49c3b cannot carry init.]`,
483
- )
520
+ const selection = await MultisigOperation.selectApprovals({
521
+ account,
522
+ approvals: [
523
+ SignatureEnvelope.serialize({
524
+ account: child,
525
+ config: childConfig,
526
+ signatures: [
527
+ SignatureEnvelope.deserialize(signApproval(owners[1]!, childHash)),
528
+ ],
529
+ type: 'multisig',
530
+ }),
531
+ ],
532
+ config,
533
+ hash,
534
+ resolveConfig: () => ({ config: childConfig, version: 0n }),
535
+ })
536
+ expect({
537
+ signatureCount: selection.signatureCount,
538
+ threshold: selection.threshold,
539
+ weight: selection.weight,
540
+ }).toMatchInlineSnapshot(`
541
+ {
542
+ "signatureCount": 1,
543
+ "threshold": 1,
544
+ "weight": 1,
545
+ }
546
+ `)
484
547
  })
485
548
 
486
- test('rejects nested account cycles', async () => {
549
+ test('rejects nested account cycles while serializing', () => {
487
550
  const config = MultisigConfig.from({
488
551
  owners: [{ owner: account, weight: 1 }],
489
552
  threshold: 1,
@@ -496,30 +559,21 @@ describe('selectApprovals', () => {
496
559
  })
497
560
  const nestedHash = MultisigConfig.getSignPayload({
498
561
  account,
562
+ config: { version: 2n },
499
563
  payload: hash,
500
- version: 2n,
501
564
  })
502
565
 
503
- await expect(
504
- MultisigOperation.selectApprovals({
566
+ expect(() =>
567
+ SignatureEnvelope.serialize({
505
568
  account,
506
- approvals: [
507
- SignatureEnvelope.serialize({
508
- account,
509
- signatures: [
510
- SignatureEnvelope.deserialize(
511
- signApproval(owners[0]!, nestedHash),
512
- ),
513
- ],
514
- type: 'multisig',
515
- }),
569
+ config: MultisigConfig.from({ ...config, version: 2n }),
570
+ signatures: [
571
+ SignatureEnvelope.deserialize(signApproval(owners[0]!, nestedHash)),
516
572
  ],
517
- config,
518
- hash,
519
- resolveConfig: () => ({ config, version: 2n }),
573
+ type: 'multisig',
520
574
  }),
521
- ).rejects.toThrowErrorMatchingInlineSnapshot(
522
- `[MultisigOperation.InvalidApprovalError: Invalid multisig approval: nested multisig owner 0xf81b7763d3a6876195d780865bd783dbd97dd36e is invalid.]`,
575
+ ).toThrowErrorMatchingInlineSnapshot(
576
+ `[SignatureEnvelope.InvalidMultisigApprovalError: Invalid native multisig owner approval: multisig account cannot be an owner.]`,
523
577
  )
524
578
  })
525
579
 
@@ -547,13 +601,13 @@ describe('selectApprovals', () => {
547
601
  })
548
602
  const childHash = MultisigConfig.getSignPayload({
549
603
  account: child,
604
+ config: { version: 1n },
550
605
  payload: hash,
551
- version: 1n,
552
606
  })
553
607
  const grandchildHash = MultisigConfig.getSignPayload({
554
608
  account: grandchild,
609
+ config: { version: 1n },
555
610
  payload: childHash,
556
- version: 1n,
557
611
  })
558
612
 
559
613
  await expect(
@@ -562,9 +616,14 @@ describe('selectApprovals', () => {
562
616
  approvals: [
563
617
  SignatureEnvelope.serialize({
564
618
  account: child,
619
+ config: MultisigConfig.from({ ...childConfig, version: 1n }),
565
620
  signatures: [
566
621
  {
567
622
  account: grandchild,
623
+ config: MultisigConfig.from({
624
+ ...grandchildConfig,
625
+ version: 1n,
626
+ }),
568
627
  signatures: [
569
628
  SignatureEnvelope.deserialize(
570
629
  signApproval(owners[2]!, grandchildHash),
@@ -580,8 +639,17 @@ describe('selectApprovals', () => {
580
639
  hash,
581
640
  resolveConfig: ({ account }) => {
582
641
  if (Address.isEqual(account, child))
583
- return { config: childConfig, version: 1n }
584
- return { config: grandchildConfig, version: 1n }
642
+ return {
643
+ config: MultisigConfig.from({ ...childConfig, version: 1n }),
644
+ version: 1n,
645
+ }
646
+ return {
647
+ config: MultisigConfig.from({
648
+ ...grandchildConfig,
649
+ version: 1n,
650
+ }),
651
+ version: 1n,
652
+ }
585
653
  },
586
654
  }),
587
655
  ).rejects.toThrowErrorMatchingInlineSnapshot(
@@ -595,6 +663,7 @@ describe('serializeTransaction', () => {
595
663
  const results = []
596
664
  for (const init of [false, true]) {
597
665
  const configVersion = init ? 0n : 1n
666
+ const applicableConfig = init ? config : initializedConfig
598
667
  const hash = MultisigOperation.getHash({
599
668
  account,
600
669
  configVersion,
@@ -607,13 +676,13 @@ describe('serializeTransaction', () => {
607
676
  signApproval(owners[1]!, hash),
608
677
  signApproval(owners[0]!, hash),
609
678
  ],
610
- config,
679
+ config: applicableConfig,
611
680
  hash,
612
681
  })
613
682
  const operation = MultisigOperation.from({
614
683
  account,
615
684
  approvals: selection.approvals,
616
- config,
685
+ config: applicableConfig,
617
686
  configVersion,
618
687
  createdAt: 1,
619
688
  hash,
@@ -632,8 +701,11 @@ describe('serializeTransaction', () => {
632
701
  const value = TxEnvelopeTempo.deserialize(serialized)
633
702
  results.push({
634
703
  account: value.signature?.account,
704
+ configVersion:
705
+ value.signature?.type === 'multisig'
706
+ ? value.signature.config.version
707
+ : undefined,
635
708
  hash: Hash.keccak256(serialized),
636
- init: value.signature?.type === 'multisig' && !!value.signature.init,
637
709
  signatureCount:
638
710
  value.signature?.type === 'multisig'
639
711
  ? value.signature.signatures.length
@@ -646,15 +718,15 @@ describe('serializeTransaction', () => {
646
718
  [
647
719
  {
648
720
  "account": "0xf81b7763d3a6876195d780865bd783dbd97dd36e",
649
- "hash": "0x704768725a4e798e2656f0f355f99507522c97b2947f551a5ee696216a2ba6fe",
650
- "init": false,
721
+ "configVersion": 1n,
722
+ "hash": "0x8309740edaf304284186f7bcfe4527745cd4eb48e7441795ebdd970798091f8f",
651
723
  "signatureCount": 2,
652
724
  "type": "0x76",
653
725
  },
654
726
  {
655
727
  "account": "0xf81b7763d3a6876195d780865bd783dbd97dd36e",
656
- "hash": "0x08131922349c385f9112fefc617fa6f6258a71df1125ec243bb3ee7cff59b700",
657
- "init": true,
728
+ "configVersion": 0n,
729
+ "hash": "0x636af84d8445d87cbcd33039d5a3a2274a5911036b1b7ceb740ac41e2f638611",
658
730
  "signatureCount": 2,
659
731
  "type": "0x76",
660
732
  },
@@ -694,14 +766,14 @@ describe('serializeTransaction', () => {
694
766
  signApproval(owners[0]!, hash),
695
767
  signApproval(owners[1]!, hash),
696
768
  ],
697
- config,
769
+ config: initializedConfig,
698
770
  hash,
699
771
  })
700
772
  const serialized = MultisigOperation.serializeTransaction(
701
773
  MultisigOperation.from({
702
774
  account,
703
775
  approvals: selection.approvals,
704
- config,
776
+ config: initializedConfig,
705
777
  configVersion: 1n,
706
778
  createdAt: 1,
707
779
  hash,
@@ -762,13 +834,13 @@ describe('serializeTransaction', () => {
762
834
  const selection = await MultisigOperation.selectApprovals({
763
835
  account,
764
836
  approvals: [approval_1],
765
- config,
837
+ config: initializedConfig,
766
838
  hash,
767
839
  })
768
840
  const operation = MultisigOperation.from({
769
841
  account,
770
842
  approvals: selection.approvals,
771
- config,
843
+ config: initializedConfig,
772
844
  configVersion: 1n,
773
845
  createdAt: 1,
774
846
  hash,
@@ -833,6 +905,7 @@ describe('from', () => {
833
905
  ],
834
906
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
835
907
  "threshold": 2,
908
+ "version": 1n,
836
909
  },
837
910
  "configVersion": 1n,
838
911
  "createdAt": 1,
@@ -865,6 +938,7 @@ describe('from', () => {
865
938
  ],
866
939
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
867
940
  "threshold": 2,
941
+ "version": 1n,
868
942
  },
869
943
  "configVersion": 1n,
870
944
  "createdAt": 1,
@@ -899,6 +973,7 @@ describe('from', () => {
899
973
  ],
900
974
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
901
975
  "threshold": 2,
976
+ "version": 1n,
902
977
  },
903
978
  "configVersion": 1n,
904
979
  "createdAt": 1,
@@ -929,10 +1004,10 @@ describe('from', () => {
929
1004
  ...transactionPending,
930
1005
  hash: MultisigConfig.getSignPayload({
931
1006
  account,
1007
+ config: initializedConfig,
932
1008
  payload: TxEnvelopeTempo.getSignPayload(
933
1009
  TxEnvelopeTempo.deserialize(transaction),
934
1010
  ),
935
- version: 1n,
936
1011
  }),
937
1012
  transaction,
938
1013
  })
@@ -961,6 +1036,7 @@ describe('from', () => {
961
1036
  ],
962
1037
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
963
1038
  "threshold": 2,
1039
+ "version": 1n,
964
1040
  },
965
1041
  "configVersion": 1n,
966
1042
  "createdAt": 1,
@@ -991,10 +1067,10 @@ describe('from', () => {
991
1067
  ...transactionPending,
992
1068
  hash: MultisigConfig.getSignPayload({
993
1069
  account,
1070
+ config: initializedConfig,
994
1071
  payload: TxEnvelopeTempo.getSignPayload(
995
1072
  TxEnvelopeTempo.deserialize(transaction),
996
1073
  ),
997
- version: 1n,
998
1074
  }),
999
1075
  transaction,
1000
1076
  })
@@ -1005,13 +1081,14 @@ describe('from', () => {
1005
1081
  test('bootstrap transaction', () => {
1006
1082
  const operation = MultisigOperation.from({
1007
1083
  ...transactionPending,
1084
+ config,
1008
1085
  configVersion: 0n,
1009
1086
  hash: MultisigConfig.getSignPayload({
1010
1087
  account,
1088
+ config,
1011
1089
  payload: TxEnvelopeTempo.getSignPayload(
1012
1090
  TxEnvelopeTempo.deserialize(transaction),
1013
1091
  ),
1014
- version: 0n,
1015
1092
  }),
1016
1093
  init: true,
1017
1094
  })
@@ -1040,6 +1117,7 @@ describe('from', () => {
1040
1117
  ],
1041
1118
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
1042
1119
  "threshold": 2,
1120
+ "version": 0n,
1043
1121
  },
1044
1122
  "configVersion": 0n,
1045
1123
  "createdAt": 1,
@@ -1060,13 +1138,14 @@ describe('from', () => {
1060
1138
  test('initialized transaction at config version zero', () => {
1061
1139
  const operation = MultisigOperation.from({
1062
1140
  ...transactionPending,
1141
+ config,
1063
1142
  configVersion: 0n,
1064
1143
  hash: MultisigConfig.getSignPayload({
1065
1144
  account,
1145
+ config,
1066
1146
  payload: TxEnvelopeTempo.getSignPayload(
1067
1147
  TxEnvelopeTempo.deserialize(transaction),
1068
1148
  ),
1069
- version: 0n,
1070
1149
  }),
1071
1150
  })
1072
1151
 
@@ -1091,6 +1170,7 @@ describe('from', () => {
1091
1170
  KeyAuthorization.from(authorization, {
1092
1171
  signature: {
1093
1172
  account,
1173
+ config: initializedConfig,
1094
1174
  signatures: [
1095
1175
  SignatureEnvelope.deserialize(approval_1),
1096
1176
  SignatureEnvelope.deserialize(approval_2),
@@ -1124,6 +1204,7 @@ describe('from', () => {
1124
1204
  ],
1125
1205
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
1126
1206
  "threshold": 2,
1207
+ "version": 1n,
1127
1208
  },
1128
1209
  "configVersion": 1n,
1129
1210
  "createdAt": 1,
@@ -1156,12 +1237,13 @@ describe('from', () => {
1156
1237
  ],
1157
1238
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
1158
1239
  "threshold": 2,
1240
+ "version": 1n,
1159
1241
  },
1160
1242
  "configVersion": 1n,
1161
1243
  "createdAt": 1,
1162
1244
  "hash": "0xf6995eb69c12c03d3d13b357abf7cac22b4effe52fba8ff02e5aef26161f77a0",
1163
1245
  "init": false,
1164
- "keyAuthorization": "0xf9015ff782107980943333333333333333333333333333333333333333846b49d2008080808094f81b7763d3a6876195d780865bd783dbd97dd36eb9012405f9012094f81b7763d3a6876195d780865bd783dbd97dd36ef90108b88201000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000065ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c8734640c4998ff7e374b06ce1a64a2ecd82ab036384fb83d9a79b127a27d503200b88201000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000047cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997807775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d100",
1246
+ "keyAuthorization": "0xf901b3f782107980943333333333333333333333333333333333333333846b49d2008080808094f81b7763d3a6876195d780865bd783dbd97dd36eb9017805f9017494f81b7763d3a6876195d780865bd783dbd97dd36ef852a000000000000000000000000000000000000000000000000000000000000000000102eed69407e1ed8ea0e9601e5546b0a03aed683df360140701d694288f0cd85005f34168f731a468aef268c2f9456f01f90108b88201000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000065ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c8734640c4998ff7e374b06ce1a64a2ecd82ab036384fb83d9a79b127a27d503200b88201000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000047cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997807775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d100",
1165
1247
  "signatureCount": 2,
1166
1248
  "status": "success",
1167
1249
  "threshold": 2,
@@ -1179,7 +1261,7 @@ describe('from', () => {
1179
1261
  KeyAuthorization.from(authorization, {
1180
1262
  signature: {
1181
1263
  account,
1182
- init: config,
1264
+ config,
1183
1265
  signatures: [
1184
1266
  SignatureEnvelope.deserialize(approval_1),
1185
1267
  SignatureEnvelope.deserialize(approval_2),
@@ -1191,11 +1273,12 @@ describe('from', () => {
1191
1273
  const operation = MultisigOperation.from({
1192
1274
  ...keyAuthorizationPending,
1193
1275
  approvals: [approval_1, approval_2],
1276
+ config,
1194
1277
  configVersion: 0n,
1195
1278
  hash: MultisigConfig.getSignPayload({
1196
1279
  account,
1280
+ config,
1197
1281
  payload: KeyAuthorization.getSignPayload(authorization),
1198
- version: 0n,
1199
1282
  }),
1200
1283
  init: true,
1201
1284
  keyAuthorization: keyAuthorization_,
@@ -1229,6 +1312,7 @@ describe('from', () => {
1229
1312
  ],
1230
1313
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
1231
1314
  "threshold": 2,
1315
+ "version": 0n,
1232
1316
  },
1233
1317
  "configVersion": 0n,
1234
1318
  "createdAt": 1,
@@ -1252,6 +1336,9 @@ describe('RPC conversion', () => {
1252
1336
  const transactionRpc = MultisigOperation.toRpc(transactionPending)
1253
1337
  const keyAuthorizationRpc = MultisigOperation.toRpc(keyAuthorizationPending)
1254
1338
 
1339
+ expect(() =>
1340
+ JSON.stringify({ keyAuthorizationRpc, transactionRpc }),
1341
+ ).not.toThrow()
1255
1342
  expect({ keyAuthorizationRpc, transactionRpc }).toMatchInlineSnapshot(`
1256
1343
  {
1257
1344
  "keyAuthorizationRpc": {
@@ -1272,6 +1359,7 @@ describe('RPC conversion', () => {
1272
1359
  ],
1273
1360
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
1274
1361
  "threshold": 2,
1362
+ "version": "0x1",
1275
1363
  },
1276
1364
  "configVersion": "0x1",
1277
1365
  "createdAt": 1,
@@ -1303,6 +1391,7 @@ describe('RPC conversion', () => {
1303
1391
  ],
1304
1392
  "salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
1305
1393
  "threshold": 2,
1394
+ "version": "0x1",
1306
1395
  },
1307
1396
  "configVersion": "0x1",
1308
1397
  "createdAt": 1,
@@ -1440,10 +1529,10 @@ describe('validation', () => {
1440
1529
  account: '0x0000000000000000000000000000000000000000',
1441
1530
  hash: MultisigConfig.getSignPayload({
1442
1531
  account: '0x0000000000000000000000000000000000000000',
1532
+ config: initializedConfig,
1443
1533
  payload: TxEnvelopeTempo.getSignPayload(
1444
1534
  TxEnvelopeTempo.deserialize(transaction),
1445
1535
  ),
1446
- version: 1n,
1447
1536
  }),
1448
1537
  },
1449
1538
  },
@@ -1513,7 +1602,7 @@ describe('validation', () => {
1513
1602
  approvals: [
1514
1603
  SignatureEnvelope.serialize({
1515
1604
  account,
1516
- init: config,
1605
+ config,
1517
1606
  signatures: [ownerSignature_1],
1518
1607
  type: 'multisig',
1519
1608
  }),
@@ -1530,6 +1619,17 @@ describe('validation', () => {
1530
1619
  ).toThrowError(MultisigOperation.InvalidOperationError)
1531
1620
  })
1532
1621
 
1622
+ test('rejects mismatched config versions', () => {
1623
+ expect(() =>
1624
+ MultisigOperation.from({
1625
+ ...transactionPending,
1626
+ config: { ...initializedConfig, version: 2n },
1627
+ }),
1628
+ ).toThrowErrorMatchingInlineSnapshot(
1629
+ `[MultisigOperation.InvalidOperationError: Invalid multisig operation: config.version must equal configVersion.]`,
1630
+ )
1631
+ })
1632
+
1533
1633
  test('rejects noncanonical RPC quantities', () => {
1534
1634
  expect(() =>
1535
1635
  MultisigOperation.fromRpc({
@@ -1550,6 +1650,7 @@ describe('validation', () => {
1550
1650
  KeyAuthorization.from(authorization, {
1551
1651
  signature: {
1552
1652
  account,
1653
+ config: initializedConfig,
1553
1654
  signatures: [
1554
1655
  SignatureEnvelope.deserialize(approval_1),
1555
1656
  SignatureEnvelope.deserialize(approval_3),
@@ -1573,12 +1674,12 @@ describe('validation', () => {
1573
1674
  const signatures = [
1574
1675
  ...SignatureEnvelope.sortMultisigApprovals({
1575
1676
  account,
1677
+ config: initializedConfig,
1576
1678
  payload: KeyAuthorization.getSignPayload(authorization),
1577
1679
  signatures: [
1578
1680
  SignatureEnvelope.deserialize(approval_1),
1579
1681
  SignatureEnvelope.deserialize(approval_2),
1580
1682
  ],
1581
- version: 1n,
1582
1683
  }),
1583
1684
  ].reverse()
1584
1685
  const operation = {
@@ -1586,7 +1687,12 @@ describe('validation', () => {
1586
1687
  approvals: [approval_1, approval_2],
1587
1688
  keyAuthorization: KeyAuthorization.serialize(
1588
1689
  KeyAuthorization.from(authorization, {
1589
- signature: { account, signatures, type: 'multisig' },
1690
+ signature: {
1691
+ account,
1692
+ config: initializedConfig,
1693
+ signatures,
1694
+ type: 'multisig',
1695
+ },
1590
1696
  }),
1591
1697
  ),
1592
1698
  signatureCount: 2,
@@ -1608,6 +1714,7 @@ describe('validation', () => {
1608
1714
  KeyAuthorization.from(authorization, {
1609
1715
  signature: {
1610
1716
  account,
1717
+ config: initializedConfig,
1611
1718
  signatures: [
1612
1719
  SignatureEnvelope.deserialize(approval_1),
1613
1720
  SignatureEnvelope.deserialize(approval_1),
@@ -1628,37 +1735,49 @@ describe('validation', () => {
1628
1735
 
1629
1736
  test('rejects reordered nested key authorization approvals', () => {
1630
1737
  const authorization = KeyAuthorization.deserialize(keyAuthorization)
1738
+ const nestedConfig = MultisigConfig.from({
1739
+ owners: [{ owner: owner_2, weight: 1 }],
1740
+ threshold: 1,
1741
+ version: 1n,
1742
+ })
1631
1743
  const childSignatures = SignatureEnvelope.sortMultisigApprovals({
1632
1744
  account: owner_1,
1745
+ config: nestedConfig,
1633
1746
  payload: keyAuthorizationHash,
1634
1747
  signatures: [
1635
1748
  SignatureEnvelope.deserialize(approval_1),
1636
1749
  SignatureEnvelope.deserialize(approval_2),
1637
1750
  ],
1638
- version: 1n,
1639
1751
  })
1640
1752
  const retainedNested = SignatureEnvelope.from({
1641
1753
  account: owner_1,
1754
+ config: nestedConfig,
1642
1755
  signatures: childSignatures,
1643
1756
  type: 'multisig',
1644
1757
  })
1645
1758
  const selectedNested = SignatureEnvelope.from({
1646
1759
  account: owner_1,
1760
+ config: nestedConfig,
1647
1761
  signatures: [...childSignatures].reverse(),
1648
1762
  type: 'multisig',
1649
1763
  })
1650
1764
  const selected = SignatureEnvelope.sortMultisigApprovals({
1651
1765
  account,
1766
+ config: initializedConfig,
1652
1767
  payload: KeyAuthorization.getSignPayload(authorization),
1653
1768
  signatures: [selectedNested, SignatureEnvelope.deserialize(approval_2)],
1654
- version: 1n,
1655
1769
  })
1656
1770
  const operation = {
1657
1771
  ...keyAuthorizationPending,
1658
1772
  approvals: [SignatureEnvelope.serialize(retainedNested), approval_2],
1659
1773
  keyAuthorization: KeyAuthorization.serialize(
1660
1774
  KeyAuthorization.from(authorization, {
1661
- signature: { account, signatures: selected, type: 'multisig' },
1775
+ signature: {
1776
+ account,
1777
+ config: initializedConfig,
1778
+ signatures: selected,
1779
+ type: 'multisig',
1780
+ },
1662
1781
  }),
1663
1782
  ),
1664
1783
  signatureCount: 2,
@@ -1697,12 +1816,12 @@ describe('validation', () => {
1697
1816
  })
1698
1817
  const signatures = SignatureEnvelope.sortMultisigApprovals({
1699
1818
  account,
1819
+ config,
1700
1820
  payload: KeyAuthorization.getSignPayload(authorization),
1701
1821
  signatures: [
1702
1822
  SignatureEnvelope.deserialize(approval_1),
1703
1823
  SignatureEnvelope.deserialize(approval_2),
1704
1824
  ],
1705
- version: 0n,
1706
1825
  })
1707
1826
  const approvals = signatures.map((signature) =>
1708
1827
  SignatureEnvelope.serialize(signature),
@@ -1716,15 +1835,15 @@ describe('validation', () => {
1716
1835
  createdAt: 1,
1717
1836
  hash: MultisigConfig.getSignPayload({
1718
1837
  account,
1838
+ config,
1719
1839
  payload: KeyAuthorization.getSignPayload(authorization),
1720
- version: 0n,
1721
1840
  }),
1722
1841
  init: true,
1723
1842
  keyAuthorization: KeyAuthorization.serialize(
1724
1843
  KeyAuthorization.from(authorization, {
1725
1844
  signature: {
1726
1845
  account,
1727
- init: config,
1846
+ config,
1728
1847
  signatures,
1729
1848
  type: 'multisig',
1730
1849
  },