ox 1.7.1 → 1.7.2

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 (121) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/core/Hash.js +1 -1
  3. package/dist/core/Hash.js.map +1 -1
  4. package/dist/tempo/KeyAuthorization.d.ts +1 -1
  5. package/dist/tempo/KeyAuthorization.d.ts.map +1 -1
  6. package/dist/tempo/MultisigConfig.d.ts +151 -83
  7. package/dist/tempo/MultisigConfig.d.ts.map +1 -1
  8. package/dist/tempo/MultisigConfig.js +164 -86
  9. package/dist/tempo/MultisigConfig.js.map +1 -1
  10. package/dist/tempo/MultisigOperation.d.ts +324 -0
  11. package/dist/tempo/MultisigOperation.d.ts.map +1 -0
  12. package/dist/tempo/MultisigOperation.js +809 -0
  13. package/dist/tempo/MultisigOperation.js.map +1 -0
  14. package/dist/tempo/MultisigWitness.d.ts +106 -0
  15. package/dist/tempo/MultisigWitness.d.ts.map +1 -0
  16. package/dist/tempo/MultisigWitness.js +118 -0
  17. package/dist/tempo/MultisigWitness.js.map +1 -0
  18. package/dist/tempo/RpcSchemaTempo.d.ts +35 -0
  19. package/dist/tempo/RpcSchemaTempo.d.ts.map +1 -1
  20. package/dist/tempo/SignatureEnvelope.d.ts +60 -80
  21. package/dist/tempo/SignatureEnvelope.d.ts.map +1 -1
  22. package/dist/tempo/SignatureEnvelope.js +87 -146
  23. package/dist/tempo/SignatureEnvelope.js.map +1 -1
  24. package/dist/tempo/TransactionRequest.d.ts +9 -17
  25. package/dist/tempo/TransactionRequest.d.ts.map +1 -1
  26. package/dist/tempo/TransactionRequest.js +7 -7
  27. package/dist/tempo/TransactionRequest.js.map +1 -1
  28. package/dist/tempo/TxEnvelopeTempo.d.ts +3 -2
  29. package/dist/tempo/TxEnvelopeTempo.d.ts.map +1 -1
  30. package/dist/tempo/TxEnvelopeTempo.js +3 -2
  31. package/dist/tempo/TxEnvelopeTempo.js.map +1 -1
  32. package/dist/tempo/index.d.ts +22 -2
  33. package/dist/tempo/index.d.ts.map +1 -1
  34. package/dist/tempo/index.js +22 -2
  35. package/dist/tempo/index.js.map +1 -1
  36. package/dist/zod/tempo/AuthorizationTempo.d.ts +110 -110
  37. package/dist/zod/tempo/AuthorizationTempo.d.ts.map +1 -1
  38. package/dist/zod/tempo/KeyAuthorization.d.ts +90 -83
  39. package/dist/zod/tempo/KeyAuthorization.d.ts.map +1 -1
  40. package/dist/zod/tempo/MultisigConfig.d.ts +31 -2
  41. package/dist/zod/tempo/MultisigConfig.d.ts.map +1 -1
  42. package/dist/zod/tempo/MultisigConfig.js +26 -3
  43. package/dist/zod/tempo/MultisigConfig.js.map +1 -1
  44. package/dist/zod/tempo/MultisigOperation.d.ts +168 -0
  45. package/dist/zod/tempo/MultisigOperation.d.ts.map +1 -0
  46. package/dist/zod/tempo/MultisigOperation.js +65 -0
  47. package/dist/zod/tempo/MultisigOperation.js.map +1 -0
  48. package/dist/zod/tempo/MultisigWitness.d.ts +152 -0
  49. package/dist/zod/tempo/MultisigWitness.d.ts.map +1 -0
  50. package/dist/zod/tempo/MultisigWitness.js +76 -0
  51. package/dist/zod/tempo/MultisigWitness.js.map +1 -0
  52. package/dist/zod/tempo/RpcSchemaTempo.d.ts +607 -102
  53. package/dist/zod/tempo/RpcSchemaTempo.d.ts.map +1 -1
  54. package/dist/zod/tempo/RpcSchemaTempo.js +38 -0
  55. package/dist/zod/tempo/RpcSchemaTempo.js.map +1 -1
  56. package/dist/zod/tempo/SignatureEnvelope.d.ts +33 -33
  57. package/dist/zod/tempo/SignatureEnvelope.d.ts.map +1 -1
  58. package/dist/zod/tempo/SignatureEnvelope.js +9 -16
  59. package/dist/zod/tempo/SignatureEnvelope.js.map +1 -1
  60. package/dist/zod/tempo/Transaction.d.ts +228 -222
  61. package/dist/zod/tempo/Transaction.d.ts.map +1 -1
  62. package/dist/zod/tempo/TransactionRequest.d.ts +379 -176
  63. package/dist/zod/tempo/TransactionRequest.d.ts.map +1 -1
  64. package/dist/zod/tempo/TransactionRequest.js +11 -22
  65. package/dist/zod/tempo/TransactionRequest.js.map +1 -1
  66. package/dist/zod/tempo/TxEnvelopeTempo.d.ts +60 -48
  67. package/dist/zod/tempo/TxEnvelopeTempo.d.ts.map +1 -1
  68. package/dist/zod/tempo/ZoneRpcAuthentication.d.ts +15 -12
  69. package/dist/zod/tempo/ZoneRpcAuthentication.d.ts.map +1 -1
  70. package/dist/zod/tempo/z.d.ts +2 -0
  71. package/dist/zod/tempo/z.d.ts.map +1 -1
  72. package/dist/zod/tempo/z.js +2 -0
  73. package/dist/zod/tempo/z.js.map +1 -1
  74. package/package.json +21 -1
  75. package/src/core/Hash.ts +1 -1
  76. package/src/core/_test/Hash.test.ts +15 -0
  77. package/src/tempo/KeyAuthorization.test-d.ts +13 -1
  78. package/src/tempo/KeyAuthorization.test.ts +65 -0
  79. package/src/tempo/KeyAuthorization.ts +1 -1
  80. package/src/tempo/MultisigConfig.test-d.ts +52 -0
  81. package/src/tempo/MultisigConfig.test.ts +288 -227
  82. package/src/tempo/MultisigConfig.ts +275 -104
  83. package/src/tempo/MultisigOperation.test-d.ts +77 -0
  84. package/src/tempo/MultisigOperation.test.ts +1883 -0
  85. package/src/tempo/MultisigOperation.ts +1254 -0
  86. package/src/tempo/MultisigWitness.test-d.ts +42 -0
  87. package/src/tempo/MultisigWitness.test.ts +288 -0
  88. package/src/tempo/MultisigWitness.ts +210 -0
  89. package/src/tempo/RpcSchemaTempo.test-d.ts +56 -0
  90. package/src/tempo/RpcSchemaTempo.ts +37 -0
  91. package/src/tempo/SignatureEnvelope.test-d.ts +63 -46
  92. package/src/tempo/SignatureEnvelope.test.ts +523 -500
  93. package/src/tempo/SignatureEnvelope.ts +172 -242
  94. package/src/tempo/TransactionRequest.test-d.ts +11 -0
  95. package/src/tempo/TransactionRequest.test.ts +285 -33
  96. package/src/tempo/TransactionRequest.ts +15 -20
  97. package/src/tempo/TxEnvelopeTempo.test-d.ts +7 -0
  98. package/src/tempo/TxEnvelopeTempo.test.ts +25 -0
  99. package/src/tempo/TxEnvelopeTempo.ts +5 -3
  100. package/src/tempo/index.ts +22 -2
  101. package/src/tempo/multisig.e2e.test.ts +113 -86
  102. package/src/version.ts +1 -1
  103. package/src/zod/tempo/MultisigConfig.ts +29 -3
  104. package/src/zod/tempo/MultisigOperation.ts +69 -0
  105. package/src/zod/tempo/MultisigWitness.ts +101 -0
  106. package/src/zod/tempo/RpcSchemaTempo.ts +43 -0
  107. package/src/zod/tempo/SignatureEnvelope.ts +20 -38
  108. package/src/zod/tempo/TransactionRequest.ts +17 -26
  109. package/src/zod/tempo/_test/KeyAuthorization.test.ts +11 -0
  110. package/src/zod/tempo/_test/MultisigConfig.test-d.ts +13 -0
  111. package/src/zod/tempo/_test/MultisigConfig.test.ts +13 -2
  112. package/src/zod/tempo/_test/MultisigOperation.test-d.ts +27 -0
  113. package/src/zod/tempo/_test/MultisigOperation.test.ts +68 -0
  114. package/src/zod/tempo/_test/MultisigWitness.test-d.ts +13 -0
  115. package/src/zod/tempo/_test/MultisigWitness.test.ts +149 -0
  116. package/src/zod/tempo/_test/RpcSchemaTempo.test-d.ts +31 -0
  117. package/src/zod/tempo/_test/RpcSchemaTempo.test.ts +41 -0
  118. package/src/zod/tempo/_test/SignatureEnvelope.test-d.ts +1 -1
  119. package/src/zod/tempo/_test/SignatureEnvelope.test.ts +25 -34
  120. package/src/zod/tempo/_test/TransactionRequest.test.ts +176 -8
  121. package/src/zod/tempo/z.ts +2 -0
@@ -0,0 +1,42 @@
1
+ import { expectTypeOf, test } from 'vp/test'
2
+ import * as MultisigWitness from './MultisigWitness.js'
3
+
4
+ const rpc = {
5
+ account: '0x2222222222222222222222222222222222222222',
6
+ approvals: [
7
+ {
8
+ owner: '0x1111111111111111111111111111111111111111',
9
+ type: 'primitive',
10
+ },
11
+ ],
12
+ config: {
13
+ owners: [
14
+ {
15
+ owner: '0x1111111111111111111111111111111111111111',
16
+ weight: 1,
17
+ },
18
+ ],
19
+ salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
20
+ threshold: 1,
21
+ version: 0,
22
+ },
23
+ } as const satisfies MultisigWitness.Rpc
24
+
25
+ test('fromRpc returns a domain witness', () => {
26
+ const witness = MultisigWitness.fromRpc(rpc)
27
+
28
+ expectTypeOf(witness).toEqualTypeOf<MultisigWitness.MultisigWitness>()
29
+ expectTypeOf(witness.config.version).toEqualTypeOf<bigint>()
30
+ })
31
+
32
+ test('RPC witnesses use numeric configuration versions', () => {
33
+ expectTypeOf<
34
+ MultisigWitness.Rpc['config']['version']
35
+ >().toEqualTypeOf<number>()
36
+ })
37
+
38
+ test('toRpc returns an RPC witness', () => {
39
+ expectTypeOf(
40
+ MultisigWitness.toRpc(MultisigWitness.fromRpc(rpc)),
41
+ ).toEqualTypeOf<MultisigWitness.Rpc>()
42
+ })
@@ -0,0 +1,288 @@
1
+ import { MultisigWitness } from 'ox/tempo'
2
+ import { describe, expect, test } from 'vp/test'
3
+
4
+ const rpc = {
5
+ account: '0xcccccccccccccccccccccccccccccccccccccccc',
6
+ approvals: [
7
+ {
8
+ keyData: '0x0102030405',
9
+ keyType: 'webAuthn',
10
+ owner: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
11
+ type: 'primitive',
12
+ },
13
+ {
14
+ type: 'multisig',
15
+ witness: {
16
+ account: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
17
+ approvals: [
18
+ {
19
+ keyData: '0x010203040506',
20
+ keyType: 'secp256k1',
21
+ owner: '0xdddddddddddddddddddddddddddddddddddddddd',
22
+ },
23
+ {
24
+ owner: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
25
+ },
26
+ ],
27
+ config: {
28
+ owners: [
29
+ {
30
+ owner: '0xdddddddddddddddddddddddddddddddddddddddd',
31
+ weight: 1,
32
+ },
33
+ {
34
+ owner: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
35
+ weight: 1,
36
+ },
37
+ ],
38
+ salt: '0x2222222222222222222222222222222222222222222222222222222222222222',
39
+ threshold: 2,
40
+ version: 2,
41
+ },
42
+ },
43
+ },
44
+ ],
45
+ config: {
46
+ owners: [
47
+ {
48
+ owner: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
49
+ weight: 1,
50
+ },
51
+ {
52
+ owner: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
53
+ weight: 1,
54
+ },
55
+ ],
56
+ salt: '0x1111111111111111111111111111111111111111111111111111111111111111',
57
+ threshold: 2,
58
+ version: 1,
59
+ },
60
+ } as const satisfies MultisigWitness.Rpc
61
+
62
+ describe('fromRpc', () => {
63
+ test('behavior: converts numeric configuration versions to bigint', () => {
64
+ expect(MultisigWitness.fromRpc(rpc)).toMatchInlineSnapshot(`
65
+ {
66
+ "account": "0xcccccccccccccccccccccccccccccccccccccccc",
67
+ "approvals": [
68
+ {
69
+ "keyData": "0x0102030405",
70
+ "keyType": "webAuthn",
71
+ "owner": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
72
+ "type": "primitive",
73
+ },
74
+ {
75
+ "type": "multisig",
76
+ "witness": {
77
+ "account": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
78
+ "approvals": [
79
+ {
80
+ "keyData": "0x010203040506",
81
+ "keyType": "secp256k1",
82
+ "owner": "0xdddddddddddddddddddddddddddddddddddddddd",
83
+ },
84
+ {
85
+ "owner": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
86
+ },
87
+ ],
88
+ "config": {
89
+ "owners": [
90
+ {
91
+ "owner": "0xdddddddddddddddddddddddddddddddddddddddd",
92
+ "weight": 1,
93
+ },
94
+ {
95
+ "owner": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
96
+ "weight": 1,
97
+ },
98
+ ],
99
+ "salt": "0x2222222222222222222222222222222222222222222222222222222222222222",
100
+ "threshold": 2,
101
+ "version": 2n,
102
+ },
103
+ },
104
+ },
105
+ ],
106
+ "config": {
107
+ "owners": [
108
+ {
109
+ "owner": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
110
+ "weight": 1,
111
+ },
112
+ {
113
+ "owner": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
114
+ "weight": 1,
115
+ },
116
+ ],
117
+ "salt": "0x1111111111111111111111111111111111111111111111111111111111111111",
118
+ "threshold": 2,
119
+ "version": 1n,
120
+ },
121
+ }
122
+ `)
123
+ })
124
+
125
+ test('error: rejects unsafe numeric configuration versions', () => {
126
+ expect(() =>
127
+ MultisigWitness.fromRpc({
128
+ ...rpc,
129
+ config: {
130
+ ...rpc.config,
131
+ version: Number.MAX_SAFE_INTEGER + 1,
132
+ },
133
+ }),
134
+ ).toThrowErrorMatchingInlineSnapshot(
135
+ `[MultisigConfig.InvalidConfigError: Invalid native multisig config: version must be an unsigned 64-bit integer.]`,
136
+ )
137
+ })
138
+
139
+ test('error: rejects excess root approvals', () => {
140
+ expect(() =>
141
+ MultisigWitness.fromRpc({
142
+ ...rpc,
143
+ approvals: Array.from({ length: 9 }, () => rpc.approvals[0]),
144
+ }),
145
+ ).toThrowErrorMatchingInlineSnapshot(
146
+ `[MultisigWitness.InvalidWitnessError: Invalid multisig witness: approval count exceeds 8.]`,
147
+ )
148
+ })
149
+
150
+ test('error: rejects excess nested approvals', () => {
151
+ expect(() =>
152
+ MultisigWitness.fromRpc({
153
+ ...rpc,
154
+ approvals: [
155
+ {
156
+ ...rpc.approvals[1],
157
+ witness: {
158
+ ...rpc.approvals[1].witness,
159
+ approvals: Array.from(
160
+ { length: 9 },
161
+ () => rpc.approvals[1].witness.approvals[0],
162
+ ),
163
+ },
164
+ },
165
+ ],
166
+ }),
167
+ ).toThrowErrorMatchingInlineSnapshot(
168
+ `[MultisigWitness.InvalidWitnessError: Invalid multisig witness: approval count exceeds 8.]`,
169
+ )
170
+ })
171
+ })
172
+
173
+ describe('toRpc', () => {
174
+ test('behavior: converts bigint configuration versions to numbers', () => {
175
+ expect(MultisigWitness.toRpc(MultisigWitness.fromRpc(rpc)))
176
+ .toMatchInlineSnapshot(`
177
+ {
178
+ "account": "0xcccccccccccccccccccccccccccccccccccccccc",
179
+ "approvals": [
180
+ {
181
+ "keyData": "0x0005",
182
+ "keyType": "webAuthn",
183
+ "owner": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
184
+ "type": "primitive",
185
+ },
186
+ {
187
+ "type": "multisig",
188
+ "witness": {
189
+ "account": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
190
+ "approvals": [
191
+ {
192
+ "keyData": "0x0006",
193
+ "keyType": "secp256k1",
194
+ "owner": "0xdddddddddddddddddddddddddddddddddddddddd",
195
+ },
196
+ {
197
+ "owner": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
198
+ },
199
+ ],
200
+ "config": {
201
+ "owners": [
202
+ {
203
+ "owner": "0xdddddddddddddddddddddddddddddddddddddddd",
204
+ "weight": 1,
205
+ },
206
+ {
207
+ "owner": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
208
+ "weight": 1,
209
+ },
210
+ ],
211
+ "salt": "0x2222222222222222222222222222222222222222222222222222222222222222",
212
+ "threshold": 2,
213
+ "version": 2,
214
+ },
215
+ },
216
+ },
217
+ ],
218
+ "config": {
219
+ "owners": [
220
+ {
221
+ "owner": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
222
+ "weight": 1,
223
+ },
224
+ {
225
+ "owner": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
226
+ "weight": 1,
227
+ },
228
+ ],
229
+ "salt": "0x1111111111111111111111111111111111111111111111111111111111111111",
230
+ "threshold": 2,
231
+ "version": 1,
232
+ },
233
+ }
234
+ `)
235
+ })
236
+
237
+ test('error: rejects versions that JSON cannot represent exactly', () => {
238
+ const witness = MultisigWitness.fromRpc(rpc)
239
+ expect(() =>
240
+ MultisigWitness.toRpc({
241
+ ...witness,
242
+ config: {
243
+ ...witness.config,
244
+ version: BigInt(Number.MAX_SAFE_INTEGER) + 1n,
245
+ },
246
+ }),
247
+ ).toThrowErrorMatchingInlineSnapshot(
248
+ `[Hex.IntegerOutOfRangeError: Number \`9007199254740992\` is not in safe unsigned integer range (\`0\` to \`9007199254740991\`)]`,
249
+ )
250
+ })
251
+
252
+ test('error: rejects excess root approvals', () => {
253
+ const witness = MultisigWitness.fromRpc(rpc)
254
+ expect(() =>
255
+ MultisigWitness.toRpc({
256
+ ...witness,
257
+ approvals: Array.from({ length: 9 }, () => witness.approvals[0]!),
258
+ }),
259
+ ).toThrowErrorMatchingInlineSnapshot(
260
+ `[MultisigWitness.InvalidWitnessError: Invalid multisig witness: approval count exceeds 8.]`,
261
+ )
262
+ })
263
+
264
+ test('error: rejects excess nested approvals', () => {
265
+ const witness = MultisigWitness.fromRpc(rpc)
266
+ const nested = witness.approvals[1]!
267
+ if (nested.type !== 'multisig') throw new Error('unreachable')
268
+ expect(() =>
269
+ MultisigWitness.toRpc({
270
+ ...witness,
271
+ approvals: [
272
+ {
273
+ ...nested,
274
+ witness: {
275
+ ...nested.witness,
276
+ approvals: Array.from(
277
+ { length: 9 },
278
+ () => nested.witness.approvals[0]!,
279
+ ),
280
+ },
281
+ },
282
+ ],
283
+ }),
284
+ ).toThrowErrorMatchingInlineSnapshot(
285
+ `[MultisigWitness.InvalidWitnessError: Invalid multisig witness: approval count exceeds 8.]`,
286
+ )
287
+ })
288
+ })
@@ -0,0 +1,210 @@
1
+ import type * as Address from '../core/Address.js'
2
+ import * as Errors from '../core/Errors.js'
3
+ import * as Hex from '../core/Hex.js'
4
+ import type { Compute } from '../core/internal/types.js'
5
+ import * as MultisigConfig from './MultisigConfig.js'
6
+ import type * as SignatureEnvelope from './SignatureEnvelope.js'
7
+
8
+ /** Native multisig owner approval used for RPC simulation. */
9
+ export type Approval<versionType = bigint> =
10
+ | NestedApproval<versionType>
11
+ | PrimitiveApproval
12
+
13
+ /** Native multisig witness used to construct an RPC simulation signature. */
14
+ export type MultisigWitness<versionType = bigint> = Compute<{
15
+ /** Account authorized by this witness. */
16
+ account: Address.Address
17
+ /** Owner approvals to model. */
18
+ approvals: readonly Approval<versionType>[]
19
+ /** Complete applicable configuration. */
20
+ config: MultisigConfig.Config<versionType>
21
+ }>
22
+
23
+ /** Nested native multisig owner approval used for RPC simulation. */
24
+ export type NestedApproval<versionType = bigint> = {
25
+ /** Approval type. */
26
+ type: 'multisig'
27
+ /** Depth-2 multisig witness. */
28
+ witness: NestedWitness<versionType>
29
+ }
30
+
31
+ /** Primitive approval in a depth-2 multisig simulation witness. */
32
+ export type NestedPrimitiveApproval = {
33
+ /** Optional signature-specific gas-estimation data. */
34
+ keyData?: Hex.Hex | undefined
35
+ /** Signature type to model. Omission uses a maximum-size WebAuthn signature. */
36
+ keyType?: SignatureEnvelope.Type | undefined
37
+ /** Configured owner address. */
38
+ owner: Address.Address
39
+ }
40
+
41
+ /** Depth-2 native multisig witness used for RPC simulation. */
42
+ export type NestedWitness<versionType = bigint> = {
43
+ /** Nested multisig account. */
44
+ account: Address.Address
45
+ /** Primitive owner approvals to model. */
46
+ approvals: readonly NestedPrimitiveApproval[]
47
+ /** Complete applicable configuration. */
48
+ config: MultisigConfig.Config<versionType>
49
+ }
50
+
51
+ /** Primitive owner approval used for RPC simulation. */
52
+ export type PrimitiveApproval = {
53
+ /** Optional signature-specific gas-estimation data. */
54
+ keyData?: Hex.Hex | undefined
55
+ /** Signature type to model. Omission uses a maximum-size WebAuthn signature. */
56
+ keyType?: SignatureEnvelope.Type | undefined
57
+ /** Configured owner address. */
58
+ owner: Address.Address
59
+ /** Approval type. */
60
+ type: 'primitive'
61
+ }
62
+
63
+ /** JSON-RPC representation of a native multisig simulation witness. */
64
+ export type Rpc = MultisigWitness<number>
65
+
66
+ /**
67
+ * Converts a JSON-RPC multisig witness to its domain representation.
68
+ *
69
+ * @example
70
+ * ```ts twoslash
71
+ * // @noErrors
72
+ * import { MultisigWitness } from 'ox/tempo'
73
+ *
74
+ * const witness = MultisigWitness.fromRpc(witnessRpc)
75
+ * ```
76
+ *
77
+ * @param witness - JSON-RPC multisig witness.
78
+ * @returns The multisig witness with bigint configuration versions.
79
+ */
80
+ export function fromRpc(witness: Rpc): MultisigWitness {
81
+ const { account, approvals, config } = witness
82
+ assertApprovalCount(approvals)
83
+ return {
84
+ account,
85
+ approvals: approvals.map((approval) => {
86
+ if (approval.type === 'primitive') return approval
87
+ assertApprovalCount(approval.witness.approvals)
88
+ return {
89
+ type: 'multisig',
90
+ witness: {
91
+ account: approval.witness.account,
92
+ approvals: approval.witness.approvals,
93
+ config: MultisigConfig.from(approval.witness.config),
94
+ },
95
+ }
96
+ }),
97
+ config: MultisigConfig.from(config),
98
+ }
99
+ }
100
+
101
+ export declare namespace fromRpc {
102
+ /** Error type for `fromRpc`. */
103
+ export type ErrorType =
104
+ | InvalidWitnessError
105
+ | MultisigConfig.assert.ErrorType
106
+ | Errors.GlobalErrorType
107
+ }
108
+
109
+ /**
110
+ * Converts a multisig witness to its JSON-RPC representation.
111
+ *
112
+ * @example
113
+ * ```ts twoslash
114
+ * // @noErrors
115
+ * import { MultisigWitness } from 'ox/tempo'
116
+ *
117
+ * const witnessRpc = MultisigWitness.toRpc(witness)
118
+ * ```
119
+ *
120
+ * @param witness - Multisig witness.
121
+ * @returns The JSON-RPC multisig witness with numeric configuration versions.
122
+ */
123
+ export function toRpc(witness: MultisigWitness): Rpc {
124
+ const { account, approvals, config } = witness
125
+ assertApprovalCount(approvals)
126
+ return {
127
+ account,
128
+ approvals: approvals.map((approval) => {
129
+ if (approval.type === 'primitive')
130
+ return {
131
+ ...approval,
132
+ ...(typeof approval.keyData !== 'undefined'
133
+ ? { keyData: shimKeyData(approval.keyData) }
134
+ : {}),
135
+ }
136
+ assertApprovalCount(approval.witness.approvals)
137
+ return {
138
+ type: 'multisig',
139
+ witness: {
140
+ account: approval.witness.account,
141
+ approvals: approval.witness.approvals.map((approval) => ({
142
+ ...approval,
143
+ ...(typeof approval.keyData !== 'undefined'
144
+ ? { keyData: shimKeyData(approval.keyData) }
145
+ : {}),
146
+ })),
147
+ config: configToRpc(approval.witness.config),
148
+ },
149
+ }
150
+ }),
151
+ config: configToRpc(config),
152
+ }
153
+ }
154
+
155
+ export declare namespace toRpc {
156
+ /** Error type for `toRpc`. */
157
+ export type ErrorType =
158
+ | Hex.fromNumber.ErrorType
159
+ | Hex.toNumber.ErrorType
160
+ | InvalidWitnessError
161
+ | MultisigConfig.assert.ErrorType
162
+ | Errors.GlobalErrorType
163
+ }
164
+
165
+ /** @internal */
166
+ function assertApprovalCount(approvals: readonly unknown[]) {
167
+ if (approvals.length > MultisigConfig.maxSignatures)
168
+ throw new InvalidWitnessError({
169
+ reason: `approval count exceeds ${MultisigConfig.maxSignatures}`,
170
+ })
171
+ }
172
+
173
+ /** @internal */
174
+ function configToRpc(
175
+ config: MultisigConfig.Config,
176
+ ): MultisigConfig.Config<number> {
177
+ const value = MultisigConfig.from(config)
178
+ return {
179
+ ...value,
180
+ version: Hex.toNumber(Hex.fromNumber(value.version)),
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Shims key data longer than 4 bytes into a 2-byte big-endian length hint.
186
+ * The node's gas estimator only accepts 1, 2, or 4-byte key data as a
187
+ * signature-size hint; anything else silently falls back to the default.
188
+ * @internal
189
+ */
190
+ function shimKeyData(data: Hex.Hex): Hex.Hex {
191
+ const size = Hex.size(data)
192
+ if (size <= 4) return data
193
+ return Hex.fromNumber(size, { size: 2 })
194
+ }
195
+
196
+ /** Thrown when a native multisig witness is invalid. */
197
+ export class InvalidWitnessError extends Errors.BaseError {
198
+ override readonly name = 'MultisigWitness.InvalidWitnessError'
199
+ constructor(options: InvalidWitnessError.Options) {
200
+ super(`Invalid multisig witness: ${options.reason}.`)
201
+ }
202
+ }
203
+
204
+ export declare namespace InvalidWitnessError {
205
+ /** Error construction options. */
206
+ export type Options = {
207
+ /** Validation failure. */
208
+ reason: string
209
+ }
210
+ }
@@ -0,0 +1,56 @@
1
+ import type { Provider } from 'ox'
2
+ import type {
3
+ KeyAuthorization,
4
+ MultisigOperation,
5
+ RpcSchemaTempo,
6
+ } from 'ox/tempo'
7
+ import { expectTypeOf, test } from 'vp/test'
8
+ import type * as Hex from '../core/Hex.js'
9
+
10
+ declare const provider: Provider.Provider<{ schema: RpcSchemaTempo.Multisig }>
11
+ declare const hash: Hex.Hex
12
+ declare const keyAuthorization: KeyAuthorization.Rpc
13
+ declare const serializedTransaction: Hex.Hex
14
+ declare const signature: Hex.Hex
15
+
16
+ test('multisig provider methods', () => {
17
+ expectTypeOf(
18
+ provider.request({
19
+ method: 'multisig_approveRawTransaction',
20
+ params: [serializedTransaction],
21
+ }),
22
+ ).resolves.toEqualTypeOf<Hex.Hex>()
23
+
24
+ expectTypeOf(
25
+ provider.request({
26
+ method: 'multisig_approveRawTransactionSync',
27
+ params: [serializedTransaction],
28
+ }),
29
+ ).resolves.toEqualTypeOf<MultisigOperation.TransactionRpc>()
30
+
31
+ void provider.request({
32
+ method: 'multisig_approveRawTransactionSync',
33
+ params: [serializedTransaction, 30_000],
34
+ })
35
+
36
+ expectTypeOf(
37
+ provider.request({
38
+ method: 'multisig_approveKeyAuthorization',
39
+ params: [{ keyAuthorization }],
40
+ }),
41
+ ).resolves.toEqualTypeOf<MultisigOperation.KeyAuthorizationRpc>()
42
+
43
+ expectTypeOf(
44
+ provider.request({
45
+ method: 'multisig_approveKeyAuthorization',
46
+ params: [{ hash, signature }],
47
+ }),
48
+ ).resolves.toEqualTypeOf<MultisigOperation.KeyAuthorizationRpc>()
49
+
50
+ expectTypeOf(
51
+ provider.request({
52
+ method: 'multisig_getOperation',
53
+ params: [hash],
54
+ }),
55
+ ).resolves.toEqualTypeOf<MultisigOperation.Rpc | null>()
56
+ })
@@ -4,6 +4,8 @@ import type * as Hex from '../core/Hex.js'
4
4
  import type * as Log from '../core/Log.js'
5
5
  import type * as RpcSchema from '../core/RpcSchema.js'
6
6
  import type * as StateOverrides from '../core/StateOverrides.js'
7
+ import type * as KeyAuthorization from './KeyAuthorization.js'
8
+ import type * as MultisigOperation from './MultisigOperation.js'
7
9
  import type * as TransactionRequest from './TransactionRequest.js'
8
10
 
9
11
  /**
@@ -53,3 +55,38 @@ export type Tempo = RpcSchema.From<{
53
55
  }
54
56
  }
55
57
  }>
58
+
59
+ /** Union of all JSON-RPC methods for the `multisig_` namespace. */
60
+ export type Multisig = RpcSchema.From<
61
+ | {
62
+ Request: {
63
+ method: 'multisig_approveRawTransaction'
64
+ params: [serializedTransaction: Hex.Hex]
65
+ }
66
+ ReturnType: Hex.Hex
67
+ }
68
+ | {
69
+ Request: {
70
+ method: 'multisig_approveRawTransactionSync'
71
+ params: [serializedTransaction: Hex.Hex, timeout?: number]
72
+ }
73
+ ReturnType: MultisigOperation.TransactionRpc
74
+ }
75
+ | {
76
+ Request: {
77
+ method: 'multisig_approveKeyAuthorization'
78
+ params: [
79
+ | { keyAuthorization: KeyAuthorization.Rpc }
80
+ | { hash: Hex.Hex; signature: Hex.Hex },
81
+ ]
82
+ }
83
+ ReturnType: MultisigOperation.KeyAuthorizationRpc
84
+ }
85
+ | {
86
+ Request: {
87
+ method: 'multisig_getOperation'
88
+ params: [hash: Hex.Hex]
89
+ }
90
+ ReturnType: MultisigOperation.Rpc | null
91
+ }
92
+ >