ox 1.7.2 → 1.7.5
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 +43 -0
- package/dist/core/AbiEvent.d.ts.map +1 -1
- package/dist/core/AbiEvent.js +10 -9
- package/dist/core/AbiEvent.js.map +1 -1
- package/dist/core/Blobs.d.ts.map +1 -1
- package/dist/core/Blobs.js +6 -2
- package/dist/core/Blobs.js.map +1 -1
- package/dist/core/Signature.d.ts +6 -5
- package/dist/core/Signature.d.ts.map +1 -1
- package/dist/core/Signature.js +17 -7
- package/dist/core/Signature.js.map +1 -1
- package/dist/core/Siwe.d.ts.map +1 -1
- package/dist/core/Siwe.js +21 -1
- package/dist/core/Siwe.js.map +1 -1
- package/dist/tempo/KeyAuthorization.d.ts +43 -39
- package/dist/tempo/KeyAuthorization.d.ts.map +1 -1
- package/dist/tempo/KeyAuthorization.js +24 -4
- package/dist/tempo/KeyAuthorization.js.map +1 -1
- package/dist/tempo/MultisigConfig.d.ts +18 -15
- package/dist/tempo/MultisigConfig.d.ts.map +1 -1
- package/dist/tempo/MultisigConfig.js +49 -20
- package/dist/tempo/MultisigConfig.js.map +1 -1
- package/dist/tempo/MultisigOperation.d.ts +45 -28
- package/dist/tempo/MultisigOperation.d.ts.map +1 -1
- package/dist/tempo/MultisigOperation.js +81 -131
- package/dist/tempo/MultisigOperation.js.map +1 -1
- package/dist/tempo/MultisigSimulation.d.ts +85 -0
- package/dist/tempo/MultisigSimulation.d.ts.map +1 -0
- package/dist/tempo/MultisigSimulation.js +112 -0
- package/dist/tempo/MultisigSimulation.js.map +1 -0
- package/dist/tempo/RpcSchemaTempo.d.ts +20 -10
- package/dist/tempo/RpcSchemaTempo.d.ts.map +1 -1
- package/dist/tempo/SignatureEnvelope.d.ts +74 -153
- package/dist/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/dist/tempo/SignatureEnvelope.js +130 -187
- package/dist/tempo/SignatureEnvelope.js.map +1 -1
- package/dist/tempo/TransactionRequest.d.ts +9 -7
- package/dist/tempo/TransactionRequest.d.ts.map +1 -1
- package/dist/tempo/TransactionRequest.js +12 -7
- package/dist/tempo/TransactionRequest.js.map +1 -1
- package/dist/tempo/index.d.ts +7 -5
- package/dist/tempo/index.d.ts.map +1 -1
- package/dist/tempo/index.js +7 -5
- package/dist/tempo/index.js.map +1 -1
- package/dist/zod/tempo/AuthorizationTempo.d.ts +360 -140
- package/dist/zod/tempo/AuthorizationTempo.d.ts.map +1 -1
- package/dist/zod/tempo/KeyAuthorization.d.ts +247 -487
- package/dist/zod/tempo/KeyAuthorization.d.ts.map +1 -1
- package/dist/zod/tempo/KeyAuthorization.js +29 -31
- package/dist/zod/tempo/KeyAuthorization.js.map +1 -1
- package/dist/zod/tempo/MultisigOperation.d.ts +0 -10
- package/dist/zod/tempo/MultisigOperation.d.ts.map +1 -1
- package/dist/zod/tempo/MultisigOperation.js +0 -3
- package/dist/zod/tempo/MultisigOperation.js.map +1 -1
- package/dist/zod/tempo/MultisigSimulation.d.ts +52 -0
- package/dist/zod/tempo/MultisigSimulation.d.ts.map +1 -0
- package/dist/zod/tempo/MultisigSimulation.js +44 -0
- package/dist/zod/tempo/MultisigSimulation.js.map +1 -0
- package/dist/zod/tempo/RpcSchemaTempo.d.ts +357 -422
- package/dist/zod/tempo/RpcSchemaTempo.d.ts.map +1 -1
- package/dist/zod/tempo/RpcSchemaTempo.js +19 -10
- package/dist/zod/tempo/RpcSchemaTempo.js.map +1 -1
- package/dist/zod/tempo/SignatureEnvelope.d.ts +108 -42
- package/dist/zod/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/dist/zod/tempo/SignatureEnvelope.js +21 -19
- package/dist/zod/tempo/SignatureEnvelope.js.map +1 -1
- package/dist/zod/tempo/Transaction.d.ts +678 -666
- package/dist/zod/tempo/Transaction.d.ts.map +1 -1
- package/dist/zod/tempo/TransactionRequest.d.ts +580 -619
- package/dist/zod/tempo/TransactionRequest.d.ts.map +1 -1
- package/dist/zod/tempo/TransactionRequest.js +18 -10
- package/dist/zod/tempo/TransactionRequest.js.map +1 -1
- package/dist/zod/tempo/TxEnvelopeTempo.d.ts +327 -213
- package/dist/zod/tempo/TxEnvelopeTempo.d.ts.map +1 -1
- package/dist/zod/tempo/ZoneRpcAuthentication.d.ts +105 -3
- package/dist/zod/tempo/ZoneRpcAuthentication.d.ts.map +1 -1
- package/dist/zod/tempo/z.d.ts +1 -1
- package/dist/zod/tempo/z.d.ts.map +1 -1
- package/dist/zod/tempo/z.js +1 -1
- package/dist/zod/tempo/z.js.map +1 -1
- package/package.json +9 -9
- package/src/core/AbiEvent.ts +11 -9
- package/src/core/Blobs.ts +6 -2
- package/src/core/Signature.ts +41 -11
- package/src/core/Siwe.ts +20 -1
- package/src/core/_test/AbiEvent.test.ts +45 -0
- package/src/core/_test/Blobs.test.ts +22 -0
- package/src/core/_test/Signature.test.ts +166 -0
- package/src/core/_test/Siwe.test.ts +100 -1
- package/src/tempo/AuthorizationTempo.test.ts +8 -0
- package/src/tempo/KeyAuthorization.test-d.ts +16 -74
- package/src/tempo/KeyAuthorization.test.ts +113 -14
- package/src/tempo/KeyAuthorization.ts +110 -66
- package/src/tempo/MultisigConfig.test.ts +44 -20
- package/src/tempo/MultisigConfig.ts +65 -23
- package/src/tempo/MultisigOperation.test-d.ts +8 -6
- package/src/tempo/MultisigOperation.test.ts +187 -591
- package/src/tempo/MultisigOperation.ts +129 -205
- package/src/tempo/MultisigSimulation.test-d.ts +33 -0
- package/src/tempo/MultisigSimulation.test.ts +194 -0
- package/src/tempo/MultisigSimulation.ts +192 -0
- package/src/tempo/RpcSchemaTempo.test-d.ts +45 -10
- package/src/tempo/RpcSchemaTempo.ts +15 -6
- package/src/tempo/SignatureEnvelope.test-d.ts +27 -101
- package/src/tempo/SignatureEnvelope.test.ts +330 -533
- package/src/tempo/SignatureEnvelope.ts +198 -310
- package/src/tempo/Transaction.test.ts +61 -0
- package/src/tempo/TransactionRequest.test-d.ts +7 -7
- package/src/tempo/TransactionRequest.test.ts +81 -223
- package/src/tempo/TransactionRequest.ts +34 -13
- package/src/tempo/index.ts +7 -5
- package/src/tempo/multisig.e2e.test.ts +329 -818
- package/src/version.ts +1 -1
- package/src/zod/tempo/KeyAuthorization.ts +50 -39
- package/src/zod/tempo/MultisigOperation.ts +0 -3
- package/src/zod/tempo/MultisigSimulation.ts +53 -0
- package/src/zod/tempo/RpcSchemaTempo.ts +20 -10
- package/src/zod/tempo/SignatureEnvelope.ts +46 -59
- package/src/zod/tempo/TransactionRequest.ts +28 -14
- package/src/zod/tempo/_test/KeyAuthorization.test.ts +66 -30
- package/src/zod/tempo/_test/MultisigOperation.test.ts +0 -2
- package/src/zod/tempo/_test/MultisigSimulation.test-d.ts +13 -0
- package/src/zod/tempo/_test/MultisigSimulation.test.ts +53 -0
- package/src/zod/tempo/_test/RpcSchemaTempo.test-d.ts +19 -2
- package/src/zod/tempo/_test/RpcSchemaTempo.test.ts +46 -4
- package/src/zod/tempo/_test/SignatureEnvelope.test.ts +108 -129
- package/src/zod/tempo/_test/TransactionRequest.test.ts +17 -168
- package/src/zod/tempo/z.ts +1 -1
- package/dist/tempo/MultisigWitness.d.ts +0 -106
- package/dist/tempo/MultisigWitness.d.ts.map +0 -1
- package/dist/tempo/MultisigWitness.js +0 -118
- package/dist/tempo/MultisigWitness.js.map +0 -1
- package/dist/zod/tempo/MultisigWitness.d.ts +0 -152
- package/dist/zod/tempo/MultisigWitness.d.ts.map +0 -1
- package/dist/zod/tempo/MultisigWitness.js +0 -76
- package/dist/zod/tempo/MultisigWitness.js.map +0 -1
- package/src/tempo/MultisigWitness.test-d.ts +0 -42
- package/src/tempo/MultisigWitness.test.ts +0 -288
- package/src/tempo/MultisigWitness.ts +0 -210
- package/src/zod/tempo/MultisigWitness.ts +0 -101
- package/src/zod/tempo/_test/MultisigWitness.test-d.ts +0 -13
- package/src/zod/tempo/_test/MultisigWitness.test.ts +0 -149
|
@@ -4,7 +4,11 @@ import type * as Errors from '../core/Errors.js'
|
|
|
4
4
|
import * as Hash from '../core/Hash.js'
|
|
5
5
|
import * as Hex from '../core/Hex.js'
|
|
6
6
|
import * as Quantity from '../core/internal/quantity.js'
|
|
7
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
Compute,
|
|
9
|
+
PartialBy,
|
|
10
|
+
UnionPartialBy,
|
|
11
|
+
} from '../core/internal/types.js'
|
|
8
12
|
import * as Rlp from '../core/Rlp.js'
|
|
9
13
|
import * as SignatureEnvelope from './SignatureEnvelope.js'
|
|
10
14
|
|
|
@@ -25,7 +29,7 @@ import * as SignatureEnvelope from './SignatureEnvelope.js'
|
|
|
25
29
|
* - `chainId`: Chain ID for replay protection (0 = valid on any chain)
|
|
26
30
|
* - `expiry`: Unix timestamp when the key expires (undefined = never expires)
|
|
27
31
|
* - `limits`: Per-TIP-20 token spending limits (only applies to `transfer()` and `approve()` calls)
|
|
28
|
-
* - `type`: Key type (`secp256k1`, `p256`, or `
|
|
32
|
+
* - `type`: Key type (`secp256k1`, `p256`, `webAuthn`, or `multisig`)
|
|
29
33
|
*
|
|
30
34
|
* [Access Keys Specification](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#access-keys)
|
|
31
35
|
*/
|
|
@@ -34,12 +38,16 @@ export type KeyAuthorization<
|
|
|
34
38
|
bigintType = bigint,
|
|
35
39
|
numberType = number,
|
|
36
40
|
> = {
|
|
41
|
+
/** Account address this authorization is bound to. Required for multisig grants. */
|
|
42
|
+
account?: Address.Address | undefined
|
|
37
43
|
/** Address derived from the public key of the key type. */
|
|
38
44
|
address: Address.Address
|
|
39
45
|
/** Chain ID for replay protection. */
|
|
40
46
|
chainId: bigintType
|
|
41
47
|
/** Unix timestamp when key expires (undefined = never expires). */
|
|
42
48
|
expiry?: numberType | null | undefined
|
|
49
|
+
/** Whether this authorization provisions an admin access key. */
|
|
50
|
+
isAdmin?: boolean | undefined
|
|
43
51
|
/** TIP20 spending limits for this key. */
|
|
44
52
|
limits?: readonly TokenLimit<bigintType, numberType>[] | undefined
|
|
45
53
|
/**
|
|
@@ -50,8 +58,8 @@ export type KeyAuthorization<
|
|
|
50
58
|
* - `[...]` = only listed contract+selector combinations allowed
|
|
51
59
|
*/
|
|
52
60
|
scopes?: readonly Scope[] | undefined
|
|
53
|
-
/** Key type
|
|
54
|
-
type: SignatureEnvelope.Type
|
|
61
|
+
/** Key type (secp256k1, P256, WebAuthn, or multisig). */
|
|
62
|
+
type: SignatureEnvelope.Type | 'multisig'
|
|
55
63
|
/**
|
|
56
64
|
* Optional 32-byte witness bound into the signing hash.
|
|
57
65
|
*
|
|
@@ -62,37 +70,28 @@ export type KeyAuthorization<
|
|
|
62
70
|
* [TIP-1053 Specification](https://tips.sh/1053)
|
|
63
71
|
*/
|
|
64
72
|
witness?: Hex.Hex | undefined
|
|
65
|
-
} &
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
//
|
|
71
|
-
// [TIP-1049 Specification](https://tips.sh/1049)
|
|
72
|
-
| {
|
|
73
|
-
/** Account address this authorization is bound to. */
|
|
74
|
-
account: Address.Address
|
|
75
|
-
/** Whether this authorization provisions an admin access key. */
|
|
76
|
-
isAdmin: boolean
|
|
73
|
+
} & (signed extends true
|
|
74
|
+
? {
|
|
75
|
+
signature:
|
|
76
|
+
| SignatureEnvelope.Primitive<numberType>
|
|
77
|
+
| SignatureEnvelope.Multisig<numberType>
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
})
|
|
79
|
+
: {
|
|
80
|
+
signature?:
|
|
81
|
+
| SignatureEnvelope.Primitive<numberType>
|
|
82
|
+
| SignatureEnvelope.Multisig<numberType>
|
|
83
|
+
| undefined
|
|
84
|
+
})
|
|
85
85
|
|
|
86
86
|
/** Signature that can authorize an access key. */
|
|
87
|
-
export type Signature<numberType = number> =
|
|
87
|
+
export type Signature<numberType = number> =
|
|
88
88
|
| SignatureEnvelope.Primitive<numberType>
|
|
89
89
|
| SignatureEnvelope.Multisig<numberType>
|
|
90
|
-
>
|
|
91
90
|
|
|
92
91
|
/** RPC-formatted signature that can authorize an access key. */
|
|
93
|
-
export type SignatureRpc =
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
export type SignatureRpc =
|
|
93
|
+
| SignatureEnvelope.MultisigRpc
|
|
94
|
+
| SignatureEnvelope.PrimitiveRpc
|
|
96
95
|
|
|
97
96
|
/** Input type for a Key Authorization. */
|
|
98
97
|
export type Input = KeyAuthorization<false, bigint, number>
|
|
@@ -112,32 +111,32 @@ export type Rpc = {
|
|
|
112
111
|
/** Key identifier. */
|
|
113
112
|
keyId: Address.Address
|
|
114
113
|
/** Key type. */
|
|
115
|
-
keyType: SignatureEnvelope.Type
|
|
114
|
+
keyType: SignatureEnvelope.Type | 'multisig'
|
|
116
115
|
/** Token spending limits. */
|
|
117
116
|
limits?: readonly RpcTokenLimit[] | null | undefined
|
|
118
|
-
/**
|
|
119
|
-
signature:
|
|
117
|
+
/** Primitive or multisig signature authorizing this key. */
|
|
118
|
+
signature: SignatureEnvelope.PrimitiveRpc | SignatureEnvelope.MultisigRpc
|
|
120
119
|
/** Optional 32-byte witness (hex). */
|
|
121
120
|
witness?: Hex.Hex | null | undefined
|
|
122
121
|
}
|
|
123
122
|
|
|
124
123
|
/** RPC representation of a token limit (matches node's `TokenLimit` serde). */
|
|
125
124
|
export type RpcTokenLimit = {
|
|
126
|
-
token: Address.Address
|
|
127
125
|
limit: Hex.Hex
|
|
128
126
|
period?: Hex.Hex | null | undefined
|
|
127
|
+
token: Address.Address
|
|
129
128
|
}
|
|
130
129
|
|
|
131
130
|
/** RPC representation of a call scope (matches node's `CallScope` serde). */
|
|
132
131
|
export type RpcCallScope = {
|
|
133
|
-
target: Address.Address
|
|
134
132
|
selectorRules?: readonly RpcSelectorRule[] | null | undefined
|
|
133
|
+
target: Address.Address
|
|
135
134
|
}
|
|
136
135
|
|
|
137
136
|
/** RPC representation of a selector rule (matches node's `SelectorRule` serde). */
|
|
138
137
|
export type RpcSelectorRule = {
|
|
139
|
-
selector: Hex.Hex
|
|
140
138
|
recipients?: readonly Address.Address[] | null | undefined
|
|
139
|
+
selector: Hex.Hex
|
|
141
140
|
}
|
|
142
141
|
|
|
143
142
|
/** Signed representation of a Key Authorization. */
|
|
@@ -148,10 +147,11 @@ export type Signed<bigintType = bigint, numberType = number> = KeyAuthorization<
|
|
|
148
147
|
>
|
|
149
148
|
|
|
150
149
|
type SignatureValue =
|
|
151
|
-
|
|
|
150
|
+
| SignatureEnvelope.from.MultisigFromConfig
|
|
151
|
+
| UnionPartialBy<SignatureEnvelope.Primitive, 'prehash' | 'type'>
|
|
152
|
+
| PartialBy<SignatureEnvelope.Multisig, 'type'>
|
|
152
153
|
| SignatureEnvelope.Secp256k1Flat
|
|
153
154
|
| SignatureEnvelope.Serialized
|
|
154
|
-
| SignatureEnvelope.from.MultisigFromConfig
|
|
155
155
|
|
|
156
156
|
type BaseTuple = readonly [
|
|
157
157
|
chainId: Hex.Hex,
|
|
@@ -227,14 +227,6 @@ export type Tuple<signed extends boolean = boolean> = signed extends true
|
|
|
227
227
|
export type Scope = {
|
|
228
228
|
/** Target contract address. */
|
|
229
229
|
address: Address.Address
|
|
230
|
-
/**
|
|
231
|
-
* 4-byte function selector, or a human-readable ABI signature
|
|
232
|
-
* (e.g. `'transfer(address,uint256)'` or `'function transfer(address,uint256)'`).
|
|
233
|
-
*
|
|
234
|
-
* Signatures are encoded into a 4-byte selector automatically.
|
|
235
|
-
* Omit to allow any selector on this contract.
|
|
236
|
-
*/
|
|
237
|
-
selector?: Hex.Hex | string | undefined
|
|
238
230
|
/**
|
|
239
231
|
* Recipient allowlist for this selector (first ABI `address` argument).
|
|
240
232
|
*
|
|
@@ -244,6 +236,14 @@ export type Scope = {
|
|
|
244
236
|
* Only valid for constrained selectors: `transfer`, `approve`, `transferWithMemo`.
|
|
245
237
|
*/
|
|
246
238
|
recipients?: readonly Address.Address[] | undefined
|
|
239
|
+
/**
|
|
240
|
+
* 4-byte function selector, or a human-readable ABI signature
|
|
241
|
+
* (e.g. `'transfer(address,uint256)'` or `'function transfer(address,uint256)'`).
|
|
242
|
+
*
|
|
243
|
+
* Signatures are encoded into a 4-byte selector automatically.
|
|
244
|
+
* Omit to allow any selector on this contract.
|
|
245
|
+
*/
|
|
246
|
+
selector?: Hex.Hex | string | undefined
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
/**
|
|
@@ -255,8 +255,6 @@ export type Scope = {
|
|
|
255
255
|
* [Access Keys Specification](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#access-keys)
|
|
256
256
|
*/
|
|
257
257
|
export type TokenLimit<bigintType = bigint, numberType = number> = {
|
|
258
|
-
/** Address of the TIP-20 token. */
|
|
259
|
-
token: Address.Address
|
|
260
258
|
/** Maximum spending amount for this token (enforced over the key's lifetime, or per period if `period` \> 0). */
|
|
261
259
|
limit: bigintType
|
|
262
260
|
/**
|
|
@@ -266,6 +264,8 @@ export type TokenLimit<bigintType = bigint, numberType = number> = {
|
|
|
266
264
|
* - `\> 0` = periodic limit that resets every `period` seconds
|
|
267
265
|
*/
|
|
268
266
|
period?: numberType | undefined
|
|
267
|
+
/** Address of the TIP-20 token. */
|
|
268
|
+
token: Address.Address
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
/**
|
|
@@ -433,12 +433,13 @@ export function from<
|
|
|
433
433
|
options: from.Options<signature> = {},
|
|
434
434
|
): from.ReturnType<authorization, signature> {
|
|
435
435
|
if ('keyId' in authorization) return fromRpc(authorization as Rpc) as never
|
|
436
|
+
assertAccountBinding(authorization.type, authorization.account)
|
|
436
437
|
const auth = authorization as KeyAuthorization & {
|
|
437
|
-
limits?: readonly { token: Address.Address
|
|
438
|
+
limits?: readonly { limit: bigint; token: Address.Address }[]
|
|
438
439
|
scopes?: readonly {
|
|
439
440
|
address: Address.Address
|
|
440
|
-
selector?: Hex.Hex | string
|
|
441
441
|
recipients?: readonly Address.Address[]
|
|
442
|
+
selector?: Hex.Hex | string
|
|
442
443
|
}[]
|
|
443
444
|
}
|
|
444
445
|
if (auth.witness !== undefined) assertWitness(auth.witness)
|
|
@@ -471,8 +472,12 @@ export declare namespace from {
|
|
|
471
472
|
type Options<
|
|
472
473
|
signature extends SignatureValue | undefined = SignatureValue | undefined,
|
|
473
474
|
> = {
|
|
474
|
-
/** The signature to attach to the Key Authorization. */
|
|
475
|
-
signature?:
|
|
475
|
+
/** The primitive or multisig signature to attach to the Key Authorization. */
|
|
476
|
+
signature?:
|
|
477
|
+
| signature
|
|
478
|
+
| SignatureEnvelope.Primitive
|
|
479
|
+
| SignatureEnvelope.Multisig
|
|
480
|
+
| undefined
|
|
476
481
|
}
|
|
477
482
|
|
|
478
483
|
type ReturnType<
|
|
@@ -486,13 +491,16 @@ export declare namespace from {
|
|
|
486
491
|
? {
|
|
487
492
|
signature: Extract<
|
|
488
493
|
SignatureEnvelope.from.ReturnValue<signature>,
|
|
489
|
-
|
|
494
|
+
SignatureEnvelope.Primitive | SignatureEnvelope.Multisig
|
|
490
495
|
>
|
|
491
496
|
}
|
|
492
497
|
: {})
|
|
493
498
|
>
|
|
494
499
|
|
|
495
|
-
type ErrorType =
|
|
500
|
+
type ErrorType =
|
|
501
|
+
| InvalidSignatureTypeError
|
|
502
|
+
| MissingAccountError
|
|
503
|
+
| Errors.GlobalErrorType
|
|
496
504
|
}
|
|
497
505
|
|
|
498
506
|
/**
|
|
@@ -531,6 +539,7 @@ export function fromRpc(authorization: Rpc): Signed {
|
|
|
531
539
|
const witness = authorization.witness ?? undefined
|
|
532
540
|
const isAdmin = authorization.isAdmin ?? undefined
|
|
533
541
|
const account = authorization.account ?? undefined
|
|
542
|
+
assertAccountBinding(keyType, account)
|
|
534
543
|
const signature = SignatureEnvelope.fromRpc(authorization.signature)
|
|
535
544
|
assertSignature(signature)
|
|
536
545
|
if (witness !== undefined) assertWitness(witness)
|
|
@@ -552,9 +561,6 @@ export function fromRpc(authorization: Rpc): Signed {
|
|
|
552
561
|
})
|
|
553
562
|
: undefined
|
|
554
563
|
|
|
555
|
-
const accountBinding =
|
|
556
|
-
account !== undefined ? { account, isAdmin: isAdmin ?? false } : {}
|
|
557
|
-
|
|
558
564
|
return {
|
|
559
565
|
address: keyId,
|
|
560
566
|
chainId: chainId === '0x' ? 0n : Hex.toBigInt(chainId),
|
|
@@ -570,12 +576,16 @@ export function fromRpc(authorization: Rpc): Signed {
|
|
|
570
576
|
signature,
|
|
571
577
|
type: keyType,
|
|
572
578
|
...(witness !== undefined ? { witness } : {}),
|
|
573
|
-
...
|
|
579
|
+
...(account !== undefined ? { account } : {}),
|
|
580
|
+
...(isAdmin ? { isAdmin: true as const } : {}),
|
|
574
581
|
}
|
|
575
582
|
}
|
|
576
583
|
|
|
577
584
|
export declare namespace fromRpc {
|
|
578
|
-
type ErrorType =
|
|
585
|
+
type ErrorType =
|
|
586
|
+
| InvalidSignatureTypeError
|
|
587
|
+
| MissingAccountError
|
|
588
|
+
| Errors.GlobalErrorType
|
|
579
589
|
}
|
|
580
590
|
|
|
581
591
|
/**
|
|
@@ -647,6 +657,8 @@ export function fromTuple<const tuple extends Tuple>(
|
|
|
647
657
|
return 'p256'
|
|
648
658
|
case '0x02':
|
|
649
659
|
return 'webAuthn'
|
|
660
|
+
case '0x03':
|
|
661
|
+
return 'multisig'
|
|
650
662
|
default:
|
|
651
663
|
throw new Error(`Invalid key type: ${keyType_hex}`)
|
|
652
664
|
}
|
|
@@ -702,8 +714,7 @@ export function fromTuple<const tuple extends Tuple>(
|
|
|
702
714
|
const account = isAbsent(rawAccount)
|
|
703
715
|
? undefined
|
|
704
716
|
: (rawAccount as Address.Address)
|
|
705
|
-
|
|
706
|
-
account !== undefined ? { account, isAdmin: isAdmin ?? false } : {}
|
|
717
|
+
assertAccountBinding(keyType, account)
|
|
707
718
|
const args: KeyAuthorization = {
|
|
708
719
|
address: keyId,
|
|
709
720
|
chainId: chainId === '0x' ? 0n : Hex.toBigInt(chainId),
|
|
@@ -712,7 +723,8 @@ export function fromTuple<const tuple extends Tuple>(
|
|
|
712
723
|
...(limits !== undefined ? { limits } : {}),
|
|
713
724
|
...(scopes !== undefined ? { scopes } : {}),
|
|
714
725
|
...(witness !== undefined ? { witness } : {}),
|
|
715
|
-
...
|
|
726
|
+
...(account !== undefined ? { account } : {}),
|
|
727
|
+
...(isAdmin ? { isAdmin: true as const } : {}),
|
|
716
728
|
}
|
|
717
729
|
if (signatureSerialized) {
|
|
718
730
|
const signature = SignatureEnvelope.deserialize(signatureSerialized)
|
|
@@ -727,7 +739,10 @@ export declare namespace fromTuple {
|
|
|
727
739
|
KeyAuthorization<authorization extends Tuple<true> ? true : false>
|
|
728
740
|
>
|
|
729
741
|
|
|
730
|
-
type ErrorType =
|
|
742
|
+
type ErrorType =
|
|
743
|
+
| InvalidSignatureTypeError
|
|
744
|
+
| MissingAccountError
|
|
745
|
+
| Errors.GlobalErrorType
|
|
731
746
|
}
|
|
732
747
|
|
|
733
748
|
/**
|
|
@@ -933,6 +948,7 @@ export declare namespace serialize {
|
|
|
933
948
|
* @returns An RPC-formatted Key Authorization.
|
|
934
949
|
*/
|
|
935
950
|
export function toRpc(authorization: toRpc.Input): Rpc {
|
|
951
|
+
assertAccountBinding(authorization.type, authorization.account)
|
|
936
952
|
const {
|
|
937
953
|
address,
|
|
938
954
|
scopes,
|
|
@@ -984,7 +1000,9 @@ export function toRpc(authorization: toRpc.Input): Rpc {
|
|
|
984
1000
|
limit: Quantity.fromNumberish(limit),
|
|
985
1001
|
...(period ? { period: Quantity.fromNumberish(period) } : {}),
|
|
986
1002
|
})),
|
|
987
|
-
signature: SignatureEnvelope.toRpc(signature) as
|
|
1003
|
+
signature: SignatureEnvelope.toRpc(signature) as
|
|
1004
|
+
| SignatureEnvelope.PrimitiveRpc
|
|
1005
|
+
| SignatureEnvelope.MultisigRpc,
|
|
988
1006
|
...(allowedCalls ? { allowedCalls } : {}),
|
|
989
1007
|
...(witness !== undefined ? { witness } : {}),
|
|
990
1008
|
...(isAdmin ? { isAdmin: true } : {}),
|
|
@@ -996,7 +1014,10 @@ export declare namespace toRpc {
|
|
|
996
1014
|
/** Numberish input accepted by {@link ox#KeyAuthorization.(toRpc:function)}. */
|
|
997
1015
|
type Input = Signed<Hex.Hex | bigint | number, Hex.Hex | number>
|
|
998
1016
|
|
|
999
|
-
type ErrorType =
|
|
1017
|
+
type ErrorType =
|
|
1018
|
+
| InvalidSignatureTypeError
|
|
1019
|
+
| MissingAccountError
|
|
1020
|
+
| Errors.GlobalErrorType
|
|
1000
1021
|
}
|
|
1001
1022
|
|
|
1002
1023
|
/**
|
|
@@ -1035,6 +1056,7 @@ export declare namespace toRpc {
|
|
|
1035
1056
|
export function toTuple<const authorization extends KeyAuthorization>(
|
|
1036
1057
|
authorization: authorization,
|
|
1037
1058
|
): toTuple.ReturnType<authorization> {
|
|
1059
|
+
assertAccountBinding(authorization.type, authorization.account)
|
|
1038
1060
|
const {
|
|
1039
1061
|
address,
|
|
1040
1062
|
chainId,
|
|
@@ -1059,6 +1081,8 @@ export function toTuple<const authorization extends KeyAuthorization>(
|
|
|
1059
1081
|
return '0x01'
|
|
1060
1082
|
case 'webAuthn':
|
|
1061
1083
|
return '0x02'
|
|
1084
|
+
case 'multisig':
|
|
1085
|
+
return '0x03'
|
|
1062
1086
|
default:
|
|
1063
1087
|
throw new Error(`Invalid key type: ${authorization.type}`)
|
|
1064
1088
|
}
|
|
@@ -1109,7 +1133,7 @@ export function toTuple<const authorization extends KeyAuthorization>(
|
|
|
1109
1133
|
// single entry to this list with `placeholder: '0x'`.
|
|
1110
1134
|
const hasTip1053Plus =
|
|
1111
1135
|
witness !== undefined || isAdmin || account !== undefined
|
|
1112
|
-
const optionals: readonly {
|
|
1136
|
+
const optionals: readonly { placeholder: unknown; value: unknown }[] = [
|
|
1113
1137
|
{
|
|
1114
1138
|
value:
|
|
1115
1139
|
expiry !== null && expiry !== undefined && expiry !== 0
|
|
@@ -1146,7 +1170,10 @@ export declare namespace toTuple {
|
|
|
1146
1170
|
type ReturnType<authorization extends KeyAuthorization = KeyAuthorization> =
|
|
1147
1171
|
Compute<Tuple<authorization extends KeyAuthorization<true> ? true : false>>
|
|
1148
1172
|
|
|
1149
|
-
type ErrorType =
|
|
1173
|
+
type ErrorType =
|
|
1174
|
+
| InvalidSignatureTypeError
|
|
1175
|
+
| MissingAccountError
|
|
1176
|
+
| Errors.GlobalErrorType
|
|
1150
1177
|
}
|
|
1151
1178
|
|
|
1152
1179
|
function bigintToHex(value: bigint): Hex.Hex {
|
|
@@ -1180,13 +1207,22 @@ function resolveSelector(
|
|
|
1180
1207
|
return AbiItem.getSelector(selector)
|
|
1181
1208
|
}
|
|
1182
1209
|
|
|
1210
|
+
function assertAccountBinding(
|
|
1211
|
+
type: KeyAuthorization['type'],
|
|
1212
|
+
account: Address.Address | null | undefined,
|
|
1213
|
+
): void {
|
|
1214
|
+
if (type === 'multisig' && account == null) throw new MissingAccountError()
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1183
1217
|
function assertWitness(witness: Hex.Hex): void {
|
|
1184
1218
|
if (Hex.size(witness) !== 32) throw new InvalidWitnessSizeError(witness)
|
|
1185
1219
|
}
|
|
1186
1220
|
|
|
1187
1221
|
function assertSignature<numberType>(
|
|
1188
1222
|
signature: SignatureEnvelope.SignatureEnvelope<numberType>,
|
|
1189
|
-
): asserts signature is
|
|
1223
|
+
): asserts signature is
|
|
1224
|
+
| SignatureEnvelope.Primitive<numberType>
|
|
1225
|
+
| SignatureEnvelope.Multisig<numberType> {
|
|
1190
1226
|
if (signature.type === 'keychain')
|
|
1191
1227
|
throw new InvalidSignatureTypeError(signature.type)
|
|
1192
1228
|
}
|
|
@@ -1224,3 +1260,11 @@ export class InvalidSignatureTypeError extends Error {
|
|
|
1224
1260
|
)
|
|
1225
1261
|
}
|
|
1226
1262
|
}
|
|
1263
|
+
|
|
1264
|
+
/** Thrown when a multisig key grant omits its parent account binding. */
|
|
1265
|
+
export class MissingAccountError extends Error {
|
|
1266
|
+
override readonly name = 'KeyAuthorization.MissingAccountError'
|
|
1267
|
+
constructor() {
|
|
1268
|
+
super('Multisig key grants require a parent account binding.')
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { factory } from '../../test/tempo/multisig.js'
|
|
1
2
|
import { Hash, Hex, Rlp } from 'ox'
|
|
2
3
|
import { MultisigConfig } from 'ox/tempo'
|
|
3
4
|
import { describe, expect, test } from 'vp/test'
|
|
@@ -9,7 +10,7 @@ const config = MultisigConfig.from({
|
|
|
9
10
|
owners: [{ owner: owner_1, weight: 1 }],
|
|
10
11
|
threshold: 1,
|
|
11
12
|
})
|
|
12
|
-
const account = MultisigConfig.getAddress(config)
|
|
13
|
+
const account = MultisigConfig.getAddress(config, { factory })
|
|
13
14
|
|
|
14
15
|
describe('from', () => {
|
|
15
16
|
test('behavior: normalizes an initial configuration', () => {
|
|
@@ -98,35 +99,59 @@ describe('fromRpc/toRpc', () => {
|
|
|
98
99
|
})
|
|
99
100
|
|
|
100
101
|
describe('getAddress', () => {
|
|
101
|
-
test('example: matches the frozen
|
|
102
|
+
test('example: matches the frozen CREATE2 vector', () => {
|
|
102
103
|
expect(account).toMatchInlineSnapshot(
|
|
103
|
-
`"
|
|
104
|
+
`"0x90ba71cb7534da990a1182cf28c9bf415055e03d"`,
|
|
104
105
|
)
|
|
106
|
+
expect(account).not.toBe('0x8820d1497eeaf4f68e00b2cfc00a2f3b1dbb00da')
|
|
105
107
|
})
|
|
106
108
|
|
|
107
109
|
test('behavior: includes salt, threshold, and owners', () => {
|
|
108
110
|
expect(
|
|
109
|
-
MultisigConfig.getAddress(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
MultisigConfig.getAddress(
|
|
112
|
+
{
|
|
113
|
+
owners: [
|
|
114
|
+
{ owner: owner_1, weight: 1 },
|
|
115
|
+
{ owner: owner_2, weight: 2 },
|
|
116
|
+
],
|
|
117
|
+
salt: `0x${'42'.repeat(32)}`,
|
|
118
|
+
threshold: 2,
|
|
119
|
+
},
|
|
120
|
+
{ factory },
|
|
121
|
+
),
|
|
122
|
+
).toMatchInlineSnapshot(`"0x7898a7d1dd96946d2a968de1540ca884a244320c"`)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test('behavior: is stable and binds the salt', () => {
|
|
126
|
+
expect({
|
|
127
|
+
repeated: MultisigConfig.getAddress(config, { factory }),
|
|
128
|
+
salted: MultisigConfig.getAddress(
|
|
129
|
+
{
|
|
130
|
+
...config,
|
|
131
|
+
salt: `0x${'42'.repeat(32)}`,
|
|
132
|
+
},
|
|
133
|
+
{ factory },
|
|
134
|
+
),
|
|
135
|
+
}).toMatchInlineSnapshot(`
|
|
136
|
+
{
|
|
137
|
+
"repeated": "0x90ba71cb7534da990a1182cf28c9bf415055e03d",
|
|
138
|
+
"salted": "0xa1a8472f4a01772db729d8ebc73fe46120750b83",
|
|
139
|
+
}
|
|
140
|
+
`)
|
|
118
141
|
})
|
|
119
142
|
|
|
120
143
|
test('error: rejects a current configuration', () => {
|
|
121
144
|
expect(() =>
|
|
122
|
-
MultisigConfig.getAddress({ ...config, version: 1n }),
|
|
145
|
+
MultisigConfig.getAddress({ ...config, version: 1n }, { factory }),
|
|
123
146
|
).toThrowErrorMatchingInlineSnapshot(
|
|
124
147
|
`[MultisigConfig.InvalidConfigError: Invalid native multisig config: account address requires version zero.]`,
|
|
125
148
|
)
|
|
126
149
|
})
|
|
127
150
|
|
|
128
151
|
test('behavior: accepts numeric zero for an initial configuration', () => {
|
|
129
|
-
expect(
|
|
152
|
+
expect(
|
|
153
|
+
MultisigConfig.getAddress({ ...config, version: 0 }, { factory }),
|
|
154
|
+
).toBe(account)
|
|
130
155
|
})
|
|
131
156
|
})
|
|
132
157
|
|
|
@@ -151,7 +176,7 @@ describe('getSignPayload', () => {
|
|
|
151
176
|
expect(
|
|
152
177
|
MultisigConfig.getSignPayload({ account, config, payload }),
|
|
153
178
|
).toMatchInlineSnapshot(
|
|
154
|
-
`"
|
|
179
|
+
`"0x728efe90611b01c91c2be0da56e7eb8e0d2c274c84f97182e274187dde0b8a20"`,
|
|
155
180
|
)
|
|
156
181
|
})
|
|
157
182
|
|
|
@@ -206,14 +231,14 @@ describe('assert/validate', () => {
|
|
|
206
231
|
})
|
|
207
232
|
const rlp = Rlp.fromHex(MultisigConfig.toTuple(boundary))
|
|
208
233
|
expect({
|
|
209
|
-
account: MultisigConfig.getAddress(boundary),
|
|
234
|
+
account: MultisigConfig.getAddress(boundary, { factory }),
|
|
210
235
|
commitment: MultisigConfig.getCommitment(boundary),
|
|
211
236
|
rlpHash: Hash.keccak256(rlp),
|
|
212
237
|
rlpLength: Hex.size(rlp),
|
|
213
238
|
valid: MultisigConfig.validate(boundary),
|
|
214
239
|
}).toMatchInlineSnapshot(`
|
|
215
240
|
{
|
|
216
|
-
"account": "
|
|
241
|
+
"account": "0x6acb25715a2b0cf05c098f753a87d9b38471e99f",
|
|
217
242
|
"commitment": "0x0dc47a7ab45ffa21a01bfd115427e26617b5a57d7ccbea57db2fd4537ba96f56",
|
|
218
243
|
"rlpHash": "0xbaf0d030add91caaa10815d2e99c942f1e39b0d199216973781adb4fc1af6955",
|
|
219
244
|
"rlpLength": 1145,
|
|
@@ -229,7 +254,7 @@ describe('assert/validate', () => {
|
|
|
229
254
|
{ owner: owner_1, weight: 128 },
|
|
230
255
|
{ owner: owner_2, weight: 127 },
|
|
231
256
|
],
|
|
232
|
-
threshold:
|
|
257
|
+
threshold: 8,
|
|
233
258
|
}),
|
|
234
259
|
).toBe(true)
|
|
235
260
|
})
|
|
@@ -295,7 +320,7 @@ describe('assert/validate', () => {
|
|
|
295
320
|
{ owner: owner_1, weight: 128 },
|
|
296
321
|
{ owner: owner_2, weight: 128 },
|
|
297
322
|
],
|
|
298
|
-
threshold:
|
|
323
|
+
threshold: 8,
|
|
299
324
|
},
|
|
300
325
|
name: 'weight overflow',
|
|
301
326
|
},
|
|
@@ -342,7 +367,6 @@ describe('assert/validate', () => {
|
|
|
342
367
|
test('exports', () => {
|
|
343
368
|
expect(Object.keys(MultisigConfig)).toMatchInlineSnapshot(`
|
|
344
369
|
[
|
|
345
|
-
"maxNestingDepth",
|
|
346
370
|
"maxOwnerSignatureBytes",
|
|
347
371
|
"maxOwners",
|
|
348
372
|
"maxSignatures",
|