ox 0.14.39 → 0.14.41

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 (54) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/_cjs/tempo/MultisigOperation.js +30 -45
  3. package/_cjs/tempo/MultisigOperation.js.map +1 -1
  4. package/_cjs/tempo/MultisigWitness.js +92 -0
  5. package/_cjs/tempo/MultisigWitness.js.map +1 -0
  6. package/_cjs/tempo/SignatureEnvelope.js +5 -2
  7. package/_cjs/tempo/SignatureEnvelope.js.map +1 -1
  8. package/_cjs/tempo/TransactionRequest.js +7 -1
  9. package/_cjs/tempo/TransactionRequest.js.map +1 -1
  10. package/_cjs/tempo/index.js +2 -1
  11. package/_cjs/tempo/index.js.map +1 -1
  12. package/_cjs/version.js +1 -1
  13. package/_esm/tempo/MultisigOperation.js +31 -48
  14. package/_esm/tempo/MultisigOperation.js.map +1 -1
  15. package/_esm/tempo/MultisigWitness.js +123 -0
  16. package/_esm/tempo/MultisigWitness.js.map +1 -0
  17. package/_esm/tempo/SignatureEnvelope.js +5 -2
  18. package/_esm/tempo/SignatureEnvelope.js.map +1 -1
  19. package/_esm/tempo/TransactionRequest.js +7 -1
  20. package/_esm/tempo/TransactionRequest.js.map +1 -1
  21. package/_esm/tempo/index.js +9 -0
  22. package/_esm/tempo/index.js.map +1 -1
  23. package/_esm/version.js +1 -1
  24. package/_types/tempo/MultisigOperation.d.ts +4 -25
  25. package/_types/tempo/MultisigOperation.d.ts.map +1 -1
  26. package/_types/tempo/MultisigWitness.d.ts +106 -0
  27. package/_types/tempo/MultisigWitness.d.ts.map +1 -0
  28. package/_types/tempo/SignatureEnvelope.d.ts +3 -3
  29. package/_types/tempo/SignatureEnvelope.d.ts.map +1 -1
  30. package/_types/tempo/TransactionRequest.d.ts +6 -3
  31. package/_types/tempo/TransactionRequest.d.ts.map +1 -1
  32. package/_types/tempo/index.d.ts +9 -0
  33. package/_types/tempo/index.d.ts.map +1 -1
  34. package/_types/version.d.ts +1 -1
  35. package/package.json +16 -1
  36. package/tempo/KeyAuthorization.test-d.ts +1 -1
  37. package/tempo/MultisigOperation.test-d.ts +0 -6
  38. package/tempo/MultisigOperation.test.ts +196 -145
  39. package/tempo/MultisigOperation.ts +40 -83
  40. package/tempo/MultisigWitness/package.json +6 -0
  41. package/tempo/MultisigWitness.test-d/package.json +6 -0
  42. package/tempo/MultisigWitness.test-d.ts +42 -0
  43. package/tempo/MultisigWitness.test.ts +289 -0
  44. package/tempo/MultisigWitness.ts +210 -0
  45. package/tempo/RpcSchemaTempo.test-d.ts +25 -0
  46. package/tempo/SignatureEnvelope.test-d.ts +4 -4
  47. package/tempo/SignatureEnvelope.test.ts +2 -2
  48. package/tempo/SignatureEnvelope.ts +9 -5
  49. package/tempo/TransactionRequest.test-d/package.json +6 -0
  50. package/tempo/TransactionRequest.test-d.ts +24 -0
  51. package/tempo/TransactionRequest.test.ts +102 -1
  52. package/tempo/TransactionRequest.ts +12 -2
  53. package/tempo/index.ts +9 -0
  54. package/version.ts +1 -1
@@ -36,7 +36,7 @@ const config = MultisigConfig.from({
36
36
  ],
37
37
  threshold: 2,
38
38
  })
39
- const initializedConfig = MultisigConfig.from({ ...config, version: 1n })
39
+ const currentConfig = MultisigConfig.from({ ...config, version: 1n })
40
40
  const account = MultisigConfig.getAddress(config)
41
41
  const ownerSignature_1 = owners[0]!.signature
42
42
  const approval_1 = SignatureEnvelope.serialize(ownerSignature_1)
@@ -63,14 +63,14 @@ const keyAuthorization = KeyAuthorization.serialize(
63
63
 
64
64
  const transactionHash_ = MultisigConfig.getSignPayload({
65
65
  account,
66
- config: initializedConfig,
66
+ config: currentConfig,
67
67
  payload: TxEnvelopeTempo.getSignPayload(
68
68
  TxEnvelopeTempo.deserialize(transaction),
69
69
  ),
70
70
  })
71
71
  const keyAuthorizationHash = MultisigConfig.getSignPayload({
72
72
  account,
73
- config: initializedConfig,
73
+ config: currentConfig,
74
74
  payload: KeyAuthorization.getSignPayload(
75
75
  KeyAuthorization.deserialize(keyAuthorization),
76
76
  ),
@@ -79,10 +79,8 @@ const keyAuthorizationHash = MultisigConfig.getSignPayload({
79
79
  const base = {
80
80
  account,
81
81
  approvals: [approval_1],
82
- config: initializedConfig,
83
- configVersion: 1n,
82
+ config: currentConfig,
84
83
  createdAt: 1,
85
- init: false,
86
84
  signatureCount: 1,
87
85
  threshold: 2,
88
86
  updatedAt: 2,
@@ -139,13 +137,13 @@ describe('getHash', () => {
139
137
  expect({
140
138
  keyAuthorization: MultisigOperation.getHash({
141
139
  account,
142
- configVersion: 1n,
140
+ config: currentConfig,
143
141
  keyAuthorization,
144
142
  type: 'keyAuthorization',
145
143
  }),
146
144
  transaction: MultisigOperation.getHash({
147
145
  account,
148
- configVersion: 1n,
146
+ config: currentConfig,
149
147
  transaction,
150
148
  type: 'transaction',
151
149
  }),
@@ -171,7 +169,7 @@ describe('selectApprovals', () => {
171
169
  const account = MultisigConfig.getAddress(config)
172
170
  const hash = MultisigOperation.getHash({
173
171
  account,
174
- configVersion: 1n,
172
+ config: { ...config, version: 1n },
175
173
  transaction,
176
174
  type: 'transaction',
177
175
  })
@@ -244,13 +242,13 @@ describe('selectApprovals', () => {
244
242
  const account = MultisigConfig.getAddress(config)
245
243
  const hash = MultisigOperation.getHash({
246
244
  account,
247
- configVersion: 1n,
245
+ config: { ...config, version: 1n },
248
246
  transaction,
249
247
  type: 'transaction',
250
248
  })
251
249
  const childHash = MultisigConfig.getSignPayload({
252
250
  account: child,
253
- config: { version: 2n },
251
+ config: { ...childConfig, version: 2n },
254
252
  payload: hash,
255
253
  })
256
254
  const childApprovals = [
@@ -258,12 +256,6 @@ describe('selectApprovals', () => {
258
256
  signApproval(owners[2]!, childHash),
259
257
  ]
260
258
  const rootApproval = signApproval(owners[0]!, hash)
261
- const resolveConfig: MultisigOperation.selectApprovals.ResolveConfig = ({
262
- account,
263
- }) => {
264
- if (!Address.isEqual(account, child)) throw new Error('unknown account')
265
- return { config: childConfig, version: 2n }
266
- }
267
259
  const partial = await MultisigOperation.selectApprovals({
268
260
  account,
269
261
  approvals: [
@@ -277,7 +269,6 @@ describe('selectApprovals', () => {
277
269
  ],
278
270
  config,
279
271
  hash,
280
- resolveConfig,
281
272
  })
282
273
  const complete = await MultisigOperation.selectApprovals({
283
274
  account,
@@ -294,7 +285,6 @@ describe('selectApprovals', () => {
294
285
  ],
295
286
  config,
296
287
  hash,
297
- resolveConfig,
298
288
  })
299
289
 
300
290
  expect({
@@ -338,10 +328,95 @@ describe('selectApprovals', () => {
338
328
  `)
339
329
  })
340
330
 
331
+ test('rejects conflicting nested config witnesses', async () => {
332
+ const childConfig = MultisigConfig.from({
333
+ owners: [{ owner: owners[1]!.address, weight: 1 }],
334
+ threshold: 1,
335
+ })
336
+ const child = MultisigConfig.getAddress(childConfig)
337
+ const config = MultisigConfig.from({
338
+ owners: [{ owner: child, weight: 1 }],
339
+ threshold: 1,
340
+ })
341
+ const account = MultisigConfig.getAddress(config)
342
+ const hash = MultisigOperation.getHash({
343
+ account,
344
+ config: { ...config, version: 1n },
345
+ transaction,
346
+ type: 'transaction',
347
+ })
348
+ const config_2 = MultisigConfig.from({
349
+ ...childConfig,
350
+ version: 2n,
351
+ })
352
+ const config_3 = MultisigConfig.from({
353
+ ...childConfig,
354
+ version: 3n,
355
+ })
356
+ const childHash_2 = MultisigConfig.getSignPayload({
357
+ account: child,
358
+ config: config_2,
359
+ payload: hash,
360
+ })
361
+ const childHash_3 = MultisigConfig.getSignPayload({
362
+ account: child,
363
+ config: config_3,
364
+ payload: hash,
365
+ })
366
+
367
+ await expect(
368
+ MultisigOperation.selectApprovals({
369
+ account,
370
+ approvals: [
371
+ SignatureEnvelope.serialize({
372
+ account: child,
373
+ config: config_2,
374
+ signatures: [
375
+ SignatureEnvelope.deserialize(
376
+ signApproval(owners[1]!, childHash_2),
377
+ ),
378
+ ],
379
+ type: 'multisig',
380
+ }),
381
+ SignatureEnvelope.serialize({
382
+ account: child,
383
+ config: config_3,
384
+ signatures: [
385
+ SignatureEnvelope.deserialize(
386
+ signApproval(owners[1]!, childHash_3),
387
+ ),
388
+ ],
389
+ type: 'multisig',
390
+ }),
391
+ ],
392
+ config,
393
+ hash,
394
+ }),
395
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
396
+ `[MultisigOperation.InvalidApprovalError: Invalid multisig approval: nested multisig owner 0x7888d60e9cc26c8569d394fce435c248f1e49c3b has conflicting config witnesses.]`,
397
+ )
398
+ })
399
+
400
+ test('rejects an initial root config for another account', async () => {
401
+ await expect(
402
+ MultisigOperation.selectApprovals({
403
+ account,
404
+ approvals: [],
405
+ config: MultisigConfig.from({
406
+ ...config,
407
+ salt: `0x${'ff'.repeat(32)}`,
408
+ }),
409
+ hash: transactionHash_,
410
+ }),
411
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
412
+ `[MultisigOperation.InvalidApprovalError: Invalid multisig approval: initial config does not derive the root multisig account.]`,
413
+ )
414
+ })
415
+
341
416
  test('rejects invalid and non-owner approvals', async () => {
342
417
  const hash = MultisigOperation.getHash({
343
418
  account,
344
- configVersion: 1n,
419
+ config: currentConfig,
345
420
  transaction,
346
421
  type: 'transaction',
347
422
  })
@@ -373,7 +448,7 @@ describe('selectApprovals', () => {
373
448
  )
374
449
  })
375
450
 
376
- test('requires a resolver for nested owners', async () => {
451
+ test('reads current nested config witnesses from approvals', async () => {
377
452
  const childConfig = MultisigConfig.from({
378
453
  owners: [{ owner: owners[1]!.address, weight: 1 }],
379
454
  threshold: 1,
@@ -386,36 +461,49 @@ describe('selectApprovals', () => {
386
461
  const account = MultisigConfig.getAddress(config)
387
462
  const hash = MultisigOperation.getHash({
388
463
  account,
389
- configVersion: 1n,
464
+ config: { ...config, version: 1n },
390
465
  transaction,
391
466
  type: 'transaction',
392
467
  })
393
468
  const childHash = MultisigConfig.getSignPayload({
394
469
  account: child,
395
- config: { version: 1n },
470
+ config: { ...childConfig, version: 1n },
396
471
  payload: hash,
397
472
  })
398
473
 
399
- await expect(
400
- MultisigOperation.selectApprovals({
401
- account,
402
- approvals: [
403
- SignatureEnvelope.serialize({
404
- account: child,
405
- config: MultisigConfig.from({ ...childConfig, version: 1n }),
406
- signatures: [
407
- SignatureEnvelope.deserialize(
408
- signApproval(owners[1]!, childHash),
409
- ),
410
- ],
411
- type: 'multisig',
412
- }),
474
+ const selection = await MultisigOperation.selectApprovals({
475
+ account,
476
+ approvals: [
477
+ SignatureEnvelope.serialize({
478
+ account: child,
479
+ config: MultisigConfig.from({ ...childConfig, version: 1n }),
480
+ signatures: [
481
+ SignatureEnvelope.deserialize(signApproval(owners[1]!, childHash)),
482
+ ],
483
+ type: 'multisig',
484
+ }),
485
+ ],
486
+ config,
487
+ hash,
488
+ })
489
+ expect(selection).toMatchInlineSnapshot(
490
+ {
491
+ approvals: [expect.any(String)],
492
+ selectedApprovals: [expect.any(String)],
493
+ },
494
+ `
495
+ {
496
+ "approvals": [
497
+ Any<String>,
413
498
  ],
414
- config,
415
- hash,
416
- }),
417
- ).rejects.toThrowErrorMatchingInlineSnapshot(
418
- `[MultisigOperation.InvalidApprovalError: Invalid multisig approval: nested multisig owner 0x7888d60e9cc26c8569d394fce435c248f1e49c3b requires a config resolver.]`,
499
+ "selectedApprovals": [
500
+ Any<String>,
501
+ ],
502
+ "signatureCount": 1,
503
+ "threshold": 1,
504
+ "weight": 1,
505
+ }
506
+ `,
419
507
  )
420
508
  })
421
509
 
@@ -435,7 +523,7 @@ describe('selectApprovals', () => {
435
523
  const account = MultisigConfig.getAddress(config)
436
524
  const hash = MultisigOperation.getHash({
437
525
  account,
438
- configVersion: 1n,
526
+ config: { ...config, version: 1n },
439
527
  transaction,
440
528
  type: 'transaction',
441
529
  })
@@ -477,7 +565,6 @@ describe('selectApprovals', () => {
477
565
  ],
478
566
  config,
479
567
  hash,
480
- resolveConfig: () => ({ config: childConfig, version: 0n }),
481
568
  })
482
569
  expect({
483
570
  signatureCount: selection.signatureCount,
@@ -499,7 +586,7 @@ describe('selectApprovals', () => {
499
586
  })
500
587
  const hash = MultisigOperation.getHash({
501
588
  account,
502
- configVersion: 2n,
589
+ config: { ...config, version: 2n },
503
590
  transaction,
504
591
  type: 'transaction',
505
592
  })
@@ -541,18 +628,18 @@ describe('selectApprovals', () => {
541
628
  const account = MultisigConfig.getAddress(config)
542
629
  const hash = MultisigOperation.getHash({
543
630
  account,
544
- configVersion: 1n,
631
+ config: { ...config, version: 1n },
545
632
  transaction,
546
633
  type: 'transaction',
547
634
  })
548
635
  const childHash = MultisigConfig.getSignPayload({
549
636
  account: child,
550
- config: { version: 1n },
637
+ config: { ...childConfig, version: 1n },
551
638
  payload: hash,
552
639
  })
553
640
  const grandchildHash = MultisigConfig.getSignPayload({
554
641
  account: grandchild,
555
- config: { version: 1n },
642
+ config: { ...grandchildConfig, version: 1n },
556
643
  payload: childHash,
557
644
  })
558
645
 
@@ -583,11 +670,6 @@ describe('selectApprovals', () => {
583
670
  ],
584
671
  config,
585
672
  hash,
586
- resolveConfig: ({ account }) => {
587
- if (Address.isEqual(account, child))
588
- return { config: childConfig, version: 1n }
589
- return { config: grandchildConfig, version: 1n }
590
- },
591
673
  }),
592
674
  ).rejects.toThrowErrorMatchingInlineSnapshot(
593
675
  `[MultisigOperation.InvalidApprovalError: Invalid multisig approval: nested multisig owner 0xf529c8f6b2b4c72102af4cfe5eeb55b7d45dede2 is invalid.]`,
@@ -596,13 +678,12 @@ describe('selectApprovals', () => {
596
678
  })
597
679
 
598
680
  describe('serializeTransaction', () => {
599
- test('initialized and bootstrap transactions', async () => {
681
+ test('current and initial transactions', async () => {
600
682
  const results = []
601
- for (const init of [false, true]) {
602
- const configVersion = init ? 0n : 1n
683
+ for (const applicableConfig of [currentConfig, config]) {
603
684
  const hash = MultisigOperation.getHash({
604
685
  account,
605
- configVersion,
686
+ config: applicableConfig,
606
687
  transaction,
607
688
  type: 'transaction',
608
689
  })
@@ -612,17 +693,15 @@ describe('serializeTransaction', () => {
612
693
  signApproval(owners[1]!, hash),
613
694
  signApproval(owners[0]!, hash),
614
695
  ],
615
- config,
696
+ config: applicableConfig,
616
697
  hash,
617
698
  })
618
699
  const operation = MultisigOperation.from({
619
700
  account,
620
701
  approvals: selection.approvals,
621
- config,
622
- configVersion,
702
+ config: applicableConfig,
623
703
  createdAt: 1,
624
704
  hash,
625
- init,
626
705
  signatureCount: selection.signatureCount,
627
706
  status: 'pending',
628
707
  threshold: selection.threshold,
@@ -637,7 +716,7 @@ describe('serializeTransaction', () => {
637
716
  const value = TxEnvelopeTempo.deserialize(serialized)
638
717
  results.push({
639
718
  account: value.signature?.account,
640
- configVersion:
719
+ version:
641
720
  value.signature?.type === 'multisig'
642
721
  ? value.signature.config.version
643
722
  : undefined,
@@ -654,17 +733,17 @@ describe('serializeTransaction', () => {
654
733
  [
655
734
  {
656
735
  "account": "0xf81b7763d3a6876195d780865bd783dbd97dd36e",
657
- "configVersion": 1n,
658
736
  "hash": "0x8309740edaf304284186f7bcfe4527745cd4eb48e7441795ebdd970798091f8f",
659
737
  "signatureCount": 2,
660
738
  "type": "0x76",
739
+ "version": 1n,
661
740
  },
662
741
  {
663
742
  "account": "0xf81b7763d3a6876195d780865bd783dbd97dd36e",
664
- "configVersion": 0n,
665
743
  "hash": "0x636af84d8445d87cbcd33039d5a3a2274a5911036b1b7ceb740ac41e2f638611",
666
744
  "signatureCount": 2,
667
745
  "type": "0x76",
746
+ "version": 0n,
668
747
  },
669
748
  ]
670
749
  `)
@@ -692,7 +771,7 @@ describe('serializeTransaction', () => {
692
771
  for (const transaction of transactions) {
693
772
  const hash = MultisigOperation.getHash({
694
773
  account,
695
- configVersion: 1n,
774
+ config: currentConfig,
696
775
  transaction,
697
776
  type: 'transaction',
698
777
  })
@@ -702,18 +781,16 @@ describe('serializeTransaction', () => {
702
781
  signApproval(owners[0]!, hash),
703
782
  signApproval(owners[1]!, hash),
704
783
  ],
705
- config,
784
+ config: currentConfig,
706
785
  hash,
707
786
  })
708
787
  const serialized = MultisigOperation.serializeTransaction(
709
788
  MultisigOperation.from({
710
789
  account,
711
790
  approvals: selection.approvals,
712
- config,
713
- configVersion: 1n,
791
+ config: currentConfig,
714
792
  createdAt: 1,
715
793
  hash,
716
- init: false,
717
794
  signatureCount: selection.signatureCount,
718
795
  status: 'pending',
719
796
  threshold: selection.threshold,
@@ -761,7 +838,7 @@ describe('serializeTransaction', () => {
761
838
  test('rejects an approval not retained by the operation', async () => {
762
839
  const hash = MultisigOperation.getHash({
763
840
  account,
764
- configVersion: 1n,
841
+ config: currentConfig,
765
842
  transaction,
766
843
  type: 'transaction',
767
844
  })
@@ -770,17 +847,15 @@ describe('serializeTransaction', () => {
770
847
  const selection = await MultisigOperation.selectApprovals({
771
848
  account,
772
849
  approvals: [approval_1],
773
- config,
850
+ config: currentConfig,
774
851
  hash,
775
852
  })
776
853
  const operation = MultisigOperation.from({
777
854
  account,
778
855
  approvals: selection.approvals,
779
- config,
780
- configVersion: 1n,
856
+ config: currentConfig,
781
857
  createdAt: 1,
782
858
  hash,
783
- init: false,
784
859
  signatureCount: selection.signatureCount,
785
860
  status: 'pending',
786
861
  threshold: selection.threshold,
@@ -843,10 +918,8 @@ describe('from', () => {
843
918
  "threshold": 2,
844
919
  "version": 1n,
845
920
  },
846
- "configVersion": 1n,
847
921
  "createdAt": 1,
848
922
  "hash": "0xcdbc24a8fb192f799c5d166b13a99fb29cbb15e71a5e730988d6f8b3c5959d02",
849
- "init": false,
850
923
  "signatureCount": 1,
851
924
  "status": "pending",
852
925
  "threshold": 2,
@@ -876,11 +949,9 @@ describe('from', () => {
876
949
  "threshold": 2,
877
950
  "version": 1n,
878
951
  },
879
- "configVersion": 1n,
880
952
  "createdAt": 1,
881
953
  "expiresAt": 10,
882
954
  "hash": "0xcdbc24a8fb192f799c5d166b13a99fb29cbb15e71a5e730988d6f8b3c5959d02",
883
- "init": false,
884
955
  "signatureCount": 2,
885
956
  "status": "submitting",
886
957
  "submissionId": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
@@ -911,10 +982,8 @@ describe('from', () => {
911
982
  "threshold": 2,
912
983
  "version": 1n,
913
984
  },
914
- "configVersion": 1n,
915
985
  "createdAt": 1,
916
986
  "hash": "0xcdbc24a8fb192f799c5d166b13a99fb29cbb15e71a5e730988d6f8b3c5959d02",
917
- "init": false,
918
987
  "signatureCount": 2,
919
988
  "status": "success",
920
989
  "threshold": 2,
@@ -940,7 +1009,7 @@ describe('from', () => {
940
1009
  ...transactionPending,
941
1010
  hash: MultisigConfig.getSignPayload({
942
1011
  account,
943
- config: initializedConfig,
1012
+ config: currentConfig,
944
1013
  payload: TxEnvelopeTempo.getSignPayload(
945
1014
  TxEnvelopeTempo.deserialize(transaction),
946
1015
  ),
@@ -974,10 +1043,8 @@ describe('from', () => {
974
1043
  "threshold": 2,
975
1044
  "version": 1n,
976
1045
  },
977
- "configVersion": 1n,
978
1046
  "createdAt": 1,
979
1047
  "hash": Any<String>,
980
- "init": false,
981
1048
  "signatureCount": 1,
982
1049
  "status": "pending",
983
1050
  "threshold": 2,
@@ -1003,7 +1070,7 @@ describe('from', () => {
1003
1070
  ...transactionPending,
1004
1071
  hash: MultisigConfig.getSignPayload({
1005
1072
  account,
1006
- config: initializedConfig,
1073
+ config: currentConfig,
1007
1074
  payload: TxEnvelopeTempo.getSignPayload(
1008
1075
  TxEnvelopeTempo.deserialize(transaction),
1009
1076
  ),
@@ -1014,10 +1081,10 @@ describe('from', () => {
1014
1081
  expect(operation.transaction).toBe(transaction)
1015
1082
  })
1016
1083
 
1017
- test('bootstrap transaction', () => {
1084
+ test('initial transaction', () => {
1018
1085
  const operation = MultisigOperation.from({
1019
1086
  ...transactionPending,
1020
- configVersion: 0n,
1087
+ config,
1021
1088
  hash: MultisigConfig.getSignPayload({
1022
1089
  account,
1023
1090
  config,
@@ -1025,7 +1092,6 @@ describe('from', () => {
1025
1092
  TxEnvelopeTempo.deserialize(transaction),
1026
1093
  ),
1027
1094
  }),
1028
- init: true,
1029
1095
  })
1030
1096
 
1031
1097
  expect(operation).toMatchInlineSnapshot(
@@ -1054,10 +1120,8 @@ describe('from', () => {
1054
1120
  "threshold": 2,
1055
1121
  "version": 0n,
1056
1122
  },
1057
- "configVersion": 0n,
1058
1123
  "createdAt": 1,
1059
1124
  "hash": Any<String>,
1060
- "init": true,
1061
1125
  "signatureCount": 1,
1062
1126
  "status": "pending",
1063
1127
  "threshold": 2,
@@ -1070,30 +1134,6 @@ describe('from', () => {
1070
1134
  )
1071
1135
  })
1072
1136
 
1073
- test('initialized transaction at config version zero', () => {
1074
- const operation = MultisigOperation.from({
1075
- ...transactionPending,
1076
- configVersion: 0n,
1077
- hash: MultisigConfig.getSignPayload({
1078
- account,
1079
- config,
1080
- payload: TxEnvelopeTempo.getSignPayload(
1081
- TxEnvelopeTempo.deserialize(transaction),
1082
- ),
1083
- }),
1084
- })
1085
-
1086
- expect({
1087
- configVersion: operation.configVersion,
1088
- init: operation.init,
1089
- }).toMatchInlineSnapshot(`
1090
- {
1091
- "configVersion": 0n,
1092
- "init": false,
1093
- }
1094
- `)
1095
- })
1096
-
1097
1137
  test('key authorization states', () => {
1098
1138
  const pending = MultisigOperation.from(keyAuthorizationPending)
1099
1139
  const authorization = KeyAuthorization.deserialize(keyAuthorization)
@@ -1104,7 +1144,7 @@ describe('from', () => {
1104
1144
  KeyAuthorization.from(authorization, {
1105
1145
  signature: {
1106
1146
  account,
1107
- config: initializedConfig,
1147
+ config: currentConfig,
1108
1148
  signatures: [
1109
1149
  SignatureEnvelope.deserialize(approval_1),
1110
1150
  SignatureEnvelope.deserialize(approval_2),
@@ -1140,10 +1180,8 @@ describe('from', () => {
1140
1180
  "threshold": 2,
1141
1181
  "version": 1n,
1142
1182
  },
1143
- "configVersion": 1n,
1144
1183
  "createdAt": 1,
1145
1184
  "hash": "0xf6995eb69c12c03d3d13b357abf7cac22b4effe52fba8ff02e5aef26161f77a0",
1146
- "init": false,
1147
1185
  "keyAuthorization": "0xf838f782107980943333333333333333333333333333333333333333846b49d2008080808094f81b7763d3a6876195d780865bd783dbd97dd36e",
1148
1186
  "signatureCount": 1,
1149
1187
  "status": "pending",
@@ -1173,10 +1211,8 @@ describe('from', () => {
1173
1211
  "threshold": 2,
1174
1212
  "version": 1n,
1175
1213
  },
1176
- "configVersion": 1n,
1177
1214
  "createdAt": 1,
1178
1215
  "hash": "0xf6995eb69c12c03d3d13b357abf7cac22b4effe52fba8ff02e5aef26161f77a0",
1179
- "init": false,
1180
1216
  "keyAuthorization": "0xf901b3f782107980943333333333333333333333333333333333333333846b49d2008080808094f81b7763d3a6876195d780865bd783dbd97dd36eb9017805f9017494f81b7763d3a6876195d780865bd783dbd97dd36ef852a000000000000000000000000000000000000000000000000000000000000000000102eed69407e1ed8ea0e9601e5546b0a03aed683df360140701d694288f0cd85005f34168f731a468aef268c2f9456f01f90108b88201000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000065ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c8734640c4998ff7e374b06ce1a64a2ecd82ab036384fb83d9a79b127a27d503200b88201000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000047cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997807775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d100",
1181
1217
  "signatureCount": 2,
1182
1218
  "status": "success",
@@ -1189,7 +1225,7 @@ describe('from', () => {
1189
1225
  `)
1190
1226
  })
1191
1227
 
1192
- test('bootstrap key authorization', () => {
1228
+ test('initial key authorization', () => {
1193
1229
  const authorization = KeyAuthorization.deserialize(keyAuthorization)
1194
1230
  const keyAuthorization_ = KeyAuthorization.serialize(
1195
1231
  KeyAuthorization.from(authorization, {
@@ -1207,13 +1243,12 @@ describe('from', () => {
1207
1243
  const operation = MultisigOperation.from({
1208
1244
  ...keyAuthorizationPending,
1209
1245
  approvals: [approval_1, approval_2],
1210
- configVersion: 0n,
1246
+ config,
1211
1247
  hash: MultisigConfig.getSignPayload({
1212
1248
  account,
1213
1249
  config,
1214
1250
  payload: KeyAuthorization.getSignPayload(authorization),
1215
1251
  }),
1216
- init: true,
1217
1252
  keyAuthorization: keyAuthorization_,
1218
1253
  signatureCount: 2,
1219
1254
  status: 'success',
@@ -1247,10 +1282,8 @@ describe('from', () => {
1247
1282
  "threshold": 2,
1248
1283
  "version": 0n,
1249
1284
  },
1250
- "configVersion": 0n,
1251
1285
  "createdAt": 1,
1252
1286
  "hash": Any<String>,
1253
- "init": true,
1254
1287
  "keyAuthorization": Any<String>,
1255
1288
  "signatureCount": 2,
1256
1289
  "status": "success",
@@ -1294,10 +1327,8 @@ describe('RPC conversion', () => {
1294
1327
  "threshold": 2,
1295
1328
  "version": "0x1",
1296
1329
  },
1297
- "configVersion": "0x1",
1298
1330
  "createdAt": 1,
1299
1331
  "hash": "0xf6995eb69c12c03d3d13b357abf7cac22b4effe52fba8ff02e5aef26161f77a0",
1300
- "init": false,
1301
1332
  "keyAuthorization": "0xf838f782107980943333333333333333333333333333333333333333846b49d2008080808094f81b7763d3a6876195d780865bd783dbd97dd36e",
1302
1333
  "signatureCount": 1,
1303
1334
  "status": "pending",
@@ -1326,10 +1357,8 @@ describe('RPC conversion', () => {
1326
1357
  "threshold": 2,
1327
1358
  "version": "0x1",
1328
1359
  },
1329
- "configVersion": "0x1",
1330
1360
  "createdAt": 1,
1331
1361
  "hash": "0xcdbc24a8fb192f799c5d166b13a99fb29cbb15e71a5e730988d6f8b3c5959d02",
1332
- "init": false,
1333
1362
  "signatureCount": 1,
1334
1363
  "status": "pending",
1335
1364
  "threshold": 2,
@@ -1462,7 +1491,7 @@ describe('validation', () => {
1462
1491
  account: '0x0000000000000000000000000000000000000000',
1463
1492
  hash: MultisigConfig.getSignPayload({
1464
1493
  account: '0x0000000000000000000000000000000000000000',
1465
- config: initializedConfig,
1494
+ config: currentConfig,
1466
1495
  payload: TxEnvelopeTempo.getSignPayload(
1467
1496
  TxEnvelopeTempo.deserialize(transaction),
1468
1497
  ),
@@ -1529,7 +1558,7 @@ describe('validation', () => {
1529
1558
  },
1530
1559
  },
1531
1560
  {
1532
- name: 'nested bootstrap owner approval',
1561
+ name: 'nested non-owner approval',
1533
1562
  operation: {
1534
1563
  ...transactionPending,
1535
1564
  approvals: [
@@ -1542,24 +1571,48 @@ describe('validation', () => {
1542
1571
  ],
1543
1572
  },
1544
1573
  },
1545
- {
1546
- name: 'bootstrap with initialized version',
1547
- operation: { ...transactionPending, init: true },
1548
- },
1549
1574
  ])('rejects $name', ({ operation }) => {
1550
1575
  expect(() =>
1551
1576
  MultisigOperation.from(operation as MultisigOperation.Operation),
1552
1577
  ).toThrowError(MultisigOperation.InvalidOperationError)
1553
1578
  })
1554
1579
 
1580
+ test('rejects an initial config for another account', () => {
1581
+ const config = MultisigConfig.from({
1582
+ ...transactionPending.config,
1583
+ salt: `0x${'ff'.repeat(32)}`,
1584
+ version: 0n,
1585
+ })
1586
+ expect(() =>
1587
+ MultisigOperation.from({
1588
+ ...transactionPending,
1589
+ config,
1590
+ hash: MultisigConfig.getSignPayload({
1591
+ account,
1592
+ config,
1593
+ payload: TxEnvelopeTempo.getSignPayload(
1594
+ TxEnvelopeTempo.deserialize(transaction),
1595
+ ),
1596
+ }),
1597
+ }),
1598
+ ).toThrowErrorMatchingInlineSnapshot(
1599
+ `
1600
+ [MultisigOperation.InvalidOperationError: Invalid multisig operation.
1601
+
1602
+ Details: Invalid native multisig owner approval: initial multisig config does not derive account.]
1603
+ `,
1604
+ )
1605
+ })
1606
+
1555
1607
  test('rejects noncanonical RPC quantities', () => {
1608
+ const operation = MultisigOperation.toRpc(transactionPending)
1556
1609
  expect(() =>
1557
1610
  MultisigOperation.fromRpc({
1558
- ...MultisigOperation.toRpc(transactionPending),
1559
- configVersion: '0x01',
1611
+ ...operation,
1612
+ config: { ...operation.config, version: '0x01' },
1560
1613
  }),
1561
1614
  ).toThrowError(
1562
- 'Invalid multisig operation: configVersion must use canonical quantity encoding.',
1615
+ 'Invalid multisig operation: config.version must use canonical quantity encoding.',
1563
1616
  )
1564
1617
  })
1565
1618
 
@@ -1572,7 +1625,7 @@ describe('validation', () => {
1572
1625
  KeyAuthorization.from(authorization, {
1573
1626
  signature: {
1574
1627
  account,
1575
- config: initializedConfig,
1628
+ config: currentConfig,
1576
1629
  signatures: [
1577
1630
  SignatureEnvelope.deserialize(approval_1),
1578
1631
  SignatureEnvelope.deserialize(approval_3),
@@ -1596,7 +1649,7 @@ describe('validation', () => {
1596
1649
  const signatures = [
1597
1650
  ...SignatureEnvelope.sortMultisigApprovals({
1598
1651
  account,
1599
- config: initializedConfig,
1652
+ config: currentConfig,
1600
1653
  payload: KeyAuthorization.getSignPayload(authorization),
1601
1654
  signatures: [
1602
1655
  SignatureEnvelope.deserialize(approval_1),
@@ -1611,7 +1664,7 @@ describe('validation', () => {
1611
1664
  KeyAuthorization.from(authorization, {
1612
1665
  signature: {
1613
1666
  account,
1614
- config: initializedConfig,
1667
+ config: currentConfig,
1615
1668
  signatures,
1616
1669
  type: 'multisig',
1617
1670
  },
@@ -1636,7 +1689,7 @@ describe('validation', () => {
1636
1689
  KeyAuthorization.from(authorization, {
1637
1690
  signature: {
1638
1691
  account,
1639
- config: initializedConfig,
1692
+ config: currentConfig,
1640
1693
  signatures: [
1641
1694
  SignatureEnvelope.deserialize(approval_1),
1642
1695
  SignatureEnvelope.deserialize(approval_1),
@@ -1685,7 +1738,7 @@ describe('validation', () => {
1685
1738
  })
1686
1739
  const selected = SignatureEnvelope.sortMultisigApprovals({
1687
1740
  account,
1688
- config: initializedConfig,
1741
+ config: currentConfig,
1689
1742
  payload: KeyAuthorization.getSignPayload(authorization),
1690
1743
  signatures: [selectedNested, SignatureEnvelope.deserialize(approval_2)],
1691
1744
  })
@@ -1696,7 +1749,7 @@ describe('validation', () => {
1696
1749
  KeyAuthorization.from(authorization, {
1697
1750
  signature: {
1698
1751
  account,
1699
- config: initializedConfig,
1752
+ config: currentConfig,
1700
1753
  signatures: selected,
1701
1754
  type: 'multisig',
1702
1755
  },
@@ -1712,7 +1765,7 @@ describe('validation', () => {
1712
1765
  )
1713
1766
  })
1714
1767
 
1715
- test('accepts case-insensitive bootstrap configs', () => {
1768
+ test('accepts case-insensitive initial configs', () => {
1716
1769
  const config = MultisigConfig.from({
1717
1770
  owners: [
1718
1771
  {
@@ -1753,14 +1806,12 @@ describe('validation', () => {
1753
1806
  account,
1754
1807
  approvals,
1755
1808
  config,
1756
- configVersion: 0n,
1757
1809
  createdAt: 1,
1758
1810
  hash: MultisigConfig.getSignPayload({
1759
1811
  account,
1760
1812
  config,
1761
1813
  payload: KeyAuthorization.getSignPayload(authorization),
1762
1814
  }),
1763
- init: true,
1764
1815
  keyAuthorization: KeyAuthorization.serialize(
1765
1816
  KeyAuthorization.from(authorization, {
1766
1817
  signature: {