ox 0.14.42 → 0.14.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/_cjs/tempo/MultisigConfig.js +9 -2
- package/_cjs/tempo/MultisigConfig.js.map +1 -1
- package/_cjs/tempo/MultisigSimulation.js +115 -0
- package/_cjs/tempo/MultisigSimulation.js.map +1 -0
- package/_cjs/tempo/SignatureEnvelope.js +12 -21
- package/_cjs/tempo/SignatureEnvelope.js.map +1 -1
- package/_cjs/tempo/TransactionRequest.js +7 -7
- package/_cjs/tempo/TransactionRequest.js.map +1 -1
- package/_cjs/tempo/index.js +2 -2
- package/_cjs/tempo/index.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/tempo/MultisigConfig.js +14 -4
- package/_esm/tempo/MultisigConfig.js.map +1 -1
- package/_esm/tempo/MultisigSimulation.js +145 -0
- package/_esm/tempo/MultisigSimulation.js.map +1 -0
- package/_esm/tempo/SignatureEnvelope.js +12 -21
- package/_esm/tempo/SignatureEnvelope.js.map +1 -1
- package/_esm/tempo/TransactionRequest.js +7 -7
- package/_esm/tempo/TransactionRequest.js.map +1 -1
- package/_esm/tempo/index.js +4 -4
- package/_esm/tempo/index.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_types/tempo/KeyAuthorization.d.ts +1 -1
- package/_types/tempo/KeyAuthorization.d.ts.map +1 -1
- package/_types/tempo/MultisigConfig.d.ts +5 -3
- package/_types/tempo/MultisigConfig.d.ts.map +1 -1
- package/_types/tempo/MultisigOperation.d.ts +2 -2
- package/_types/tempo/MultisigOperation.d.ts.map +1 -1
- package/_types/tempo/MultisigSimulation.d.ts +132 -0
- package/_types/tempo/MultisigSimulation.d.ts.map +1 -0
- package/_types/tempo/SignatureEnvelope.d.ts +10 -34
- package/_types/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/_types/tempo/TransactionRequest.d.ts +9 -9
- package/_types/tempo/TransactionRequest.d.ts.map +1 -1
- package/_types/tempo/index.d.ts +4 -4
- package/_types/tempo/index.d.ts.map +1 -1
- package/_types/version.d.ts +1 -1
- package/package.json +9 -9
- package/tempo/AuthorizationTempo.test.ts +4 -0
- package/tempo/KeyAuthorization.test-d.ts +1 -12
- package/tempo/KeyAuthorization.test.ts +37 -9
- package/tempo/KeyAuthorization.ts +3 -3
- package/tempo/MultisigConfig.test.ts +21 -5
- package/tempo/MultisigConfig.ts +18 -6
- package/tempo/MultisigOperation.test.ts +37 -37
- package/tempo/MultisigOperation.ts +2 -2
- package/tempo/MultisigSimulation/package.json +6 -0
- package/tempo/MultisigSimulation.test-d/package.json +6 -0
- package/tempo/MultisigSimulation.test-d.ts +33 -0
- package/tempo/MultisigSimulation.test.ts +284 -0
- package/tempo/MultisigSimulation.ts +266 -0
- package/tempo/RpcSchemaTempo.test-d.ts +4 -4
- package/tempo/SignatureEnvelope.test-d.ts +8 -44
- package/tempo/SignatureEnvelope.test.ts +106 -65
- package/tempo/SignatureEnvelope.ts +27 -61
- package/tempo/Transaction.test.ts +61 -0
- package/tempo/TransactionRequest.test-d.ts +9 -9
- package/tempo/TransactionRequest.test.ts +122 -49
- package/tempo/TransactionRequest.ts +20 -16
- package/tempo/index.ts +4 -4
- package/tempo/multisig.e2e.test.ts +71 -21
- package/version.ts +1 -1
- package/_cjs/tempo/MultisigWitness.js +0 -92
- package/_cjs/tempo/MultisigWitness.js.map +0 -1
- package/_esm/tempo/MultisigWitness.js +0 -123
- package/_esm/tempo/MultisigWitness.js.map +0 -1
- package/_types/tempo/MultisigWitness.d.ts +0 -106
- package/_types/tempo/MultisigWitness.d.ts.map +0 -1
- package/tempo/MultisigWitness/package.json +0 -6
- package/tempo/MultisigWitness.test-d/package.json +0 -6
- package/tempo/MultisigWitness.test-d.ts +0 -42
- package/tempo/MultisigWitness.test.ts +0 -289
- package/tempo/MultisigWitness.ts +0 -210
|
@@ -68,6 +68,9 @@ const signature_keychain_webauthn = SignatureEnvelope.from({
|
|
|
68
68
|
version: 'v2',
|
|
69
69
|
})
|
|
70
70
|
|
|
71
|
+
const signature_multisig_rpc =
|
|
72
|
+
'0xf89794c4a590afa7337e5cd5eb3aa60cacf91c5400044bf83ba000000000000000000000000000000000000000000000000000000000000000008001d7d6947e5f4552091a69125d5dfcb7b8c2659029395bdf01f843b841869437e01f64bebeb78a8a6b30bfd3a993819c8cad82c807515d9b9e9b36f98535dfaa5eebc597715d05f6ce4927747f14fa4cd2acc717fdcd3877146437f8f41b' as const
|
|
73
|
+
|
|
71
74
|
describe('assert', () => {
|
|
72
75
|
describe('secp256k1', () => {
|
|
73
76
|
test('behavior: validates valid signature', () => {
|
|
@@ -1131,7 +1134,7 @@ describe('from', () => {
|
|
|
1131
1134
|
},
|
|
1132
1135
|
`
|
|
1133
1136
|
{
|
|
1134
|
-
"account": "
|
|
1137
|
+
"account": "0xf4b916c5aea0fb199bd942389be00db0690c961f",
|
|
1135
1138
|
"config": {
|
|
1136
1139
|
"owners": [
|
|
1137
1140
|
{
|
|
@@ -2468,6 +2471,72 @@ describe('fromRpc', () => {
|
|
|
2468
2471
|
expect(envelope.keyId).toBe('0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c')
|
|
2469
2472
|
})
|
|
2470
2473
|
})
|
|
2474
|
+
|
|
2475
|
+
describe('multisig', () => {
|
|
2476
|
+
test('behavior: converts an untagged serialized multisig signature', () => {
|
|
2477
|
+
expect(
|
|
2478
|
+
SignatureEnvelope.fromRpc(signature_multisig_rpc),
|
|
2479
|
+
).toMatchInlineSnapshot(`
|
|
2480
|
+
{
|
|
2481
|
+
"account": "0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b",
|
|
2482
|
+
"config": {
|
|
2483
|
+
"owners": [
|
|
2484
|
+
{
|
|
2485
|
+
"owner": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf",
|
|
2486
|
+
"weight": 1,
|
|
2487
|
+
},
|
|
2488
|
+
],
|
|
2489
|
+
"salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
2490
|
+
"threshold": 1,
|
|
2491
|
+
"version": 0n,
|
|
2492
|
+
},
|
|
2493
|
+
"signatures": [
|
|
2494
|
+
{
|
|
2495
|
+
"signature": {
|
|
2496
|
+
"r": 60871800714128149016591846789173983752390955456021923556141688418770269698437n,
|
|
2497
|
+
"s": 24367763726302312398084372528434045669788111037623467391175388828437596076276n,
|
|
2498
|
+
"yParity": 0,
|
|
2499
|
+
},
|
|
2500
|
+
"type": "secp256k1",
|
|
2501
|
+
},
|
|
2502
|
+
],
|
|
2503
|
+
"type": "multisig",
|
|
2504
|
+
}
|
|
2505
|
+
`)
|
|
2506
|
+
})
|
|
2507
|
+
|
|
2508
|
+
test('error: rejects a payload with the transaction type byte', () => {
|
|
2509
|
+
expect(() =>
|
|
2510
|
+
SignatureEnvelope.fromRpc(`0x05${signature_multisig_rpc.slice(2)}`),
|
|
2511
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
2512
|
+
[SignatureEnvelope.InvalidSerializedError: Unable to deserialize signature envelope: invalid multisig wire shape: expected exactly three fields
|
|
2513
|
+
|
|
2514
|
+
Serialized: 0x0505f89794c4a590afa7337e5cd5eb3aa60cacf91c5400044bf83ba000000000000000000000000000000000000000000000000000000000000000008001d7d6947e5f4552091a69125d5dfcb7b8c2659029395bdf01f843b841869437e01f64bebeb78a8a6b30bfd3a993819c8cad82c807515d9b9e9b36f98535dfaa5eebc597715d05f6ce4927747f14fa4cd2acc717fdcd3877146437f8f41b]
|
|
2515
|
+
`)
|
|
2516
|
+
})
|
|
2517
|
+
|
|
2518
|
+
test('error: rejects trailing bytes', () => {
|
|
2519
|
+
expect(() =>
|
|
2520
|
+
SignatureEnvelope.fromRpc(`${signature_multisig_rpc}00`),
|
|
2521
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
2522
|
+
[SignatureEnvelope.InvalidSerializedError: Unable to deserialize signature envelope: invalid multisig RPC signature
|
|
2523
|
+
|
|
2524
|
+
Serialized: 0xf89794c4a590afa7337e5cd5eb3aa60cacf91c5400044bf83ba000000000000000000000000000000000000000000000000000000000000000008001d7d6947e5f4552091a69125d5dfcb7b8c2659029395bdf01f843b841869437e01f64bebeb78a8a6b30bfd3a993819c8cad82c807515d9b9e9b36f98535dfaa5eebc597715d05f6ce4927747f14fa4cd2acc717fdcd3877146437f8f41b00]
|
|
2525
|
+
`)
|
|
2526
|
+
})
|
|
2527
|
+
|
|
2528
|
+
test('error: rejects a structured multisig signature', () => {
|
|
2529
|
+
expect(() =>
|
|
2530
|
+
SignatureEnvelope.fromRpc({
|
|
2531
|
+
account: '0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b',
|
|
2532
|
+
config: {},
|
|
2533
|
+
signatures: [],
|
|
2534
|
+
} as never),
|
|
2535
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
2536
|
+
`[SignatureEnvelope.CoercionError: Unable to coerce value (\`{"account":"0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b","config":{},"signatures":[]}\`) to a valid signature envelope.]`,
|
|
2537
|
+
)
|
|
2538
|
+
})
|
|
2539
|
+
})
|
|
2471
2540
|
})
|
|
2472
2541
|
|
|
2473
2542
|
describe('toRpc', () => {
|
|
@@ -2565,6 +2634,7 @@ describe('toRpc', () => {
|
|
|
2565
2634
|
const rpc = SignatureEnvelope.toRpc(
|
|
2566
2635
|
signature_keychain_p256,
|
|
2567
2636
|
) as SignatureEnvelope.KeychainRpc
|
|
2637
|
+
if (typeof rpc.signature === 'string') throw new Error('unreachable')
|
|
2568
2638
|
|
|
2569
2639
|
expect(rpc.type).toBe('keychain')
|
|
2570
2640
|
expect(rpc.userAddress).toBe(signature_keychain_p256.userAddress)
|
|
@@ -2577,6 +2647,7 @@ describe('toRpc', () => {
|
|
|
2577
2647
|
const rpc = SignatureEnvelope.toRpc(
|
|
2578
2648
|
signature_keychain_webauthn,
|
|
2579
2649
|
) as SignatureEnvelope.KeychainRpc
|
|
2650
|
+
if (typeof rpc.signature === 'string') throw new Error('unreachable')
|
|
2580
2651
|
|
|
2581
2652
|
expect(rpc.type).toBe('keychain')
|
|
2582
2653
|
expect(rpc.userAddress).toBe(signature_keychain_webauthn.userAddress)
|
|
@@ -2620,6 +2691,18 @@ describe('toRpc', () => {
|
|
|
2620
2691
|
expect(rpc.keyId).toBeUndefined()
|
|
2621
2692
|
})
|
|
2622
2693
|
})
|
|
2694
|
+
|
|
2695
|
+
describe('multisig', () => {
|
|
2696
|
+
test('behavior: removes the transaction type byte', () => {
|
|
2697
|
+
const envelope = SignatureEnvelope.deserialize(
|
|
2698
|
+
`0x05${signature_multisig_rpc.slice(2)}`,
|
|
2699
|
+
)
|
|
2700
|
+
|
|
2701
|
+
expect(SignatureEnvelope.toRpc(envelope)).toMatchInlineSnapshot(
|
|
2702
|
+
`"${signature_multisig_rpc}"`,
|
|
2703
|
+
)
|
|
2704
|
+
})
|
|
2705
|
+
})
|
|
2623
2706
|
})
|
|
2624
2707
|
|
|
2625
2708
|
describe('roundtrip: toRpc <-> fromRpc', () => {
|
|
@@ -2854,18 +2937,18 @@ describe('CoercionError', () => {
|
|
|
2854
2937
|
|
|
2855
2938
|
describe('multisig', () => {
|
|
2856
2939
|
const initial =
|
|
2857
|
-
'
|
|
2940
|
+
'0x05f89794c4a590afa7337e5cd5eb3aa60cacf91c5400044bf83ba000000000000000000000000000000000000000000000000000000000000000008001d7d6947e5f4552091a69125d5dfcb7b8c2659029395bdf01f843b841869437e01f64bebeb78a8a6b30bfd3a993819c8cad82c807515d9b9e9b36f98535dfaa5eebc597715d05f6ce4927747f14fa4cd2acc717fdcd3877146437f8f41b' as const
|
|
2858
2941
|
const current =
|
|
2859
|
-
'
|
|
2942
|
+
'0x05f89794c4a590afa7337e5cd5eb3aa60cacf91c5400044bf83ba000000000000000000000000000000000000000000000000000000000000000000101d7d6942b5ad5c4795c026514f8317c7a215e218dccd6cf01f843b8414a0e5b5b4a90f08e6e8d676a73a22dc2cf022ffdcc9299512b5d9a6daf66e0504a395a2ef6f6c0f173910b875c45d01aa66d928e56ba6f49bbc8186f80268bf51b' as const
|
|
2860
2943
|
const nested =
|
|
2861
|
-
'
|
|
2944
|
+
'0x05f8f0945f0287385ec182f906c238bec5f87692d48b23f2f83ba033333333333333333333333333333333333333333333333333333333333333338001d7d69470845f2897b639686cb383799d605c52315d785501f89cb89a05f8979470845f2897b639686cb383799d605c52315d7855f83ba022222222222222222222222222222222222222222222222222222222222222228001d7d6946813eb9362372eef6200f3b1dbc3f819671cba6901f843b841032aa6f3ea7b0b7069720d0f3891983c493d149326c5c957d864ed7371b8475e3e95325079b24491f4b6d68920e4b3bacd7c6094df6ed88b8674864ab559c8fb1b' as const
|
|
2862
2945
|
|
|
2863
|
-
test('example: decodes and re-encodes the frozen initial
|
|
2946
|
+
test('example: decodes and re-encodes the frozen initial signature', () => {
|
|
2864
2947
|
const envelope = SignatureEnvelope.deserialize(initial)
|
|
2865
2948
|
|
|
2866
2949
|
expect(envelope).toMatchInlineSnapshot(`
|
|
2867
2950
|
{
|
|
2868
|
-
"account": "
|
|
2951
|
+
"account": "0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b",
|
|
2869
2952
|
"config": {
|
|
2870
2953
|
"owners": [
|
|
2871
2954
|
{
|
|
@@ -2893,12 +2976,12 @@ describe('multisig', () => {
|
|
|
2893
2976
|
expect(SignatureEnvelope.serialize(envelope)).toBe(initial)
|
|
2894
2977
|
})
|
|
2895
2978
|
|
|
2896
|
-
test('example: decodes and re-encodes the frozen current
|
|
2979
|
+
test('example: decodes and re-encodes the frozen current signature', () => {
|
|
2897
2980
|
const envelope = SignatureEnvelope.deserialize(current)
|
|
2898
2981
|
|
|
2899
2982
|
expect(envelope).toMatchInlineSnapshot(`
|
|
2900
2983
|
{
|
|
2901
|
-
"account": "
|
|
2984
|
+
"account": "0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b",
|
|
2902
2985
|
"config": {
|
|
2903
2986
|
"owners": [
|
|
2904
2987
|
{
|
|
@@ -2926,16 +3009,16 @@ describe('multisig', () => {
|
|
|
2926
3009
|
expect(SignatureEnvelope.serialize(envelope)).toBe(current)
|
|
2927
3010
|
})
|
|
2928
3011
|
|
|
2929
|
-
test('example: decodes and re-encodes the frozen nested
|
|
3012
|
+
test('example: decodes and re-encodes the frozen nested signature', () => {
|
|
2930
3013
|
const envelope = SignatureEnvelope.deserialize(nested)
|
|
2931
3014
|
|
|
2932
3015
|
expect(envelope).toMatchInlineSnapshot(`
|
|
2933
3016
|
{
|
|
2934
|
-
"account": "
|
|
3017
|
+
"account": "0x5f0287385ec182f906c238bec5f87692d48b23f2",
|
|
2935
3018
|
"config": {
|
|
2936
3019
|
"owners": [
|
|
2937
3020
|
{
|
|
2938
|
-
"owner": "
|
|
3021
|
+
"owner": "0x70845f2897b639686cb383799d605c52315d7855",
|
|
2939
3022
|
"weight": 1,
|
|
2940
3023
|
},
|
|
2941
3024
|
],
|
|
@@ -2945,7 +3028,7 @@ describe('multisig', () => {
|
|
|
2945
3028
|
},
|
|
2946
3029
|
"signatures": [
|
|
2947
3030
|
{
|
|
2948
|
-
"account": "
|
|
3031
|
+
"account": "0x70845f2897b639686cb383799d605c52315d7855",
|
|
2949
3032
|
"config": {
|
|
2950
3033
|
"owners": [
|
|
2951
3034
|
{
|
|
@@ -2995,7 +3078,7 @@ describe('multisig', () => {
|
|
|
2995
3078
|
|
|
2996
3079
|
expect(decoded).toMatchInlineSnapshot(`
|
|
2997
3080
|
[
|
|
2998
|
-
"
|
|
3081
|
+
"0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b",
|
|
2999
3082
|
[
|
|
3000
3083
|
"0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
3001
3084
|
"0x",
|
|
@@ -3014,7 +3097,7 @@ describe('multisig', () => {
|
|
|
3014
3097
|
`)
|
|
3015
3098
|
})
|
|
3016
3099
|
|
|
3017
|
-
test('behavior: round trips initial and current RPC
|
|
3100
|
+
test('behavior: round trips initial and current RPC signatures', () => {
|
|
3018
3101
|
const initialEnvelope = SignatureEnvelope.deserialize(initial)
|
|
3019
3102
|
const currentEnvelope = SignatureEnvelope.deserialize(current)
|
|
3020
3103
|
const rpc = {
|
|
@@ -3024,50 +3107,8 @@ describe('multisig', () => {
|
|
|
3024
3107
|
|
|
3025
3108
|
expect(rpc).toMatchInlineSnapshot(`
|
|
3026
3109
|
{
|
|
3027
|
-
"current":
|
|
3028
|
-
|
|
3029
|
-
"config": {
|
|
3030
|
-
"owners": [
|
|
3031
|
-
{
|
|
3032
|
-
"owner": "0x2b5ad5c4795c026514f8317c7a215e218dccd6cf",
|
|
3033
|
-
"weight": 1,
|
|
3034
|
-
},
|
|
3035
|
-
],
|
|
3036
|
-
"salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
3037
|
-
"threshold": 1,
|
|
3038
|
-
"version": 1,
|
|
3039
|
-
},
|
|
3040
|
-
"signatures": [
|
|
3041
|
-
{
|
|
3042
|
-
"r": "0x4a0e5b5b4a90f08e6e8d676a73a22dc2cf022ffdcc9299512b5d9a6daf66e050",
|
|
3043
|
-
"s": "0x4a395a2ef6f6c0f173910b875c45d01aa66d928e56ba6f49bbc8186f80268bf5",
|
|
3044
|
-
"type": "secp256k1",
|
|
3045
|
-
"yParity": "0x0",
|
|
3046
|
-
},
|
|
3047
|
-
],
|
|
3048
|
-
},
|
|
3049
|
-
"initial": {
|
|
3050
|
-
"account": "0x9dba7f426b711d4893c11611eacf7cc334e7146b",
|
|
3051
|
-
"config": {
|
|
3052
|
-
"owners": [
|
|
3053
|
-
{
|
|
3054
|
-
"owner": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf",
|
|
3055
|
-
"weight": 1,
|
|
3056
|
-
},
|
|
3057
|
-
],
|
|
3058
|
-
"salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
3059
|
-
"threshold": 1,
|
|
3060
|
-
"version": 0,
|
|
3061
|
-
},
|
|
3062
|
-
"signatures": [
|
|
3063
|
-
{
|
|
3064
|
-
"r": "0x869437e01f64bebeb78a8a6b30bfd3a993819c8cad82c807515d9b9e9b36f985",
|
|
3065
|
-
"s": "0x35dfaa5eebc597715d05f6ce4927747f14fa4cd2acc717fdcd3877146437f8f4",
|
|
3066
|
-
"type": "secp256k1",
|
|
3067
|
-
"yParity": "0x0",
|
|
3068
|
-
},
|
|
3069
|
-
],
|
|
3070
|
-
},
|
|
3110
|
+
"current": "0xf89794c4a590afa7337e5cd5eb3aa60cacf91c5400044bf83ba000000000000000000000000000000000000000000000000000000000000000000101d7d6942b5ad5c4795c026514f8317c7a215e218dccd6cf01f843b8414a0e5b5b4a90f08e6e8d676a73a22dc2cf022ffdcc9299512b5d9a6daf66e0504a395a2ef6f6c0f173910b875c45d01aa66d928e56ba6f49bbc8186f80268bf51b",
|
|
3111
|
+
"initial": "0xf89794c4a590afa7337e5cd5eb3aa60cacf91c5400044bf83ba000000000000000000000000000000000000000000000000000000000000000008001d7d6947e5f4552091a69125d5dfcb7b8c2659029395bdf01f843b841869437e01f64bebeb78a8a6b30bfd3a993819c8cad82c807515d9b9e9b36f98535dfaa5eebc597715d05f6ce4927747f14fa4cd2acc717fdcd3877146437f8f41b",
|
|
3071
3112
|
}
|
|
3072
3113
|
`)
|
|
3073
3114
|
expect(SignatureEnvelope.fromRpc(rpc.initial)).toStrictEqual(
|
|
@@ -3078,7 +3119,7 @@ describe('multisig', () => {
|
|
|
3078
3119
|
)
|
|
3079
3120
|
})
|
|
3080
3121
|
|
|
3081
|
-
test('behavior: derives the account only for an initial
|
|
3122
|
+
test('behavior: derives the account only for an initial config', () => {
|
|
3082
3123
|
const initialEnvelope = SignatureEnvelope.deserialize(initial)
|
|
3083
3124
|
if (initialEnvelope.type !== 'multisig') throw new Error('unreachable')
|
|
3084
3125
|
if (initialEnvelope.config.version !== 0n) throw new Error('unreachable')
|
|
@@ -3142,14 +3183,14 @@ describe('multisig', () => {
|
|
|
3142
3183
|
signatureCount: envelope.signatures.length,
|
|
3143
3184
|
}).toMatchInlineSnapshot(`
|
|
3144
3185
|
{
|
|
3145
|
-
"hash": "
|
|
3186
|
+
"hash": "0x507fa2d2bc6cf5e7753d4d7cb92fe3d199f64c6eaa9a0bd1d14bfb366028a379",
|
|
3146
3187
|
"length": 787,
|
|
3147
3188
|
"signatureCount": 8,
|
|
3148
3189
|
}
|
|
3149
3190
|
`)
|
|
3150
3191
|
})
|
|
3151
3192
|
|
|
3152
|
-
test('behavior: accepts initial and current nested
|
|
3193
|
+
test('behavior: accepts initial and current nested signatures', () => {
|
|
3153
3194
|
const initialEnvelope = SignatureEnvelope.deserialize(initial)
|
|
3154
3195
|
const currentEnvelope = SignatureEnvelope.deserialize(current)
|
|
3155
3196
|
if (
|
|
@@ -3191,7 +3232,7 @@ describe('multisig', () => {
|
|
|
3191
3232
|
)
|
|
3192
3233
|
})
|
|
3193
3234
|
|
|
3194
|
-
test('error: rejects a self-owned current
|
|
3235
|
+
test('error: rejects a self-owned current signature', () => {
|
|
3195
3236
|
const envelope = SignatureEnvelope.deserialize(current)
|
|
3196
3237
|
if (envelope.type !== 'multisig') throw new Error('unreachable')
|
|
3197
3238
|
const account = envelope.config.owners[0]!.owner
|
|
@@ -3282,14 +3323,14 @@ describe('multisig', () => {
|
|
|
3282
3323
|
{
|
|
3283
3324
|
name: 'two fields',
|
|
3284
3325
|
value: Rlp.fromHex([
|
|
3285
|
-
'
|
|
3326
|
+
'0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b',
|
|
3286
3327
|
[Hex.slice(initial, -65)],
|
|
3287
3328
|
]),
|
|
3288
3329
|
},
|
|
3289
3330
|
{
|
|
3290
3331
|
name: 'trailing field',
|
|
3291
3332
|
value: Rlp.fromHex([
|
|
3292
|
-
'
|
|
3333
|
+
'0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b',
|
|
3293
3334
|
MultisigConfig.toTuple(
|
|
3294
3335
|
MultisigConfig.from({
|
|
3295
3336
|
owners: [
|
|
@@ -3370,7 +3411,7 @@ describe('multisig', () => {
|
|
|
3370
3411
|
const malformed = Hex.concat(
|
|
3371
3412
|
'0x05',
|
|
3372
3413
|
Rlp.fromHex([
|
|
3373
|
-
'
|
|
3414
|
+
'0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b',
|
|
3374
3415
|
value as never,
|
|
3375
3416
|
[Hex.slice(initial, -65)],
|
|
3376
3417
|
]),
|
|
@@ -53,8 +53,6 @@ type SignatureEnvelopeKey =
|
|
|
53
53
|
| 'version'
|
|
54
54
|
|
|
55
55
|
type SignatureEnvelopeRpcKey =
|
|
56
|
-
| 'account'
|
|
57
|
-
| 'config'
|
|
58
56
|
| 'keyId'
|
|
59
57
|
| 'metadata'
|
|
60
58
|
| 'preHash'
|
|
@@ -63,7 +61,6 @@ type SignatureEnvelopeRpcKey =
|
|
|
63
61
|
| 'r'
|
|
64
62
|
| 's'
|
|
65
63
|
| 'signature'
|
|
66
|
-
| 'signatures'
|
|
67
64
|
| 'type'
|
|
68
65
|
| 'userAddress'
|
|
69
66
|
| 'v'
|
|
@@ -161,7 +158,7 @@ export type SignatureEnvelopeRpc =
|
|
|
161
158
|
Secp256k1Rpc | P256Rpc | WebAuthnRpc | KeychainRpc,
|
|
162
159
|
SignatureEnvelopeRpcKey
|
|
163
160
|
>
|
|
164
|
-
|
|
|
161
|
+
| MultisigRpc
|
|
165
162
|
|
|
166
163
|
/** Primitive signature envelope accepted by protocol sidecars. */
|
|
167
164
|
export type Primitive<bigintType = bigint, numberType = number> = OneOf<
|
|
@@ -215,7 +212,7 @@ export type KeychainRpc = {
|
|
|
215
212
|
export interface Multisig<bigintType = bigint, numberType = number> {
|
|
216
213
|
/** Native multisig account address. */
|
|
217
214
|
account: Address.Address
|
|
218
|
-
/** Complete applicable multisig configuration
|
|
215
|
+
/** Complete applicable multisig configuration. */
|
|
219
216
|
config: MultisigConfig.Config<bigintType, numberType>
|
|
220
217
|
/**
|
|
221
218
|
* Owner approvals over the multisig owner approval digest. Each approval is
|
|
@@ -240,33 +237,8 @@ type MultisigOneOf<bigintType = bigint, numberType = number> = Multisig<
|
|
|
240
237
|
version?: undefined
|
|
241
238
|
}
|
|
242
239
|
|
|
243
|
-
/**
|
|
244
|
-
export type MultisigRpc =
|
|
245
|
-
/** Native multisig account address. */
|
|
246
|
-
account: Address.Address
|
|
247
|
-
/** Complete applicable multisig configuration witness. */
|
|
248
|
-
config: MultisigConfig.Config<number>
|
|
249
|
-
/** Structured owner approvals. */
|
|
250
|
-
signatures: readonly SignatureEnvelopeRpc[]
|
|
251
|
-
/** Multisig RPC signatures are untagged. */
|
|
252
|
-
type?: undefined
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
type MultisigRpcOneOf = MultisigRpc & {
|
|
256
|
-
keyId?: undefined
|
|
257
|
-
metadata?: undefined
|
|
258
|
-
preHash?: undefined
|
|
259
|
-
pubKeyX?: undefined
|
|
260
|
-
pubKeyY?: undefined
|
|
261
|
-
r?: undefined
|
|
262
|
-
s?: undefined
|
|
263
|
-
signature?: undefined
|
|
264
|
-
userAddress?: undefined
|
|
265
|
-
v?: undefined
|
|
266
|
-
version?: undefined
|
|
267
|
-
webauthnData?: undefined
|
|
268
|
-
yParity?: undefined
|
|
269
|
-
}
|
|
240
|
+
/** Canonical RLP-encoded native multisig signature without the `0x05` type byte. */
|
|
241
|
+
export type MultisigRpc = Hex.Hex
|
|
270
242
|
|
|
271
243
|
export type P256<bigintType = bigint, numberType = number> = {
|
|
272
244
|
prehash: boolean
|
|
@@ -1081,7 +1053,7 @@ export declare namespace from {
|
|
|
1081
1053
|
| {
|
|
1082
1054
|
/** Initial native multisig account, derived from config when omitted. */
|
|
1083
1055
|
account?: Address.Address | undefined
|
|
1084
|
-
/** Initial version-0 multisig configuration
|
|
1056
|
+
/** Initial version-0 multisig configuration. */
|
|
1085
1057
|
config: MultisigConfig.Input<0 | 0n>
|
|
1086
1058
|
/** Primitive or nested owner approvals. */
|
|
1087
1059
|
signatures: readonly SignatureEnvelope[]
|
|
@@ -1090,7 +1062,7 @@ export declare namespace from {
|
|
|
1090
1062
|
| {
|
|
1091
1063
|
/** Native multisig account. */
|
|
1092
1064
|
account: Address.Address
|
|
1093
|
-
/** Complete applicable multisig configuration
|
|
1065
|
+
/** Complete applicable multisig configuration. */
|
|
1094
1066
|
config: MultisigConfig.Input
|
|
1095
1067
|
/** Primitive or nested owner approvals. */
|
|
1096
1068
|
signatures: readonly SignatureEnvelope[]
|
|
@@ -1140,6 +1112,20 @@ export declare namespace from {
|
|
|
1140
1112
|
* @returns The signature envelope with bigint values.
|
|
1141
1113
|
*/
|
|
1142
1114
|
export function fromRpc(envelope: SignatureEnvelopeRpc): SignatureEnvelope {
|
|
1115
|
+
if (typeof envelope === 'string') {
|
|
1116
|
+
const serialized = Hex.concat(serializedMultisigType, envelope)
|
|
1117
|
+
const result = deserialize(serialized)
|
|
1118
|
+
if (
|
|
1119
|
+
result.type !== 'multisig' ||
|
|
1120
|
+
!Hex.isEqual(serialize(result), serialized)
|
|
1121
|
+
)
|
|
1122
|
+
throw new InvalidSerializedError({
|
|
1123
|
+
reason: 'invalid multisig RPC signature',
|
|
1124
|
+
serialized: envelope,
|
|
1125
|
+
})
|
|
1126
|
+
return result
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1143
1129
|
if (envelope.type === 'secp256k1')
|
|
1144
1130
|
return {
|
|
1145
1131
|
signature: Signature.fromRpc(envelope),
|
|
@@ -1222,21 +1208,6 @@ export function fromRpc(envelope: SignatureEnvelopeRpc): SignatureEnvelope {
|
|
|
1222
1208
|
}
|
|
1223
1209
|
}
|
|
1224
1210
|
|
|
1225
|
-
if (
|
|
1226
|
-
(envelope as { type?: string | undefined }).type === 'multisig' ||
|
|
1227
|
-
('config' in envelope && 'signatures' in envelope)
|
|
1228
|
-
) {
|
|
1229
|
-
const multisig = envelope as MultisigRpc
|
|
1230
|
-
const result = {
|
|
1231
|
-
account: multisig.account,
|
|
1232
|
-
config: MultisigConfig.from(multisig.config),
|
|
1233
|
-
signatures: multisig.signatures.map((signature) => fromRpc(signature)),
|
|
1234
|
-
type: 'multisig',
|
|
1235
|
-
} satisfies Multisig
|
|
1236
|
-
assert(result)
|
|
1237
|
-
return result
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
1211
|
throw new CoercionError({ envelope })
|
|
1241
1212
|
}
|
|
1242
1213
|
|
|
@@ -1244,8 +1215,10 @@ export declare namespace fromRpc {
|
|
|
1244
1215
|
type ErrorType =
|
|
1245
1216
|
| assert.ErrorType
|
|
1246
1217
|
| CoercionError
|
|
1218
|
+
| Hex.concat.ErrorType
|
|
1219
|
+
| Hex.isEqual.ErrorType
|
|
1247
1220
|
| InvalidSerializedError
|
|
1248
|
-
|
|
|
1221
|
+
| serialize.ErrorType
|
|
1249
1222
|
| Signature.fromRpc.ErrorType
|
|
1250
1223
|
| Errors.GlobalErrorType
|
|
1251
1224
|
}
|
|
@@ -1526,7 +1499,7 @@ export declare namespace sortMultisigApprovals {
|
|
|
1526
1499
|
type Value = {
|
|
1527
1500
|
/** The native multisig account address. */
|
|
1528
1501
|
account: Address.Address
|
|
1529
|
-
/** Complete applicable multisig configuration
|
|
1502
|
+
/** Complete applicable multisig configuration. */
|
|
1530
1503
|
config: MultisigConfig.Input
|
|
1531
1504
|
/** The inner transaction sign payload (`tx.signature_hash()`). */
|
|
1532
1505
|
payload: Hex.Hex | Bytes.Bytes
|
|
@@ -1611,15 +1584,7 @@ export function toRpc<const envelope extends toRpc.Input>(
|
|
|
1611
1584
|
|
|
1612
1585
|
if (type === 'multisig') {
|
|
1613
1586
|
const multisig = envelope as Multisig
|
|
1614
|
-
|
|
1615
|
-
return {
|
|
1616
|
-
account: multisig.account,
|
|
1617
|
-
config: {
|
|
1618
|
-
...multisig.config,
|
|
1619
|
-
version: Hex.toNumber(Hex.fromNumber(multisig.config.version)),
|
|
1620
|
-
},
|
|
1621
|
-
signatures: multisig.signatures.map((signature) => toRpc(signature)),
|
|
1622
|
-
} as never
|
|
1587
|
+
return Hex.slice(serialize(multisig), 1) as never
|
|
1623
1588
|
}
|
|
1624
1589
|
|
|
1625
1590
|
throw new CoercionError({ envelope })
|
|
@@ -1647,7 +1612,8 @@ export declare namespace toRpc {
|
|
|
1647
1612
|
| assert.ErrorType
|
|
1648
1613
|
| CoercionError
|
|
1649
1614
|
| Hex.fromNumber.ErrorType
|
|
1650
|
-
| Hex.
|
|
1615
|
+
| Hex.slice.ErrorType
|
|
1616
|
+
| serialize.ErrorType
|
|
1651
1617
|
| Signature.toRpc.ErrorType
|
|
1652
1618
|
| Errors.GlobalErrorType
|
|
1653
1619
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Transaction } from 'ox/tempo'
|
|
2
2
|
import { describe, expect, test } from 'vitest'
|
|
3
3
|
|
|
4
|
+
const multisigRpcSignature =
|
|
5
|
+
'0xf89794c4a590afa7337e5cd5eb3aa60cacf91c5400044bf83ba000000000000000000000000000000000000000000000000000000000000000008001d7d6947e5f4552091a69125d5dfcb7b8c2659029395bdf01f843b841869437e01f64bebeb78a8a6b30bfd3a993819c8cad82c807515d9b9e9b36f98535dfaa5eebc597715d05f6ce4927747f14fa4cd2acc717fdcd3877146437f8f41b' as const
|
|
6
|
+
|
|
4
7
|
describe('fromRpc', () => {
|
|
5
8
|
test('default', () => {
|
|
6
9
|
const transaction = Transaction.fromRpc({
|
|
@@ -527,3 +530,61 @@ describe('toRpc', () => {
|
|
|
527
530
|
`)
|
|
528
531
|
})
|
|
529
532
|
})
|
|
533
|
+
|
|
534
|
+
describe('roundtrip', () => {
|
|
535
|
+
test('behavior: multisig RPC signature', () => {
|
|
536
|
+
const rpc = {
|
|
537
|
+
accessList: [],
|
|
538
|
+
blockHash:
|
|
539
|
+
'0xc350d807505fb835650f0013632c5515592987ba169bbc6626d9fc54d91f0f0b',
|
|
540
|
+
blockNumber: '0x12f296f',
|
|
541
|
+
calls: [],
|
|
542
|
+
chainId: '0x1',
|
|
543
|
+
feeToken: '0x20c0000000000000000000000000000000000000',
|
|
544
|
+
from: '0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b',
|
|
545
|
+
gas: '0x43f5d',
|
|
546
|
+
hash: '0x353fdfc38a2f26115daadee9f5b8392ce62b84f410957967e2ed56b35338cdd0',
|
|
547
|
+
maxFeePerGas: '0x2',
|
|
548
|
+
maxPriorityFeePerGas: '0x1',
|
|
549
|
+
nonce: '0x357',
|
|
550
|
+
signature: multisigRpcSignature,
|
|
551
|
+
transactionIndex: '0x2',
|
|
552
|
+
type: '0x76',
|
|
553
|
+
} as const satisfies Transaction.TempoRpc
|
|
554
|
+
const transaction = Transaction.fromRpc(rpc)
|
|
555
|
+
|
|
556
|
+
expect({
|
|
557
|
+
rpc: Transaction.toRpc(transaction).signature,
|
|
558
|
+
signature: transaction.signature,
|
|
559
|
+
}).toMatchInlineSnapshot(`
|
|
560
|
+
{
|
|
561
|
+
"rpc": "0xf89794c4a590afa7337e5cd5eb3aa60cacf91c5400044bf83ba000000000000000000000000000000000000000000000000000000000000000008001d7d6947e5f4552091a69125d5dfcb7b8c2659029395bdf01f843b841869437e01f64bebeb78a8a6b30bfd3a993819c8cad82c807515d9b9e9b36f98535dfaa5eebc597715d05f6ce4927747f14fa4cd2acc717fdcd3877146437f8f41b",
|
|
562
|
+
"signature": {
|
|
563
|
+
"account": "0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b",
|
|
564
|
+
"config": {
|
|
565
|
+
"owners": [
|
|
566
|
+
{
|
|
567
|
+
"owner": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf",
|
|
568
|
+
"weight": 1,
|
|
569
|
+
},
|
|
570
|
+
],
|
|
571
|
+
"salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
572
|
+
"threshold": 1,
|
|
573
|
+
"version": 0n,
|
|
574
|
+
},
|
|
575
|
+
"signatures": [
|
|
576
|
+
{
|
|
577
|
+
"signature": {
|
|
578
|
+
"r": 60871800714128149016591846789173983752390955456021923556141688418770269698437n,
|
|
579
|
+
"s": 24367763726302312398084372528434045669788111037623467391175388828437596076276n,
|
|
580
|
+
"yParity": 0,
|
|
581
|
+
},
|
|
582
|
+
"type": "secp256k1",
|
|
583
|
+
},
|
|
584
|
+
],
|
|
585
|
+
"type": "multisig",
|
|
586
|
+
},
|
|
587
|
+
}
|
|
588
|
+
`)
|
|
589
|
+
})
|
|
590
|
+
})
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { expectTypeOf, test } from 'vitest'
|
|
2
|
-
import type * as
|
|
2
|
+
import type * as MultisigSimulation from './MultisigSimulation.js'
|
|
3
3
|
import type * as TransactionRequest from './TransactionRequest.js'
|
|
4
4
|
|
|
5
5
|
declare const request: TransactionRequest.TransactionRequest
|
|
6
6
|
declare const rpc: TransactionRequest.Rpc
|
|
7
7
|
|
|
8
|
-
test('transaction requests use domain multisig
|
|
9
|
-
expectTypeOf(request.
|
|
8
|
+
test('transaction requests use domain multisig simulation specs', () => {
|
|
9
|
+
expectTypeOf(request.multisigSimulation?.config.version).toEqualTypeOf<
|
|
10
10
|
bigint | undefined
|
|
11
11
|
>()
|
|
12
12
|
|
|
13
|
-
const approval = request.
|
|
13
|
+
const approval = request.multisigSimulation?.approvals[0]
|
|
14
14
|
if (approval?.type === 'multisig')
|
|
15
|
-
expectTypeOf(approval.
|
|
16
|
-
|
|
15
|
+
expectTypeOf(approval.spec.approvals[0]?.keyType).toEqualTypeOf<
|
|
16
|
+
MultisigSimulation.NestedPrimitiveApproval['keyType']
|
|
17
17
|
>()
|
|
18
18
|
})
|
|
19
19
|
|
|
20
|
-
test('RPC requests use
|
|
21
|
-
expectTypeOf(rpc.
|
|
22
|
-
|
|
20
|
+
test('RPC requests use encoded multisig configurations', () => {
|
|
21
|
+
expectTypeOf(rpc.multisigSimulation?.config).toEqualTypeOf<
|
|
22
|
+
`0x${string}` | undefined
|
|
23
23
|
>()
|
|
24
24
|
})
|