ox 0.14.55 → 0.14.57
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 +48 -0
- package/_cjs/tempo/{MultisigConfig.js → AccountConfig.js} +32 -9
- package/_cjs/tempo/AccountConfig.js.map +1 -0
- package/_cjs/tempo/{MultisigOperation.js → AccountOperation.js} +29 -29
- package/_cjs/tempo/AccountOperation.js.map +1 -0
- package/_cjs/tempo/{MultisigSimulation.js → AccountSimulation.js} +22 -13
- package/_cjs/tempo/AccountSimulation.js.map +1 -0
- package/_cjs/tempo/KeyAuthorization.js +10 -18
- package/_cjs/tempo/KeyAuthorization.js.map +1 -1
- package/_cjs/tempo/SignatureEnvelope.js +64 -64
- package/_cjs/tempo/SignatureEnvelope.js.map +1 -1
- package/_cjs/tempo/TransactionRequest.js +15 -10
- package/_cjs/tempo/TransactionRequest.js.map +1 -1
- package/_cjs/tempo/index.js +4 -4
- package/_cjs/tempo/index.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/tempo/{MultisigConfig.js → AccountConfig.js} +161 -64
- package/_esm/tempo/AccountConfig.js.map +1 -0
- package/_esm/tempo/{MultisigOperation.js → AccountOperation.js} +64 -64
- package/_esm/tempo/AccountOperation.js.map +1 -0
- package/_esm/tempo/{MultisigSimulation.js → AccountSimulation.js} +35 -25
- package/_esm/tempo/AccountSimulation.js.map +1 -0
- package/_esm/tempo/KeyAuthorization.js +16 -19
- package/_esm/tempo/KeyAuthorization.js.map +1 -1
- package/_esm/tempo/SignatureEnvelope.js +71 -71
- package/_esm/tempo/SignatureEnvelope.js.map +1 -1
- package/_esm/tempo/TransactionRequest.js +15 -10
- package/_esm/tempo/TransactionRequest.js.map +1 -1
- package/_esm/tempo/index.js +50 -48
- package/_esm/tempo/index.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_types/tempo/{MultisigConfig.d.ts → AccountConfig.d.ts} +156 -66
- package/_types/tempo/AccountConfig.d.ts.map +1 -0
- package/_types/tempo/{MultisigOperation.d.ts → AccountOperation.d.ts} +62 -62
- package/_types/tempo/AccountOperation.d.ts.map +1 -0
- package/_types/tempo/{MultisigSimulation.d.ts → AccountSimulation.d.ts} +25 -21
- package/_types/tempo/AccountSimulation.d.ts.map +1 -0
- package/_types/tempo/KeyAuthorization.d.ts +28 -23
- package/_types/tempo/KeyAuthorization.d.ts.map +1 -1
- package/_types/tempo/RpcSchemaTempo.d.ts +13 -13
- package/_types/tempo/RpcSchemaTempo.d.ts.map +1 -1
- package/_types/tempo/SignatureEnvelope.d.ts +36 -33
- package/_types/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/_types/tempo/TransactionRequest.d.ts +11 -9
- package/_types/tempo/TransactionRequest.d.ts.map +1 -1
- package/_types/tempo/index.d.ts +50 -48
- package/_types/tempo/index.d.ts.map +1 -1
- package/_types/version.d.ts +1 -1
- package/package.json +31 -31
- package/tempo/AccountConfig/package.json +6 -0
- package/tempo/AccountConfig.test-d/package.json +6 -0
- package/tempo/AccountConfig.test-d.ts +72 -0
- package/tempo/AccountConfig.test.ts +642 -0
- package/tempo/{MultisigConfig.ts → AccountConfig.ts} +212 -75
- package/tempo/AccountOperation/package.json +6 -0
- package/tempo/AccountOperation.test-d/package.json +6 -0
- package/tempo/AccountOperation.test-d.ts +71 -0
- package/tempo/{MultisigOperation.test.ts → AccountOperation.test.ts} +129 -129
- package/tempo/{MultisigOperation.ts → AccountOperation.ts} +95 -97
- package/tempo/AccountSimulation/package.json +6 -0
- package/tempo/AccountSimulation.test-d/package.json +6 -0
- package/tempo/{MultisigSimulation.test-d.ts → AccountSimulation.test-d.ts} +7 -9
- package/tempo/{MultisigSimulation.test.ts → AccountSimulation.test.ts} +73 -29
- package/tempo/{MultisigSimulation.ts → AccountSimulation.ts} +47 -35
- package/tempo/KeyAuthorization.test-d.ts +19 -29
- package/tempo/KeyAuthorization.test.ts +151 -74
- package/tempo/KeyAuthorization.ts +40 -61
- package/tempo/RpcSchemaTempo.test-d.ts +20 -20
- package/tempo/RpcSchemaTempo.ts +13 -13
- package/tempo/SignatureEnvelope.test-d.ts +7 -7
- package/tempo/SignatureEnvelope.test.ts +34 -34
- package/tempo/SignatureEnvelope.ts +107 -103
- package/tempo/Transaction.test.ts +4 -4
- package/tempo/TransactionRequest.test-d.ts +17 -8
- package/tempo/TransactionRequest.test.ts +31 -21
- package/tempo/TransactionRequest.ts +29 -20
- package/tempo/{multisig.e2e.test.ts → configurableAccounts.e2e.test.ts} +16 -16
- package/tempo/index.ts +50 -48
- package/version.ts +1 -1
- package/_cjs/tempo/MultisigConfig.js.map +0 -1
- package/_cjs/tempo/MultisigOperation.js.map +0 -1
- package/_cjs/tempo/MultisigSimulation.js.map +0 -1
- package/_esm/tempo/MultisigConfig.js.map +0 -1
- package/_esm/tempo/MultisigOperation.js.map +0 -1
- package/_esm/tempo/MultisigSimulation.js.map +0 -1
- package/_types/tempo/MultisigConfig.d.ts.map +0 -1
- package/_types/tempo/MultisigOperation.d.ts.map +0 -1
- package/_types/tempo/MultisigSimulation.d.ts.map +0 -1
- package/tempo/MultisigConfig/package.json +0 -6
- package/tempo/MultisigConfig.test-d/package.json +0 -6
- package/tempo/MultisigConfig.test-d.ts +0 -52
- package/tempo/MultisigConfig.test.ts +0 -391
- package/tempo/MultisigOperation/package.json +0 -6
- package/tempo/MultisigOperation.test-d/package.json +0 -6
- package/tempo/MultisigOperation.test-d.ts +0 -71
- package/tempo/MultisigSimulation/package.json +0 -6
- package/tempo/MultisigSimulation.test-d/package.json +0 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AccountConfig, AccountSimulation } from 'ox/tempo'
|
|
2
2
|
import { describe, expect, test } from 'vitest'
|
|
3
3
|
|
|
4
4
|
const config =
|
|
@@ -12,11 +12,11 @@ const rpc = {
|
|
|
12
12
|
},
|
|
13
13
|
],
|
|
14
14
|
config,
|
|
15
|
-
} as const satisfies
|
|
15
|
+
} as const satisfies AccountSimulation.Rpc
|
|
16
16
|
|
|
17
17
|
describe('fromRpc', () => {
|
|
18
18
|
test('behavior: decodes the configuration', () => {
|
|
19
|
-
expect(
|
|
19
|
+
expect(AccountSimulation.fromRpc(rpc)).toMatchInlineSnapshot(`
|
|
20
20
|
{
|
|
21
21
|
"approvals": [
|
|
22
22
|
{
|
|
@@ -49,43 +49,43 @@ describe('fromRpc', () => {
|
|
|
49
49
|
'0xf843a0000000000000000000000000000000000000000000000000000000000000000088ffffffffffffffff01d7d694111111111111111111111111111111111111111101' as const
|
|
50
50
|
|
|
51
51
|
expect(
|
|
52
|
-
|
|
52
|
+
AccountSimulation.fromRpc({ ...rpc, approvals: [], config }).config
|
|
53
53
|
.version,
|
|
54
54
|
).toMatchInlineSnapshot(`18446744073709551615n`)
|
|
55
55
|
})
|
|
56
56
|
|
|
57
57
|
test('error: rejects excess root approvals', () => {
|
|
58
58
|
expect(() =>
|
|
59
|
-
|
|
59
|
+
AccountSimulation.fromRpc({
|
|
60
60
|
...rpc,
|
|
61
61
|
approvals: Array.from({ length: 9 }, () => rpc.approvals[0]),
|
|
62
62
|
}),
|
|
63
63
|
).toThrowErrorMatchingInlineSnapshot(
|
|
64
|
-
`[
|
|
64
|
+
`[AccountSimulation.InvalidSimulationError: Invalid account simulation: approval count exceeds 8.]`,
|
|
65
65
|
)
|
|
66
66
|
})
|
|
67
67
|
test('error: rejects nested approvals', () => {
|
|
68
68
|
expect(() =>
|
|
69
|
-
|
|
69
|
+
AccountSimulation.fromRpc({
|
|
70
70
|
...rpc,
|
|
71
|
-
approvals: [{ type: '
|
|
71
|
+
approvals: [{ type: 'configurable', spec: rpc }],
|
|
72
72
|
} as never),
|
|
73
73
|
).toThrowErrorMatchingInlineSnapshot(
|
|
74
|
-
`[
|
|
74
|
+
`[AccountSimulation.InvalidSimulationError: Invalid account simulation: only untagged primitive owner approvals are allowed.]`,
|
|
75
75
|
)
|
|
76
76
|
})
|
|
77
77
|
|
|
78
78
|
test('error: rejects trailing configuration bytes', () => {
|
|
79
79
|
expect(() =>
|
|
80
|
-
|
|
80
|
+
AccountSimulation.fromRpc({ ...rpc, config: `${config}00` }),
|
|
81
81
|
).toThrowErrorMatchingInlineSnapshot(
|
|
82
|
-
`[
|
|
82
|
+
`[AccountSimulation.InvalidSimulationError: Invalid account simulation: noncanonical config encoding.]`,
|
|
83
83
|
)
|
|
84
84
|
})
|
|
85
85
|
|
|
86
86
|
test('error: rejects malformed configuration RLP', () => {
|
|
87
87
|
expect(() =>
|
|
88
|
-
|
|
88
|
+
AccountSimulation.fromRpc({ ...rpc, config: '0xf8' }),
|
|
89
89
|
).toThrowErrorMatchingInlineSnapshot(
|
|
90
90
|
`[Cursor.PositionOutOfBoundsError: Position \`1\` is out of bounds (\`0 < position < 1\`).]`,
|
|
91
91
|
)
|
|
@@ -93,9 +93,9 @@ describe('fromRpc', () => {
|
|
|
93
93
|
|
|
94
94
|
test('error: rejects a non-list configuration', () => {
|
|
95
95
|
expect(() =>
|
|
96
|
-
|
|
96
|
+
AccountSimulation.fromRpc({ ...rpc, config: '0x01' }),
|
|
97
97
|
).toThrowErrorMatchingInlineSnapshot(
|
|
98
|
-
`[
|
|
98
|
+
`[AccountSimulation.InvalidSimulationError: Invalid account simulation: invalid config encoding.]`,
|
|
99
99
|
)
|
|
100
100
|
})
|
|
101
101
|
|
|
@@ -105,17 +105,37 @@ describe('fromRpc', () => {
|
|
|
105
105
|
.replace('118002', '11810002') as `0x${string}`
|
|
106
106
|
|
|
107
107
|
expect(() =>
|
|
108
|
-
|
|
108
|
+
AccountSimulation.fromRpc({ ...rpc, config: noncanonical }),
|
|
109
109
|
).toThrowErrorMatchingInlineSnapshot(
|
|
110
|
-
`[
|
|
110
|
+
`[AccountSimulation.InvalidSimulationError: Invalid account simulation: invalid config encoding.]`,
|
|
111
111
|
)
|
|
112
112
|
})
|
|
113
113
|
})
|
|
114
114
|
|
|
115
115
|
describe('toRpc', () => {
|
|
116
|
+
test('behavior: round-trips the grant signer', () => {
|
|
117
|
+
const signer = '0x2222222222222222222222222222222222222222'
|
|
118
|
+
const spec = AccountSimulation.fromRpc({ ...rpc, signer })
|
|
119
|
+
expect(spec.signer).toBe(signer)
|
|
120
|
+
expect(AccountSimulation.toRpc(spec).signer).toBe(signer)
|
|
121
|
+
expect(
|
|
122
|
+
'signer' in AccountSimulation.toRpc(AccountSimulation.fromRpc(rpc)),
|
|
123
|
+
).toBe(false)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('error: rejects an invalid grant signer', () => {
|
|
127
|
+
expect(() =>
|
|
128
|
+
AccountSimulation.fromRpc({ ...rpc, signer: '0x1234' }),
|
|
129
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
130
|
+
[Address.InvalidAddressError: Address "0x1234" is invalid.
|
|
131
|
+
|
|
132
|
+
Details: Address is not a 20 byte (40 hexadecimal character) value.]
|
|
133
|
+
`)
|
|
134
|
+
})
|
|
135
|
+
|
|
116
136
|
test('behavior: encodes configurations and shims long key data', () => {
|
|
117
137
|
expect(
|
|
118
|
-
|
|
138
|
+
AccountSimulation.toRpc(AccountSimulation.fromRpc(rpc)),
|
|
119
139
|
).toMatchInlineSnapshot(`
|
|
120
140
|
{
|
|
121
141
|
"approvals": [
|
|
@@ -131,12 +151,12 @@ describe('toRpc', () => {
|
|
|
131
151
|
})
|
|
132
152
|
|
|
133
153
|
test('behavior: preserves short key data', () => {
|
|
134
|
-
const spec =
|
|
154
|
+
const spec = AccountSimulation.fromRpc({
|
|
135
155
|
...rpc,
|
|
136
156
|
approvals: [{ ...rpc.approvals[0], keyData: '0x0102' }],
|
|
137
157
|
})
|
|
138
158
|
|
|
139
|
-
expect(
|
|
159
|
+
expect(AccountSimulation.toRpc(spec).approvals).toMatchInlineSnapshot(`
|
|
140
160
|
[
|
|
141
161
|
{
|
|
142
162
|
"keyData": "0x0102",
|
|
@@ -147,14 +167,38 @@ describe('toRpc', () => {
|
|
|
147
167
|
`)
|
|
148
168
|
})
|
|
149
169
|
|
|
170
|
+
test('behavior: shims key data that is not a valid length hint', () => {
|
|
171
|
+
const keyData = (keyData: `0x${string}`) =>
|
|
172
|
+
AccountSimulation.toRpc(
|
|
173
|
+
AccountSimulation.fromRpc({
|
|
174
|
+
...rpc,
|
|
175
|
+
approvals: [{ ...rpc.approvals[0], keyData }],
|
|
176
|
+
}),
|
|
177
|
+
).approvals[0]?.keyData
|
|
178
|
+
|
|
179
|
+
expect({
|
|
180
|
+
empty: keyData('0x'),
|
|
181
|
+
four: keyData('0x01020304'),
|
|
182
|
+
one: keyData('0x01'),
|
|
183
|
+
three: keyData('0x010203'),
|
|
184
|
+
}).toMatchInlineSnapshot(`
|
|
185
|
+
{
|
|
186
|
+
"empty": "0x0000",
|
|
187
|
+
"four": "0x01020304",
|
|
188
|
+
"one": "0x01",
|
|
189
|
+
"three": "0x0003",
|
|
190
|
+
}
|
|
191
|
+
`)
|
|
192
|
+
})
|
|
193
|
+
|
|
150
194
|
test('behavior: encodes the maximum uint64 configuration version', () => {
|
|
151
|
-
const spec =
|
|
195
|
+
const spec = AccountSimulation.fromRpc(rpc)
|
|
152
196
|
|
|
153
197
|
expect(
|
|
154
|
-
|
|
198
|
+
AccountSimulation.toRpc({
|
|
155
199
|
...spec,
|
|
156
200
|
approvals: [],
|
|
157
|
-
config:
|
|
201
|
+
config: AccountConfig.from({
|
|
158
202
|
owners: [
|
|
159
203
|
{
|
|
160
204
|
owner: '0x1111111111111111111111111111111111111111',
|
|
@@ -162,7 +206,7 @@ describe('toRpc', () => {
|
|
|
162
206
|
},
|
|
163
207
|
],
|
|
164
208
|
threshold: 1,
|
|
165
|
-
version:
|
|
209
|
+
version: AccountConfig.maxVersion,
|
|
166
210
|
}),
|
|
167
211
|
}).config,
|
|
168
212
|
).toMatchInlineSnapshot(
|
|
@@ -171,25 +215,25 @@ describe('toRpc', () => {
|
|
|
171
215
|
})
|
|
172
216
|
|
|
173
217
|
test('error: rejects excess root approvals', () => {
|
|
174
|
-
const spec =
|
|
218
|
+
const spec = AccountSimulation.fromRpc(rpc)
|
|
175
219
|
|
|
176
220
|
expect(() =>
|
|
177
|
-
|
|
221
|
+
AccountSimulation.toRpc({
|
|
178
222
|
...spec,
|
|
179
223
|
approvals: Array.from({ length: 9 }, () => spec.approvals[0]!),
|
|
180
224
|
}),
|
|
181
225
|
).toThrowErrorMatchingInlineSnapshot(
|
|
182
|
-
`[
|
|
226
|
+
`[AccountSimulation.InvalidSimulationError: Invalid account simulation: approval count exceeds 8.]`,
|
|
183
227
|
)
|
|
184
228
|
})
|
|
185
229
|
test('error: rejects nested approvals', () => {
|
|
186
230
|
expect(() =>
|
|
187
|
-
|
|
231
|
+
AccountSimulation.toRpc({
|
|
188
232
|
...rpc,
|
|
189
|
-
approvals: [{ type: '
|
|
233
|
+
approvals: [{ type: 'configurable', spec: rpc }],
|
|
190
234
|
} as never),
|
|
191
235
|
).toThrowErrorMatchingInlineSnapshot(
|
|
192
|
-
`[
|
|
236
|
+
`[AccountSimulation.InvalidSimulationError: Invalid account simulation: only untagged primitive owner approvals are allowed.]`,
|
|
193
237
|
)
|
|
194
238
|
})
|
|
195
239
|
})
|
|
@@ -3,13 +3,13 @@ import * as Errors from '../core/Errors.js'
|
|
|
3
3
|
import * as Hex from '../core/Hex.js'
|
|
4
4
|
import type { Compute } from '../core/internal/types.js'
|
|
5
5
|
import * as Rlp from '../core/Rlp.js'
|
|
6
|
-
import * as
|
|
6
|
+
import * as AccountConfig from './AccountConfig.js'
|
|
7
7
|
import type * as SignatureEnvelope from './SignatureEnvelope.js'
|
|
8
8
|
|
|
9
|
-
/**
|
|
9
|
+
/** Configurable account owner approval used for RPC simulation. */
|
|
10
10
|
export type Approval = PrimitiveApproval
|
|
11
11
|
|
|
12
|
-
/** JSON-RPC
|
|
12
|
+
/** JSON-RPC configurable account owner approval used for RPC simulation. */
|
|
13
13
|
export type ApprovalRpc = PrimitiveApproval
|
|
14
14
|
|
|
15
15
|
/** Primitive owner approval used for RPC simulation. */
|
|
@@ -22,70 +22,81 @@ export type PrimitiveApproval = {
|
|
|
22
22
|
owner: Address.Address
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/** JSON-RPC representation of
|
|
25
|
+
/** JSON-RPC representation of an account simulation spec. */
|
|
26
26
|
export type Rpc = Compute<{
|
|
27
27
|
/** Owner approvals to model. */
|
|
28
28
|
approvals: readonly ApprovalRpc[]
|
|
29
29
|
/** Canonical RLP-encoded applicable configuration. */
|
|
30
30
|
config: Hex.Hex
|
|
31
|
+
/** Account that signs the modeled key authorization. Omitted for a direct signature. */
|
|
32
|
+
signer?: Address.Address | undefined
|
|
31
33
|
}>
|
|
32
34
|
|
|
33
|
-
/**
|
|
35
|
+
/** Account simulation spec used to construct an RPC simulation signature. */
|
|
34
36
|
export type Spec = Compute<{
|
|
35
37
|
/** Owner approvals to model. */
|
|
36
38
|
approvals: readonly Approval[]
|
|
37
39
|
/** Complete applicable configuration. */
|
|
38
|
-
config:
|
|
40
|
+
config: AccountConfig.Config
|
|
41
|
+
/** Account that signs the modeled key authorization. Omitted for a direct signature. */
|
|
42
|
+
signer?: Address.Address | undefined
|
|
39
43
|
}>
|
|
40
44
|
|
|
41
45
|
/**
|
|
42
|
-
* Converts a JSON-RPC
|
|
46
|
+
* Converts a JSON-RPC account simulation spec to its domain representation.
|
|
43
47
|
*
|
|
44
48
|
* @example
|
|
45
49
|
* ```ts twoslash
|
|
46
50
|
* // @noErrors
|
|
47
|
-
* import {
|
|
51
|
+
* import { AccountSimulation } from 'ox/tempo'
|
|
48
52
|
*
|
|
49
|
-
* const spec =
|
|
53
|
+
* const spec = AccountSimulation.fromRpc(specRpc)
|
|
50
54
|
* ```
|
|
51
55
|
*
|
|
52
|
-
* @param spec - JSON-RPC
|
|
53
|
-
* @returns The
|
|
56
|
+
* @param spec - JSON-RPC account simulation spec.
|
|
57
|
+
* @returns The account simulation spec with decoded configurations.
|
|
54
58
|
*/
|
|
55
59
|
export function fromRpc(spec: Rpc): Spec {
|
|
56
|
-
const { approvals, config } = spec
|
|
60
|
+
const { approvals, config, signer } = spec
|
|
57
61
|
assertApprovals(approvals)
|
|
58
|
-
|
|
62
|
+
if (signer !== undefined) Address.assert(signer)
|
|
63
|
+
return {
|
|
64
|
+
approvals,
|
|
65
|
+
config: deserializeConfig(config),
|
|
66
|
+
...(signer !== undefined ? { signer } : {}),
|
|
67
|
+
}
|
|
59
68
|
}
|
|
60
69
|
|
|
61
70
|
export declare namespace fromRpc {
|
|
62
71
|
/** Error type for `fromRpc`. */
|
|
63
72
|
export type ErrorType =
|
|
73
|
+
| Address.assert.ErrorType
|
|
64
74
|
| Hex.isEqual.ErrorType
|
|
65
75
|
| InvalidSimulationError
|
|
66
|
-
|
|
|
76
|
+
| AccountConfig.assert.ErrorType
|
|
67
77
|
| Rlp.fromHex.ErrorType
|
|
68
78
|
| Rlp.toHex.ErrorType
|
|
69
79
|
| Errors.GlobalErrorType
|
|
70
80
|
}
|
|
71
81
|
|
|
72
82
|
/**
|
|
73
|
-
* Converts
|
|
83
|
+
* Converts an account simulation spec to its JSON-RPC representation.
|
|
74
84
|
*
|
|
75
85
|
* @example
|
|
76
86
|
* ```ts twoslash
|
|
77
87
|
* // @noErrors
|
|
78
|
-
* import {
|
|
88
|
+
* import { AccountSimulation } from 'ox/tempo'
|
|
79
89
|
*
|
|
80
|
-
* const specRpc =
|
|
90
|
+
* const specRpc = AccountSimulation.toRpc(spec)
|
|
81
91
|
* ```
|
|
82
92
|
*
|
|
83
|
-
* @param spec -
|
|
84
|
-
* @returns The JSON-RPC
|
|
93
|
+
* @param spec - Account simulation spec.
|
|
94
|
+
* @returns The JSON-RPC account simulation spec with encoded configurations.
|
|
85
95
|
*/
|
|
86
96
|
export function toRpc(spec: Spec): Rpc {
|
|
87
|
-
const { approvals, config } = spec
|
|
97
|
+
const { approvals, config, signer } = spec
|
|
88
98
|
assertApprovals(approvals)
|
|
99
|
+
if (signer !== undefined) Address.assert(signer)
|
|
89
100
|
return {
|
|
90
101
|
approvals: approvals.map(({ keyData, keyType, owner }) => ({
|
|
91
102
|
...(keyData !== undefined ? { keyData: shimKeyData(keyData) } : {}),
|
|
@@ -93,15 +104,17 @@ export function toRpc(spec: Spec): Rpc {
|
|
|
93
104
|
owner,
|
|
94
105
|
})),
|
|
95
106
|
config: serializeConfig(config),
|
|
107
|
+
...(signer !== undefined ? { signer } : {}),
|
|
96
108
|
}
|
|
97
109
|
}
|
|
98
110
|
|
|
99
111
|
export declare namespace toRpc {
|
|
100
112
|
/** Error type for `toRpc`. */
|
|
101
113
|
export type ErrorType =
|
|
114
|
+
| Address.assert.ErrorType
|
|
102
115
|
| Hex.fromNumber.ErrorType
|
|
103
116
|
| InvalidSimulationError
|
|
104
|
-
|
|
|
117
|
+
| AccountConfig.assert.ErrorType
|
|
105
118
|
| Rlp.fromHex.ErrorType
|
|
106
119
|
| Errors.GlobalErrorType
|
|
107
120
|
}
|
|
@@ -120,14 +133,14 @@ function assertApprovals(approvals: readonly unknown[]) {
|
|
|
120
133
|
throw new InvalidSimulationError({
|
|
121
134
|
reason: 'only untagged primitive owner approvals are allowed',
|
|
122
135
|
})
|
|
123
|
-
if (approvals.length >
|
|
136
|
+
if (approvals.length > AccountConfig.maxSignatures)
|
|
124
137
|
throw new InvalidSimulationError({
|
|
125
|
-
reason: `approval count exceeds ${
|
|
138
|
+
reason: `approval count exceeds ${AccountConfig.maxSignatures}`,
|
|
126
139
|
})
|
|
127
140
|
}
|
|
128
141
|
|
|
129
142
|
/** @internal */
|
|
130
|
-
function deserializeConfig(config: Hex.Hex):
|
|
143
|
+
function deserializeConfig(config: Hex.Hex): AccountConfig.Config {
|
|
131
144
|
const tuple = Rlp.toHex(config)
|
|
132
145
|
if (!Array.isArray(tuple) || tuple.length !== 4)
|
|
133
146
|
throw new InvalidSimulationError({ reason: 'invalid config encoding' })
|
|
@@ -151,35 +164,34 @@ function deserializeConfig(config: Hex.Hex): MultisigConfig.Config {
|
|
|
151
164
|
)
|
|
152
165
|
)
|
|
153
166
|
throw new InvalidSimulationError({ reason: 'invalid config encoding' })
|
|
154
|
-
const value =
|
|
155
|
-
|
|
156
|
-
)
|
|
157
|
-
MultisigConfig.assert(value)
|
|
167
|
+
const value = AccountConfig.fromTuple(tuple as unknown as AccountConfig.Tuple)
|
|
168
|
+
AccountConfig.assert(value)
|
|
158
169
|
if (!Hex.isEqual(config, serializeConfig(value)))
|
|
159
170
|
throw new InvalidSimulationError({ reason: 'noncanonical config encoding' })
|
|
160
171
|
return value
|
|
161
172
|
}
|
|
162
173
|
|
|
163
174
|
/** @internal */
|
|
164
|
-
function serializeConfig(config:
|
|
165
|
-
return Rlp.fromHex(
|
|
175
|
+
function serializeConfig(config: AccountConfig.Input): Hex.Hex {
|
|
176
|
+
return Rlp.fromHex(AccountConfig.toTuple(config))
|
|
166
177
|
}
|
|
167
178
|
|
|
168
179
|
/**
|
|
169
|
-
* Shims
|
|
180
|
+
* Shims key data into the 1-, 2-, or 4-byte length hint accepted by Tempo's
|
|
181
|
+
* gas estimator. Other sizes are replaced by a 2-byte hint of their length.
|
|
170
182
|
* @internal
|
|
171
183
|
*/
|
|
172
184
|
function shimKeyData(data: Hex.Hex): Hex.Hex {
|
|
173
185
|
const size = Hex.size(data)
|
|
174
|
-
if (size
|
|
186
|
+
if (size === 1 || size === 2 || size === 4) return data
|
|
175
187
|
return Hex.fromNumber(size, { size: 2 })
|
|
176
188
|
}
|
|
177
189
|
|
|
178
|
-
/** Thrown when
|
|
190
|
+
/** Thrown when an account simulation spec is invalid. */
|
|
179
191
|
export class InvalidSimulationError extends Errors.BaseError {
|
|
180
|
-
override readonly name = '
|
|
192
|
+
override readonly name = 'AccountSimulation.InvalidSimulationError'
|
|
181
193
|
constructor(options: InvalidSimulationError.Options) {
|
|
182
|
-
super(`Invalid
|
|
194
|
+
super(`Invalid account simulation: ${options.reason}.`)
|
|
183
195
|
}
|
|
184
196
|
}
|
|
185
197
|
|
|
@@ -18,7 +18,7 @@ const signature = {
|
|
|
18
18
|
type: 'secp256k1',
|
|
19
19
|
} as const satisfies SignatureEnvelope.Secp256k1
|
|
20
20
|
|
|
21
|
-
const
|
|
21
|
+
const configurable = {
|
|
22
22
|
account: '0x2222222222222222222222222222222222222222',
|
|
23
23
|
config: {
|
|
24
24
|
salt: `0x${'00'.repeat(32)}`,
|
|
@@ -29,8 +29,8 @@ const multisig = {
|
|
|
29
29
|
],
|
|
30
30
|
},
|
|
31
31
|
signatures: [signature],
|
|
32
|
-
type: '
|
|
33
|
-
} as const satisfies SignatureEnvelope.
|
|
32
|
+
type: 'configurable',
|
|
33
|
+
} as const satisfies SignatureEnvelope.Configurable
|
|
34
34
|
|
|
35
35
|
test('accepts primitive signatures', () => {
|
|
36
36
|
const signed = KeyAuthorization.from(authorization, { signature })
|
|
@@ -40,10 +40,10 @@ test('accepts primitive signatures', () => {
|
|
|
40
40
|
>()
|
|
41
41
|
})
|
|
42
42
|
|
|
43
|
-
test('accepts
|
|
43
|
+
test('accepts configurable signatures and account-bound grants', () => {
|
|
44
44
|
const signed = KeyAuthorization.from(
|
|
45
|
-
{ ...authorization, account:
|
|
46
|
-
{ signature:
|
|
45
|
+
{ ...authorization, account: configurable.account, type: 'configurable' },
|
|
46
|
+
{ signature: configurable },
|
|
47
47
|
)
|
|
48
48
|
expectTypeOf(signed).toMatchTypeOf<KeyAuthorization.Signed>()
|
|
49
49
|
expectTypeOf(
|
|
@@ -51,37 +51,27 @@ test('accepts multisig signatures and account-bound grants', () => {
|
|
|
51
51
|
).toMatchTypeOf<KeyAuthorization.Rpc>()
|
|
52
52
|
})
|
|
53
53
|
|
|
54
|
-
test('
|
|
55
|
-
type
|
|
56
|
-
expectTypeOf<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
>().toEqualTypeOf<`0x${string}`>()
|
|
54
|
+
test('allows configurable grants without an account', () => {
|
|
55
|
+
type Configurable = Extract<KeyAuthorization.Input, { type: 'configurable' }>
|
|
56
|
+
expectTypeOf<Configurable['account']>().toEqualTypeOf<
|
|
57
|
+
TempoAddress.Address | undefined
|
|
58
|
+
>()
|
|
60
59
|
expectTypeOf<
|
|
61
|
-
|
|
62
|
-
>().
|
|
63
|
-
expectTypeOf<{
|
|
64
|
-
address: `0x${string}`
|
|
65
|
-
chainId: bigint
|
|
66
|
-
type: 'multisig'
|
|
67
|
-
}>().not.toExtend<KeyAuthorization.Input>()
|
|
60
|
+
Extract<KeyAuthorization.Signed, { type: 'configurable' }>['account']
|
|
61
|
+
>().toEqualTypeOf<`0x${string}` | undefined>()
|
|
68
62
|
expectTypeOf<{
|
|
69
|
-
account: undefined
|
|
70
63
|
address: `0x${string}`
|
|
71
64
|
chainId: bigint
|
|
72
|
-
type: '
|
|
73
|
-
}>().
|
|
65
|
+
type: 'configurable'
|
|
66
|
+
}>().toExtend<KeyAuthorization.Input>()
|
|
74
67
|
expectTypeOf<{
|
|
75
68
|
account: null
|
|
76
69
|
chainId: '0x1'
|
|
77
70
|
expiry: null
|
|
78
71
|
keyId: `0x${string}`
|
|
79
|
-
keyType: '
|
|
72
|
+
keyType: 'configurableAccount'
|
|
80
73
|
signature: KeyAuthorization.SignatureRpc
|
|
81
|
-
}>().
|
|
82
|
-
expectTypeOf<
|
|
83
|
-
Extract<KeyAuthorization.Rpc, { keyType: 'multisig' }>['account']
|
|
84
|
-
>().toEqualTypeOf<`0x${string}`>()
|
|
74
|
+
}>().toExtend<KeyAuthorization.Rpc>()
|
|
85
75
|
})
|
|
86
76
|
|
|
87
77
|
test('rejects keychain signatures', () => {
|
|
@@ -118,13 +108,13 @@ test('rejects keychain signatures', () => {
|
|
|
118
108
|
expectTypeOf(rpc).toMatchTypeOf<KeyAuthorization.Rpc>()
|
|
119
109
|
})
|
|
120
110
|
|
|
121
|
-
test('resolves Tempo address bindings for
|
|
111
|
+
test('resolves Tempo address bindings for configurable grants', () => {
|
|
122
112
|
const signed = KeyAuthorization.from(
|
|
123
113
|
{
|
|
124
114
|
account: TempoAddress.format(authorization.address),
|
|
125
115
|
address: TempoAddress.format(authorization.address),
|
|
126
116
|
chainId: 1n,
|
|
127
|
-
type: '
|
|
117
|
+
type: 'configurable',
|
|
128
118
|
},
|
|
129
119
|
{ signature },
|
|
130
120
|
)
|