ox 1.8.5 → 1.8.7
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 +37 -0
- package/dist/tempo/{MultisigConfig.d.ts → AccountConfig.d.ts} +116 -63
- package/dist/tempo/AccountConfig.d.ts.map +1 -0
- package/dist/tempo/{MultisigConfig.js → AccountConfig.js} +109 -55
- package/dist/tempo/AccountConfig.js.map +1 -0
- package/dist/tempo/{MultisigOperation.d.ts → AccountOperation.d.ts} +62 -62
- package/dist/tempo/AccountOperation.d.ts.map +1 -0
- package/dist/tempo/{MultisigOperation.js → AccountOperation.js} +64 -64
- package/dist/tempo/AccountOperation.js.map +1 -0
- package/dist/tempo/{MultisigSimulation.d.ts → AccountSimulation.d.ts} +21 -21
- package/dist/tempo/AccountSimulation.d.ts.map +1 -0
- package/dist/tempo/{MultisigSimulation.js → AccountSimulation.js} +20 -20
- package/dist/tempo/AccountSimulation.js.map +1 -0
- package/dist/tempo/KeyAuthorization.d.ts +37 -27
- package/dist/tempo/KeyAuthorization.d.ts.map +1 -1
- package/dist/tempo/KeyAuthorization.js +17 -19
- package/dist/tempo/KeyAuthorization.js.map +1 -1
- package/dist/tempo/RpcSchemaTempo.d.ts +13 -13
- package/dist/tempo/RpcSchemaTempo.d.ts.map +1 -1
- package/dist/tempo/SignatureEnvelope.d.ts +36 -33
- package/dist/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/dist/tempo/SignatureEnvelope.js +77 -77
- package/dist/tempo/SignatureEnvelope.js.map +1 -1
- package/dist/tempo/TokenRole.d.ts +4 -2
- package/dist/tempo/TokenRole.d.ts.map +1 -1
- package/dist/tempo/TokenRole.js +4 -1
- package/dist/tempo/TokenRole.js.map +1 -1
- package/dist/tempo/TransactionRequest.d.ts +11 -9
- package/dist/tempo/TransactionRequest.d.ts.map +1 -1
- package/dist/tempo/TransactionRequest.js +14 -10
- package/dist/tempo/TransactionRequest.js.map +1 -1
- package/dist/tempo/index.d.ts +56 -54
- package/dist/tempo/index.d.ts.map +1 -1
- package/dist/tempo/index.js +56 -54
- package/dist/tempo/index.js.map +1 -1
- package/dist/zod/tempo/{MultisigConfig.d.ts → AccountConfig.d.ts} +6 -6
- package/dist/zod/tempo/AccountConfig.d.ts.map +1 -0
- package/dist/zod/tempo/{MultisigConfig.js → AccountConfig.js} +12 -12
- package/dist/zod/tempo/AccountConfig.js.map +1 -0
- package/dist/zod/tempo/{MultisigOperation.d.ts → AccountOperation.d.ts} +5 -5
- package/dist/zod/tempo/AccountOperation.d.ts.map +1 -0
- package/dist/zod/tempo/{MultisigOperation.js → AccountOperation.js} +10 -10
- package/dist/zod/tempo/AccountOperation.js.map +1 -0
- package/dist/zod/tempo/{MultisigSimulation.d.ts → AccountSimulation.d.ts} +5 -5
- package/dist/zod/tempo/AccountSimulation.d.ts.map +1 -0
- package/dist/zod/tempo/AccountSimulation.js +44 -0
- package/dist/zod/tempo/AccountSimulation.js.map +1 -0
- package/dist/zod/tempo/AuthorizationTempo.d.ts +10 -10
- package/dist/zod/tempo/KeyAuthorization.d.ts +12 -12
- package/dist/zod/tempo/KeyAuthorization.js +6 -6
- package/dist/zod/tempo/KeyAuthorization.js.map +1 -1
- package/dist/zod/tempo/RpcSchemaTempo.d.ts +59 -59
- package/dist/zod/tempo/RpcSchemaTempo.d.ts.map +1 -1
- package/dist/zod/tempo/RpcSchemaTempo.js +28 -28
- package/dist/zod/tempo/RpcSchemaTempo.js.map +1 -1
- package/dist/zod/tempo/SignatureEnvelope.d.ts +7 -7
- package/dist/zod/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/dist/zod/tempo/SignatureEnvelope.js +22 -16
- package/dist/zod/tempo/SignatureEnvelope.js.map +1 -1
- package/dist/zod/tempo/TokenRole.d.ts +1 -1
- package/dist/zod/tempo/TokenRole.d.ts.map +1 -1
- package/dist/zod/tempo/Transaction.d.ts +24 -24
- package/dist/zod/tempo/TransactionRequest.d.ts +84 -84
- package/dist/zod/tempo/TransactionRequest.d.ts.map +1 -1
- package/dist/zod/tempo/TransactionRequest.js +26 -17
- package/dist/zod/tempo/TransactionRequest.js.map +1 -1
- package/dist/zod/tempo/TxEnvelopeTempo.d.ts +12 -12
- package/dist/zod/tempo/ZoneRpcAuthentication.d.ts +3 -3
- package/dist/zod/tempo/z.d.ts +3 -3
- package/dist/zod/tempo/z.d.ts.map +1 -1
- package/dist/zod/tempo/z.js +3 -3
- package/dist/zod/tempo/z.js.map +1 -1
- package/package.json +31 -31
- package/src/tempo/{MultisigConfig.test-d.ts → AccountConfig.test-d.ts} +22 -12
- package/src/tempo/{MultisigConfig.test.ts → AccountConfig.test.ts} +155 -37
- package/src/tempo/{MultisigConfig.ts → AccountConfig.ts} +138 -66
- package/src/tempo/AccountOperation.test-d.ts +79 -0
- package/src/tempo/{MultisigOperation.test.ts → AccountOperation.test.ts} +97 -97
- package/src/tempo/{MultisigOperation.ts → AccountOperation.ts} +95 -97
- package/src/tempo/{MultisigSimulation.test-d.ts → AccountSimulation.test-d.ts} +7 -9
- package/src/tempo/{MultisigSimulation.test.ts → AccountSimulation.test.ts} +28 -28
- package/src/tempo/{MultisigSimulation.ts → AccountSimulation.ts} +28 -30
- package/src/tempo/KeyAuthorization.test-d.ts +15 -6
- package/src/tempo/KeyAuthorization.test.ts +117 -37
- package/src/tempo/KeyAuthorization.ts +68 -59
- package/src/tempo/RpcSchemaTempo.test-d.ts +19 -19
- package/src/tempo/RpcSchemaTempo.ts +13 -13
- package/src/tempo/SignatureEnvelope.test-d.ts +7 -7
- package/src/tempo/SignatureEnvelope.test.ts +34 -34
- package/src/tempo/SignatureEnvelope.ts +112 -108
- package/src/tempo/TokenRole.ts +4 -1
- package/src/tempo/Transaction.test.ts +4 -4
- package/src/tempo/TransactionRequest.test-d.ts +17 -6
- package/src/tempo/TransactionRequest.test.ts +32 -17
- package/src/tempo/TransactionRequest.ts +27 -19
- package/src/tempo/{multisig.e2e.test.ts → configurableAccounts.e2e.test.ts} +16 -16
- package/src/tempo/e2e.test.ts +32 -20
- package/src/tempo/index.ts +56 -54
- package/src/version.ts +1 -1
- package/src/zod/tempo/{MultisigConfig.ts → AccountConfig.ts} +12 -12
- package/src/zod/tempo/{MultisigOperation.ts → AccountOperation.ts} +9 -9
- package/src/zod/tempo/AccountSimulation.ts +53 -0
- package/src/zod/tempo/KeyAuthorization.ts +8 -8
- package/src/zod/tempo/RpcSchemaTempo.ts +28 -28
- package/src/zod/tempo/SignatureEnvelope.ts +23 -17
- package/src/zod/tempo/TransactionRequest.ts +29 -18
- package/src/zod/tempo/_test/AccountConfig.test-d.ts +13 -0
- package/src/zod/tempo/_test/{MultisigConfig.test.ts → AccountConfig.test.ts} +7 -7
- package/src/zod/tempo/_test/AccountOperation.test-d.ts +27 -0
- package/src/zod/tempo/_test/{MultisigOperation.test.ts → AccountOperation.test.ts} +9 -9
- package/src/zod/tempo/_test/AccountSimulation.test-d.ts +13 -0
- package/src/zod/tempo/_test/{MultisigSimulation.test.ts → AccountSimulation.test.ts} +13 -13
- package/src/zod/tempo/_test/KeyAuthorization.test.ts +9 -9
- package/src/zod/tempo/_test/RpcSchemaTempo.test-d.ts +27 -27
- package/src/zod/tempo/_test/RpcSchemaTempo.test.ts +16 -18
- package/src/zod/tempo/_test/SignatureEnvelope.test-d.ts +5 -5
- package/src/zod/tempo/_test/SignatureEnvelope.test.ts +12 -9
- package/src/zod/tempo/_test/TransactionRequest.test.ts +28 -8
- package/src/zod/tempo/z.ts +3 -3
- package/dist/tempo/MultisigConfig.d.ts.map +0 -1
- package/dist/tempo/MultisigConfig.js.map +0 -1
- package/dist/tempo/MultisigOperation.d.ts.map +0 -1
- package/dist/tempo/MultisigOperation.js.map +0 -1
- package/dist/tempo/MultisigSimulation.d.ts.map +0 -1
- package/dist/tempo/MultisigSimulation.js.map +0 -1
- package/dist/zod/tempo/MultisigConfig.d.ts.map +0 -1
- package/dist/zod/tempo/MultisigConfig.js.map +0 -1
- package/dist/zod/tempo/MultisigOperation.d.ts.map +0 -1
- package/dist/zod/tempo/MultisigOperation.js.map +0 -1
- package/dist/zod/tempo/MultisigSimulation.d.ts.map +0 -1
- package/dist/zod/tempo/MultisigSimulation.js +0 -44
- package/dist/zod/tempo/MultisigSimulation.js.map +0 -1
- package/src/tempo/MultisigOperation.test-d.ts +0 -79
- package/src/zod/tempo/MultisigSimulation.ts +0 -53
- package/src/zod/tempo/_test/MultisigConfig.test-d.ts +0 -13
- package/src/zod/tempo/_test/MultisigOperation.test-d.ts +0 -27
- package/src/zod/tempo/_test/MultisigSimulation.test-d.ts +0 -13
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
WebAuthnP256,
|
|
9
9
|
} from 'ox'
|
|
10
10
|
import { describe, expect, test } from 'vp/test'
|
|
11
|
+
import * as AccountConfig from './AccountConfig.js'
|
|
11
12
|
import * as KeyAuthorization from './KeyAuthorization.js'
|
|
12
|
-
import * as MultisigConfig from './MultisigConfig.js'
|
|
13
13
|
import * as Period from './Period.js'
|
|
14
14
|
import * as SignatureEnvelope from './SignatureEnvelope.js'
|
|
15
15
|
|
|
@@ -17,6 +17,23 @@ const address = '0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c'
|
|
|
17
17
|
const expiry = 1234567890
|
|
18
18
|
const token = '0x20c0000000000000000000000000000000000001'
|
|
19
19
|
|
|
20
|
+
// Unsigned RLP and hashes produced by the Tempo node's `KeyAuthorization::encode`
|
|
21
|
+
// (`tempo-primitives`) for `address` on chain 1337.
|
|
22
|
+
const limitsVectors = {
|
|
23
|
+
denyAll: {
|
|
24
|
+
hash: '0x647445af52e13830d879f11656840959bf7cffd26c5858b6e79696ef051e1115',
|
|
25
|
+
rlp: '0xdb8205398094be95c3f554e9fc85ec51be69a3d807a0d55bcf2c80c0',
|
|
26
|
+
},
|
|
27
|
+
scopedDenyAll: {
|
|
28
|
+
hash: '0xed04735d65180756db1cac8134ee53ed77737803902572beff10d5da03eab2cf',
|
|
29
|
+
rlp: '0xf38205398094be95c3f554e9fc85ec51be69a3d807a0d55bcf2c80c0d7d69420c0000000000000000000000000000000000001c0',
|
|
30
|
+
},
|
|
31
|
+
scopedUnlimited: {
|
|
32
|
+
hash: '0x4c30b56b178f44172feee4a80a27222101e19b72de396be4d764e2f4054f32d7',
|
|
33
|
+
rlp: '0xf38205398094be95c3f554e9fc85ec51be69a3d807a0d55bcf2c8080d7d69420c0000000000000000000000000000000000001c0',
|
|
34
|
+
},
|
|
35
|
+
} as const
|
|
36
|
+
|
|
20
37
|
const privateKey_secp256k1 =
|
|
21
38
|
'0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
|
|
22
39
|
const signature_secp256k1 = Secp256k1.sign({
|
|
@@ -54,9 +71,9 @@ const signature_webauthn = SignatureEnvelope.from({
|
|
|
54
71
|
},
|
|
55
72
|
})
|
|
56
73
|
|
|
57
|
-
const
|
|
74
|
+
const signature_configurable = {
|
|
58
75
|
account: address,
|
|
59
|
-
config:
|
|
76
|
+
config: AccountConfig.from({
|
|
60
77
|
owners: [
|
|
61
78
|
{
|
|
62
79
|
owner: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
|
|
@@ -67,9 +84,9 @@ const signature_multisig = {
|
|
|
67
84
|
version: 1n,
|
|
68
85
|
}),
|
|
69
86
|
signatures: [SignatureEnvelope.from(signature_secp256k1)],
|
|
70
|
-
type: '
|
|
71
|
-
} as const satisfies SignatureEnvelope.
|
|
72
|
-
const
|
|
87
|
+
type: 'configurable',
|
|
88
|
+
} as const satisfies SignatureEnvelope.Configurable
|
|
89
|
+
const signature_configurable_rpc =
|
|
73
90
|
'0xf89794be95c3f554e9fc85ec51be69a3d807a0d55bcf2cf83ba000000000000000000000000000000000000000000000000000000000000000000101d7d694f39fd6e51aad88f6f4ce6ab8827279cfffb9226601f843b841fa78c5905fb0b9d6066ef531f962a62bc6ef0d5eb59ecb134056d206f75aaed7780926ff2601a935c2c79707d9e1799948c9f19dcdde1e090e903b19a07923d01c' as const
|
|
74
91
|
|
|
75
92
|
const signature_keychain = {
|
|
@@ -78,9 +95,13 @@ const signature_keychain = {
|
|
|
78
95
|
userAddress: address,
|
|
79
96
|
} as const satisfies SignatureEnvelope.Keychain
|
|
80
97
|
|
|
81
|
-
describe('
|
|
98
|
+
describe('configurable account binding', () => {
|
|
82
99
|
test('rejects unbound grants before signing or encoding', () => {
|
|
83
|
-
const authorization = {
|
|
100
|
+
const authorization = {
|
|
101
|
+
address,
|
|
102
|
+
chainId: 1n,
|
|
103
|
+
type: 'configurable',
|
|
104
|
+
} as const
|
|
84
105
|
const signed = {
|
|
85
106
|
...authorization,
|
|
86
107
|
signature: SignatureEnvelope.from(signature_secp256k1),
|
|
@@ -93,13 +114,13 @@ describe('multisig account binding', () => {
|
|
|
93
114
|
() => KeyAuthorization.toRpc(signed),
|
|
94
115
|
])
|
|
95
116
|
expect(encode).toThrowErrorMatchingInlineSnapshot(
|
|
96
|
-
`[KeyAuthorization.MissingAccountError:
|
|
117
|
+
`[KeyAuthorization.MissingAccountError: Configurable account key grants require a parent account binding.]`,
|
|
97
118
|
)
|
|
98
119
|
})
|
|
99
120
|
|
|
100
121
|
test('rejects unbound RPC and RLP grants', () => {
|
|
101
122
|
const signed = KeyAuthorization.from(
|
|
102
|
-
{ account: address, address, chainId: 1n, type: '
|
|
123
|
+
{ account: address, address, chainId: 1n, type: 'configurable' },
|
|
103
124
|
{ signature: signature_secp256k1 },
|
|
104
125
|
)
|
|
105
126
|
const rpc = KeyAuthorization.toRpc(signed)
|
|
@@ -118,15 +139,36 @@ describe('multisig account binding', () => {
|
|
|
118
139
|
})
|
|
119
140
|
|
|
120
141
|
describe('from', () => {
|
|
121
|
-
test('
|
|
142
|
+
test('behavior: limits encode like the Tempo node', () => {
|
|
143
|
+
const encode = (authorization: KeyAuthorization.KeyAuthorization) => ({
|
|
144
|
+
hash: KeyAuthorization.hash(authorization),
|
|
145
|
+
rlp: Rlp.fromHex(KeyAuthorization.toTuple(authorization)[0]),
|
|
146
|
+
})
|
|
147
|
+
const base = { address, chainId: 1337n, type: 'secp256k1' } as const
|
|
148
|
+
expect({
|
|
149
|
+
denyAll: encode(KeyAuthorization.from({ ...base, limits: [] })),
|
|
150
|
+
scopedDenyAll: encode(
|
|
151
|
+
KeyAuthorization.from({
|
|
152
|
+
...base,
|
|
153
|
+
limits: [],
|
|
154
|
+
scopes: [{ address: token }],
|
|
155
|
+
}),
|
|
156
|
+
),
|
|
157
|
+
scopedUnlimited: encode(
|
|
158
|
+
KeyAuthorization.from({ ...base, scopes: [{ address: token }] }),
|
|
159
|
+
),
|
|
160
|
+
}).toEqual(limitsVectors)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
test('accepts configurable grants and delegates', () => {
|
|
122
164
|
const signed = KeyAuthorization.from(
|
|
123
165
|
{
|
|
124
166
|
address,
|
|
125
167
|
chainId: 1n,
|
|
126
|
-
type: '
|
|
127
|
-
account:
|
|
168
|
+
type: 'configurable',
|
|
169
|
+
account: signature_configurable.account,
|
|
128
170
|
},
|
|
129
|
-
{ signature:
|
|
171
|
+
{ signature: signature_configurable },
|
|
130
172
|
)
|
|
131
173
|
expect(
|
|
132
174
|
KeyAuthorization.deserialize(KeyAuthorization.serialize(signed)),
|
|
@@ -501,7 +543,7 @@ describe('fromRpc', () => {
|
|
|
501
543
|
`)
|
|
502
544
|
})
|
|
503
545
|
|
|
504
|
-
test('with signature (
|
|
546
|
+
test('with signature (configurable)', () => {
|
|
505
547
|
const authorization = KeyAuthorization.from({
|
|
506
548
|
address,
|
|
507
549
|
chainId: 1n,
|
|
@@ -509,20 +551,20 @@ describe('fromRpc', () => {
|
|
|
509
551
|
})
|
|
510
552
|
|
|
511
553
|
const signed = KeyAuthorization.from(authorization, {
|
|
512
|
-
signature:
|
|
554
|
+
signature: signature_configurable,
|
|
513
555
|
})
|
|
514
|
-
expect(signed.signature).toEqual(
|
|
556
|
+
expect(signed.signature).toEqual(signature_configurable)
|
|
515
557
|
expect(
|
|
516
558
|
KeyAuthorization.from(authorization, {
|
|
517
|
-
signature: SignatureEnvelope.serialize(
|
|
559
|
+
signature: SignatureEnvelope.serialize(signature_configurable),
|
|
518
560
|
}).signature,
|
|
519
|
-
).toEqual(
|
|
561
|
+
).toEqual(signature_configurable)
|
|
520
562
|
expect(
|
|
521
563
|
KeyAuthorization.from({
|
|
522
564
|
...authorization,
|
|
523
|
-
signature:
|
|
565
|
+
signature: signature_configurable,
|
|
524
566
|
}).signature,
|
|
525
|
-
).toEqual(
|
|
567
|
+
).toEqual(signature_configurable)
|
|
526
568
|
expect(
|
|
527
569
|
KeyAuthorization.deserialize(KeyAuthorization.serialize(signed)),
|
|
528
570
|
).toEqual(signed)
|
|
@@ -540,7 +582,7 @@ describe('fromRpc', () => {
|
|
|
540
582
|
signature: signature_keychain as never,
|
|
541
583
|
}),
|
|
542
584
|
).toThrowErrorMatchingInlineSnapshot(
|
|
543
|
-
`[KeyAuthorization.InvalidSignatureTypeError: Signature type \`keychain\` is invalid for key authorizations; expected \`secp256k1\`, \`p256\`, \`webAuthn\`, or \`
|
|
585
|
+
`[KeyAuthorization.InvalidSignatureTypeError: Signature type \`keychain\` is invalid for key authorizations; expected \`secp256k1\`, \`p256\`, \`webAuthn\`, or \`configurable\`.]`,
|
|
544
586
|
)
|
|
545
587
|
|
|
546
588
|
expect(() =>
|
|
@@ -548,7 +590,7 @@ describe('fromRpc', () => {
|
|
|
548
590
|
signature: SignatureEnvelope.serialize(signature_keychain),
|
|
549
591
|
}),
|
|
550
592
|
).toThrowErrorMatchingInlineSnapshot(
|
|
551
|
-
`[KeyAuthorization.InvalidSignatureTypeError: Signature type \`keychain\` is invalid for key authorizations; expected \`secp256k1\`, \`p256\`, \`webAuthn\`, or \`
|
|
593
|
+
`[KeyAuthorization.InvalidSignatureTypeError: Signature type \`keychain\` is invalid for key authorizations; expected \`secp256k1\`, \`p256\`, \`webAuthn\`, or \`configurable\`.]`,
|
|
552
594
|
)
|
|
553
595
|
|
|
554
596
|
expect(() =>
|
|
@@ -557,19 +599,19 @@ describe('fromRpc', () => {
|
|
|
557
599
|
signature: signature_keychain,
|
|
558
600
|
} as never),
|
|
559
601
|
).toThrowErrorMatchingInlineSnapshot(
|
|
560
|
-
`[KeyAuthorization.InvalidSignatureTypeError: Signature type \`keychain\` is invalid for key authorizations; expected \`secp256k1\`, \`p256\`, \`webAuthn\`, or \`
|
|
602
|
+
`[KeyAuthorization.InvalidSignatureTypeError: Signature type \`keychain\` is invalid for key authorizations; expected \`secp256k1\`, \`p256\`, \`webAuthn\`, or \`configurable\`.]`,
|
|
561
603
|
)
|
|
562
604
|
})
|
|
563
605
|
})
|
|
564
606
|
|
|
565
607
|
describe('fromRpc', () => {
|
|
566
|
-
test('behavior:
|
|
608
|
+
test('behavior: configurable', () => {
|
|
567
609
|
const authorization = KeyAuthorization.fromRpc({
|
|
568
610
|
chainId: '0x1',
|
|
569
611
|
expiry: null,
|
|
570
612
|
keyId: address,
|
|
571
613
|
keyType: 'secp256k1',
|
|
572
|
-
signature:
|
|
614
|
+
signature: signature_configurable_rpc,
|
|
573
615
|
})
|
|
574
616
|
|
|
575
617
|
expect(authorization.signature).toMatchInlineSnapshot(`
|
|
@@ -596,7 +638,7 @@ describe('fromRpc', () => {
|
|
|
596
638
|
"type": "secp256k1",
|
|
597
639
|
},
|
|
598
640
|
],
|
|
599
|
-
"type": "
|
|
641
|
+
"type": "configurable",
|
|
600
642
|
}
|
|
601
643
|
`)
|
|
602
644
|
})
|
|
@@ -611,7 +653,7 @@ describe('fromRpc', () => {
|
|
|
611
653
|
signature: SignatureEnvelope.toRpc(signature_keychain),
|
|
612
654
|
} as never),
|
|
613
655
|
).toThrowErrorMatchingInlineSnapshot(
|
|
614
|
-
`[KeyAuthorization.InvalidSignatureTypeError: Signature type \`keychain\` is invalid for key authorizations; expected \`secp256k1\`, \`p256\`, \`webAuthn\`, or \`
|
|
656
|
+
`[KeyAuthorization.InvalidSignatureTypeError: Signature type \`keychain\` is invalid for key authorizations; expected \`secp256k1\`, \`p256\`, \`webAuthn\`, or \`configurable\`.]`,
|
|
615
657
|
)
|
|
616
658
|
})
|
|
617
659
|
|
|
@@ -832,6 +874,22 @@ describe('fromRpc', () => {
|
|
|
832
874
|
})
|
|
833
875
|
|
|
834
876
|
describe('fromTuple', () => {
|
|
877
|
+
test('behavior: keeps absent and empty limits distinct', () => {
|
|
878
|
+
const decoded = Object.fromEntries(
|
|
879
|
+
Object.entries(limitsVectors).map(([name, { rlp }]) => [
|
|
880
|
+
name,
|
|
881
|
+
KeyAuthorization.fromTuple([Rlp.toHex(rlp) as never]).limits,
|
|
882
|
+
]),
|
|
883
|
+
)
|
|
884
|
+
expect(decoded).toMatchInlineSnapshot(`
|
|
885
|
+
{
|
|
886
|
+
"denyAll": [],
|
|
887
|
+
"scopedDenyAll": [],
|
|
888
|
+
"scopedUnlimited": undefined,
|
|
889
|
+
}
|
|
890
|
+
`)
|
|
891
|
+
})
|
|
892
|
+
|
|
835
893
|
test('default', () => {
|
|
836
894
|
const authorization = KeyAuthorization.fromTuple([
|
|
837
895
|
[
|
|
@@ -1169,7 +1227,7 @@ describe('getSignPayload', () => {
|
|
|
1169
1227
|
})
|
|
1170
1228
|
|
|
1171
1229
|
describe('deserialize', () => {
|
|
1172
|
-
test('example: matches the frozen
|
|
1230
|
+
test('example: matches the frozen configurable witness vector', () => {
|
|
1173
1231
|
const serialized =
|
|
1174
1232
|
'0xf8f1f85382107980941eff47bc3a10a45d4b230b5d10e37751fe6aa718808080a053535353535353535353535353535353535353535353535353535353535353538094c4a590afa7337e5cd5eb3aa60cacf91c5400044bb89a05f89794c4a590afa7337e5cd5eb3aa60cacf91c5400044bf83ba000000000000000000000000000000000000000000000000000000000000000008001d7d6947e5f4552091a69125d5dfcb7b8c2659029395bdf01f843b8412cfed9350faf80e4115e3c4c967356b80a8e6ee42e4a49ab953c8c8a3537d8d8359bf035a9bea18f32b0da7129cdce3ce701abc09ad8919b93da21a0d57e21451b' as const
|
|
1175
1233
|
const authorization = KeyAuthorization.deserialize(serialized)
|
|
@@ -1202,7 +1260,7 @@ describe('deserialize', () => {
|
|
|
1202
1260
|
"type": "secp256k1",
|
|
1203
1261
|
},
|
|
1204
1262
|
],
|
|
1205
|
-
"type": "
|
|
1263
|
+
"type": "configurable",
|
|
1206
1264
|
},
|
|
1207
1265
|
"type": "secp256k1",
|
|
1208
1266
|
"witness": "0x5353535353535353535353535353535353535353535353535353535353535353",
|
|
@@ -1211,14 +1269,14 @@ describe('deserialize', () => {
|
|
|
1211
1269
|
expect(KeyAuthorization.serialize(authorization)).toBe(serialized)
|
|
1212
1270
|
})
|
|
1213
1271
|
|
|
1214
|
-
test('
|
|
1272
|
+
test('configurable', () => {
|
|
1215
1273
|
const serialized = Rlp.fromHex([
|
|
1216
1274
|
['0x1', '0x', address],
|
|
1217
|
-
SignatureEnvelope.serialize(
|
|
1275
|
+
SignatureEnvelope.serialize(signature_configurable),
|
|
1218
1276
|
])
|
|
1219
1277
|
|
|
1220
1278
|
expect(KeyAuthorization.deserialize(serialized).signature).toEqual(
|
|
1221
|
-
|
|
1279
|
+
signature_configurable,
|
|
1222
1280
|
)
|
|
1223
1281
|
})
|
|
1224
1282
|
|
|
@@ -1392,16 +1450,28 @@ describe('serialize', () => {
|
|
|
1392
1450
|
})
|
|
1393
1451
|
|
|
1394
1452
|
describe('toRpc', () => {
|
|
1395
|
-
test('behavior: multisig', () => {
|
|
1453
|
+
test('behavior: configurable key type uses the RPC multisig key type', () => {
|
|
1454
|
+
const authorization = KeyAuthorization.from(
|
|
1455
|
+
{ account: address, address, chainId: 1n, type: 'configurable' },
|
|
1456
|
+
{ signature: signature_secp256k1 },
|
|
1457
|
+
)
|
|
1458
|
+
const rpc = KeyAuthorization.toRpc(authorization)
|
|
1459
|
+
expect(rpc.keyType).toMatchInlineSnapshot(`"multisig"`)
|
|
1460
|
+
expect(KeyAuthorization.fromRpc(rpc).type).toMatchInlineSnapshot(
|
|
1461
|
+
`"configurable"`,
|
|
1462
|
+
)
|
|
1463
|
+
})
|
|
1464
|
+
|
|
1465
|
+
test('behavior: configurable', () => {
|
|
1396
1466
|
const authorization = KeyAuthorization.toRpc({
|
|
1397
1467
|
address,
|
|
1398
1468
|
chainId: 1n,
|
|
1399
|
-
signature:
|
|
1469
|
+
signature: signature_configurable,
|
|
1400
1470
|
type: 'secp256k1',
|
|
1401
1471
|
})
|
|
1402
1472
|
|
|
1403
1473
|
expect(authorization.signature).toMatchInlineSnapshot(
|
|
1404
|
-
`"${
|
|
1474
|
+
`"${signature_configurable_rpc}"`,
|
|
1405
1475
|
)
|
|
1406
1476
|
})
|
|
1407
1477
|
|
|
@@ -1662,6 +1732,16 @@ describe('toRpc', () => {
|
|
|
1662
1732
|
})
|
|
1663
1733
|
|
|
1664
1734
|
describe('toTuple', () => {
|
|
1735
|
+
test('behavior: round-trips Tempo node limits encoding', () => {
|
|
1736
|
+
for (const { hash, rlp } of Object.values(limitsVectors)) {
|
|
1737
|
+
const authorization = KeyAuthorization.fromTuple([
|
|
1738
|
+
Rlp.toHex(rlp) as never,
|
|
1739
|
+
])
|
|
1740
|
+
expect(Rlp.fromHex(KeyAuthorization.toTuple(authorization)[0])).toBe(rlp)
|
|
1741
|
+
expect(KeyAuthorization.hash(authorization)).toBe(hash)
|
|
1742
|
+
}
|
|
1743
|
+
})
|
|
1744
|
+
|
|
1665
1745
|
test('default', () => {
|
|
1666
1746
|
const authorization = KeyAuthorization.from({
|
|
1667
1747
|
address,
|
|
@@ -2074,7 +2154,7 @@ describe('toTuple', () => {
|
|
|
2074
2154
|
"0x",
|
|
2075
2155
|
"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c",
|
|
2076
2156
|
"0x",
|
|
2077
|
-
|
|
2157
|
+
"0x",
|
|
2078
2158
|
[
|
|
2079
2159
|
[
|
|
2080
2160
|
"0x1234567890123456789012345678901234567890",
|
|
@@ -29,7 +29,7 @@ import * as SignatureEnvelope from './SignatureEnvelope.js'
|
|
|
29
29
|
* - `chainId`: Chain ID for replay protection (0 = valid on any chain)
|
|
30
30
|
* - `expiry`: Unix timestamp when the key expires (undefined = never expires)
|
|
31
31
|
* - `limits`: Per-TIP-20 token spending limits (only applies to `transfer()` and `approve()` calls)
|
|
32
|
-
* - `type`: Key type (`secp256k1`, `p256`, `webAuthn`, or `
|
|
32
|
+
* - `type`: Key type (`secp256k1`, `p256`, `webAuthn`, or `configurable`)
|
|
33
33
|
*
|
|
34
34
|
* [Access Keys Specification](https://docs.tempo.xyz/protocol/transactions/spec-tempo-transaction#access-keys)
|
|
35
35
|
*/
|
|
@@ -38,7 +38,7 @@ export type KeyAuthorization<
|
|
|
38
38
|
bigintType = bigint,
|
|
39
39
|
numberType = number,
|
|
40
40
|
> = {
|
|
41
|
-
/** Account address this authorization is bound to. Required for
|
|
41
|
+
/** Account address this authorization is bound to. Required for configurable account grants. */
|
|
42
42
|
account?: Address.Address | undefined
|
|
43
43
|
/** Address derived from the public key of the key type. */
|
|
44
44
|
address: Address.Address
|
|
@@ -48,7 +48,13 @@ export type KeyAuthorization<
|
|
|
48
48
|
expiry?: numberType | null | undefined
|
|
49
49
|
/** Whether this authorization provisions an admin access key. */
|
|
50
50
|
isAdmin?: boolean | undefined
|
|
51
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* TIP20 spending limits for this key.
|
|
53
|
+
*
|
|
54
|
+
* - `undefined` = unlimited spending
|
|
55
|
+
* - `[]` = no spending allowed
|
|
56
|
+
* - `[...]` = only listed token limits allowed
|
|
57
|
+
*/
|
|
52
58
|
limits?: readonly TokenLimit<bigintType, numberType>[] | undefined
|
|
53
59
|
/**
|
|
54
60
|
* Call scopes restricting which contracts/selectors this key can call.
|
|
@@ -58,8 +64,8 @@ export type KeyAuthorization<
|
|
|
58
64
|
* - `[...]` = only listed contract+selector combinations allowed
|
|
59
65
|
*/
|
|
60
66
|
scopes?: readonly Scope[] | undefined
|
|
61
|
-
/** Key type (secp256k1, P256, WebAuthn, or
|
|
62
|
-
type: SignatureEnvelope.Type | '
|
|
67
|
+
/** Key type (secp256k1, P256, WebAuthn, or configurable account). */
|
|
68
|
+
type: SignatureEnvelope.Type | 'configurable'
|
|
63
69
|
/**
|
|
64
70
|
* Optional 32-byte witness bound into the signing hash.
|
|
65
71
|
*
|
|
@@ -74,23 +80,23 @@ export type KeyAuthorization<
|
|
|
74
80
|
? {
|
|
75
81
|
signature:
|
|
76
82
|
| SignatureEnvelope.Primitive<numberType>
|
|
77
|
-
| SignatureEnvelope.
|
|
83
|
+
| SignatureEnvelope.Configurable<numberType>
|
|
78
84
|
}
|
|
79
85
|
: {
|
|
80
86
|
signature?:
|
|
81
87
|
| SignatureEnvelope.Primitive<numberType>
|
|
82
|
-
| SignatureEnvelope.
|
|
88
|
+
| SignatureEnvelope.Configurable<numberType>
|
|
83
89
|
| undefined
|
|
84
90
|
})
|
|
85
91
|
|
|
86
92
|
/** Signature that can authorize an access key. */
|
|
87
93
|
export type Signature<numberType = number> =
|
|
88
94
|
| SignatureEnvelope.Primitive<numberType>
|
|
89
|
-
| SignatureEnvelope.
|
|
95
|
+
| SignatureEnvelope.Configurable<numberType>
|
|
90
96
|
|
|
91
97
|
/** RPC-formatted signature that can authorize an access key. */
|
|
92
98
|
export type SignatureRpc =
|
|
93
|
-
| SignatureEnvelope.
|
|
99
|
+
| SignatureEnvelope.ConfigurableRpc
|
|
94
100
|
| SignatureEnvelope.PrimitiveRpc
|
|
95
101
|
|
|
96
102
|
/** Input type for a Key Authorization. */
|
|
@@ -110,12 +116,12 @@ export type Rpc = {
|
|
|
110
116
|
isAdmin?: boolean | null | undefined
|
|
111
117
|
/** Key identifier. */
|
|
112
118
|
keyId: Address.Address
|
|
113
|
-
/** Key type. */
|
|
119
|
+
/** Key type. Configurable accounts use the node's `multisig` key type. */
|
|
114
120
|
keyType: SignatureEnvelope.Type | 'multisig'
|
|
115
|
-
/** Token spending limits. */
|
|
121
|
+
/** Token spending limits (`null`/`undefined` = unlimited, `[]` = no spending allowed). */
|
|
116
122
|
limits?: readonly RpcTokenLimit[] | null | undefined
|
|
117
|
-
/** Primitive or
|
|
118
|
-
signature: SignatureEnvelope.PrimitiveRpc | SignatureEnvelope.
|
|
123
|
+
/** Primitive or configurable account signature authorizing this key. */
|
|
124
|
+
signature: SignatureEnvelope.PrimitiveRpc | SignatureEnvelope.ConfigurableRpc
|
|
119
125
|
/** Optional 32-byte witness (hex). */
|
|
120
126
|
witness?: Hex.Hex | null | undefined
|
|
121
127
|
}
|
|
@@ -147,9 +153,9 @@ export type Signed<bigintType = bigint, numberType = number> = KeyAuthorization<
|
|
|
147
153
|
>
|
|
148
154
|
|
|
149
155
|
type SignatureValue =
|
|
150
|
-
| SignatureEnvelope.from.
|
|
156
|
+
| SignatureEnvelope.from.ConfigurableFromConfig
|
|
151
157
|
| UnionPartialBy<SignatureEnvelope.Primitive, 'prehash' | 'type'>
|
|
152
|
-
| PartialBy<SignatureEnvelope.
|
|
158
|
+
| PartialBy<SignatureEnvelope.Configurable, 'type'>
|
|
153
159
|
| SignatureEnvelope.Secp256k1Flat
|
|
154
160
|
| SignatureEnvelope.Serialized
|
|
155
161
|
|
|
@@ -173,36 +179,42 @@ type CallScopeTuple = readonly [
|
|
|
173
179
|
selectorRules: readonly SelectorRuleTuple[],
|
|
174
180
|
]
|
|
175
181
|
|
|
182
|
+
/** Spending limits slot; `'0x'` (RLP null) when skipped before a later field. */
|
|
183
|
+
type LimitsTuple = readonly TokenLimitTuple[] | '0x'
|
|
184
|
+
|
|
185
|
+
/** Call scopes slot; `'0x'` (RLP null) when skipped before a later field. */
|
|
186
|
+
type CallsTuple = readonly CallScopeTuple[] | '0x'
|
|
187
|
+
|
|
176
188
|
type AuthorizationTuple =
|
|
177
189
|
| BaseTuple
|
|
178
190
|
| readonly [...BaseTuple, expiry: Hex.Hex]
|
|
179
|
-
| readonly [...BaseTuple, expiry: Hex.Hex, limits:
|
|
191
|
+
| readonly [...BaseTuple, expiry: Hex.Hex, limits: LimitsTuple]
|
|
180
192
|
| readonly [
|
|
181
193
|
...BaseTuple,
|
|
182
194
|
expiry: Hex.Hex,
|
|
183
|
-
limits:
|
|
184
|
-
calls:
|
|
195
|
+
limits: LimitsTuple,
|
|
196
|
+
calls: CallsTuple,
|
|
185
197
|
]
|
|
186
198
|
| readonly [
|
|
187
199
|
...BaseTuple,
|
|
188
200
|
expiry: Hex.Hex,
|
|
189
|
-
limits:
|
|
190
|
-
calls:
|
|
201
|
+
limits: LimitsTuple,
|
|
202
|
+
calls: CallsTuple,
|
|
191
203
|
witness: Hex.Hex,
|
|
192
204
|
]
|
|
193
205
|
| readonly [
|
|
194
206
|
...BaseTuple,
|
|
195
207
|
expiry: Hex.Hex,
|
|
196
|
-
limits:
|
|
197
|
-
calls:
|
|
208
|
+
limits: LimitsTuple,
|
|
209
|
+
calls: CallsTuple,
|
|
198
210
|
witness: Hex.Hex,
|
|
199
211
|
isAdmin: Hex.Hex,
|
|
200
212
|
]
|
|
201
213
|
| readonly [
|
|
202
214
|
...BaseTuple,
|
|
203
215
|
expiry: Hex.Hex,
|
|
204
|
-
limits:
|
|
205
|
-
calls:
|
|
216
|
+
limits: LimitsTuple,
|
|
217
|
+
calls: CallsTuple,
|
|
206
218
|
witness: Hex.Hex,
|
|
207
219
|
isAdmin: Hex.Hex,
|
|
208
220
|
account: Address.Address,
|
|
@@ -472,11 +484,11 @@ export declare namespace from {
|
|
|
472
484
|
type Options<
|
|
473
485
|
signature extends SignatureValue | undefined = SignatureValue | undefined,
|
|
474
486
|
> = {
|
|
475
|
-
/** The primitive or
|
|
487
|
+
/** The primitive or configurable account signature to attach to the Key Authorization. */
|
|
476
488
|
signature?:
|
|
477
489
|
| signature
|
|
478
490
|
| SignatureEnvelope.Primitive
|
|
479
|
-
| SignatureEnvelope.
|
|
491
|
+
| SignatureEnvelope.Configurable
|
|
480
492
|
| undefined
|
|
481
493
|
}
|
|
482
494
|
|
|
@@ -491,7 +503,7 @@ export declare namespace from {
|
|
|
491
503
|
? {
|
|
492
504
|
signature: Extract<
|
|
493
505
|
SignatureEnvelope.from.ReturnValue<signature>,
|
|
494
|
-
SignatureEnvelope.Primitive | SignatureEnvelope.
|
|
506
|
+
SignatureEnvelope.Primitive | SignatureEnvelope.Configurable
|
|
495
507
|
>
|
|
496
508
|
}
|
|
497
509
|
: {})
|
|
@@ -539,7 +551,8 @@ export function fromRpc(authorization: Rpc): Signed {
|
|
|
539
551
|
const witness = authorization.witness ?? undefined
|
|
540
552
|
const isAdmin = authorization.isAdmin ?? undefined
|
|
541
553
|
const account = authorization.account ?? undefined
|
|
542
|
-
|
|
554
|
+
const type = keyType === 'multisig' ? 'configurable' : keyType
|
|
555
|
+
assertAccountBinding(type, account)
|
|
543
556
|
const signature = SignatureEnvelope.fromRpc(authorization.signature)
|
|
544
557
|
assertSignature(signature)
|
|
545
558
|
if (witness !== undefined) assertWitness(witness)
|
|
@@ -574,7 +587,7 @@ export function fromRpc(authorization: Rpc): Signed {
|
|
|
574
587
|
})),
|
|
575
588
|
...(scopes ? { scopes } : {}),
|
|
576
589
|
signature,
|
|
577
|
-
type
|
|
590
|
+
type,
|
|
578
591
|
...(witness !== undefined ? { witness } : {}),
|
|
579
592
|
...(account !== undefined ? { account } : {}),
|
|
580
593
|
...(isAdmin ? { isAdmin: true as const } : {}),
|
|
@@ -658,7 +671,7 @@ export function fromTuple<const tuple extends Tuple>(
|
|
|
658
671
|
case '0x02':
|
|
659
672
|
return 'webAuthn'
|
|
660
673
|
case '0x03':
|
|
661
|
-
return '
|
|
674
|
+
return 'configurable'
|
|
662
675
|
default:
|
|
663
676
|
throw new Error(`Invalid key type: ${keyType_hex}`)
|
|
664
677
|
}
|
|
@@ -671,17 +684,18 @@ export function fromTuple<const tuple extends Tuple>(
|
|
|
671
684
|
const expiry = isAbsent(rawExpiry)
|
|
672
685
|
? undefined
|
|
673
686
|
: hexToNumber(rawExpiry as Hex.Hex) || undefined
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
|
|
687
|
+
// An empty list (`0xc0`) is an explicit deny-all, distinct from an absent
|
|
688
|
+
// field (`0x80` or omitted), which leaves spending unlimited.
|
|
689
|
+
const limits = Array.isArray(rawLimits)
|
|
690
|
+
? rawLimits.map((limitTuple: any) => {
|
|
691
|
+
const [token, limit, period] = limitTuple
|
|
692
|
+
return {
|
|
693
|
+
token,
|
|
694
|
+
limit: hexToBigint(limit),
|
|
695
|
+
...(period !== undefined ? { period: hexToNumber(period) } : {}),
|
|
696
|
+
}
|
|
697
|
+
})
|
|
698
|
+
: undefined
|
|
685
699
|
const scopes = Array.isArray(rawScopes)
|
|
686
700
|
? rawScopes.flatMap((scopeTuple: any) => {
|
|
687
701
|
const [address, selectorRules] = scopeTuple
|
|
@@ -994,7 +1008,7 @@ export function toRpc(authorization: toRpc.Input): Rpc {
|
|
|
994
1008
|
chainId: chainIdHex === '0x0' ? '0x' : chainIdHex,
|
|
995
1009
|
expiry: expiry != null ? Quantity.fromNumberish(expiry) : null,
|
|
996
1010
|
keyId: address,
|
|
997
|
-
keyType: type,
|
|
1011
|
+
keyType: type === 'configurable' ? 'multisig' : type,
|
|
998
1012
|
limits: limits?.map(({ token, limit, period }) => ({
|
|
999
1013
|
token,
|
|
1000
1014
|
limit: Quantity.fromNumberish(limit),
|
|
@@ -1002,7 +1016,7 @@ export function toRpc(authorization: toRpc.Input): Rpc {
|
|
|
1002
1016
|
})),
|
|
1003
1017
|
signature: SignatureEnvelope.toRpc(signature) as
|
|
1004
1018
|
| SignatureEnvelope.PrimitiveRpc
|
|
1005
|
-
| SignatureEnvelope.
|
|
1019
|
+
| SignatureEnvelope.ConfigurableRpc,
|
|
1006
1020
|
...(allowedCalls ? { allowedCalls } : {}),
|
|
1007
1021
|
...(witness !== undefined ? { witness } : {}),
|
|
1008
1022
|
...(isAdmin ? { isAdmin: true } : {}),
|
|
@@ -1081,7 +1095,7 @@ export function toTuple<const authorization extends KeyAuthorization>(
|
|
|
1081
1095
|
return '0x01'
|
|
1082
1096
|
case 'webAuthn':
|
|
1083
1097
|
return '0x02'
|
|
1084
|
-
case '
|
|
1098
|
+
case 'configurable':
|
|
1085
1099
|
return '0x03'
|
|
1086
1100
|
default:
|
|
1087
1101
|
throw new Error(`Invalid key type: ${authorization.type}`)
|
|
@@ -1121,18 +1135,12 @@ export function toTuple<const authorization extends KeyAuthorization>(
|
|
|
1121
1135
|
// Optional trailing fields in wire order. Each entry's `placeholder` is
|
|
1122
1136
|
// emitted when this field is skipped but a later field is present.
|
|
1123
1137
|
//
|
|
1124
|
-
//
|
|
1125
|
-
//
|
|
1126
|
-
//
|
|
1127
|
-
// - `limits` keeps `[]` as its skipped placeholder for pre-TIP-1053 wire
|
|
1128
|
-
// shapes — preserving byte-for-byte equivalence with signed payloads
|
|
1129
|
-
// produced before TIP-1053 was added. When any TIP-1053+ field is
|
|
1130
|
-
// present, the canonical `'0x'` placeholder is used instead.
|
|
1138
|
+
// `'0x'` (RLP null) is the canonical placeholder: the node decodes it as
|
|
1139
|
+
// `None` (unrestricted). An empty list would decode as `Some([])`, so a
|
|
1140
|
+
// skipped `limits` must never use `[]` (that reads as deny-all spending).
|
|
1131
1141
|
//
|
|
1132
1142
|
// To add a new optional trailing field (e.g. from a future TIP): append a
|
|
1133
1143
|
// single entry to this list with `placeholder: '0x'`.
|
|
1134
|
-
const hasTip1053Plus =
|
|
1135
|
-
witness !== undefined || isAdmin || account !== undefined
|
|
1136
1144
|
const optionals: readonly { placeholder: unknown; value: unknown }[] = [
|
|
1137
1145
|
{
|
|
1138
1146
|
value:
|
|
@@ -1143,7 +1151,7 @@ export function toTuple<const authorization extends KeyAuthorization>(
|
|
|
1143
1151
|
},
|
|
1144
1152
|
{
|
|
1145
1153
|
value: limitsValue,
|
|
1146
|
-
placeholder:
|
|
1154
|
+
placeholder: '0x',
|
|
1147
1155
|
},
|
|
1148
1156
|
{ value: callsValue, placeholder: '0x' },
|
|
1149
1157
|
{ value: witness, placeholder: '0x' },
|
|
@@ -1211,7 +1219,8 @@ function assertAccountBinding(
|
|
|
1211
1219
|
type: KeyAuthorization['type'],
|
|
1212
1220
|
account: Address.Address | null | undefined,
|
|
1213
1221
|
): void {
|
|
1214
|
-
if (type === '
|
|
1222
|
+
if (type === 'configurable' && account == null)
|
|
1223
|
+
throw new MissingAccountError()
|
|
1215
1224
|
}
|
|
1216
1225
|
|
|
1217
1226
|
function assertWitness(witness: Hex.Hex): void {
|
|
@@ -1222,7 +1231,7 @@ function assertSignature<numberType>(
|
|
|
1222
1231
|
signature: SignatureEnvelope.SignatureEnvelope<numberType>,
|
|
1223
1232
|
): asserts signature is
|
|
1224
1233
|
| SignatureEnvelope.Primitive<numberType>
|
|
1225
|
-
| SignatureEnvelope.
|
|
1234
|
+
| SignatureEnvelope.Configurable<numberType> {
|
|
1226
1235
|
if (signature.type === 'keychain')
|
|
1227
1236
|
throw new InvalidSignatureTypeError(signature.type)
|
|
1228
1237
|
}
|
|
@@ -1256,15 +1265,15 @@ export class InvalidSignatureTypeError extends Error {
|
|
|
1256
1265
|
override readonly name = 'KeyAuthorization.InvalidSignatureTypeError'
|
|
1257
1266
|
constructor(type: SignatureEnvelope.SignatureEnvelope['type']) {
|
|
1258
1267
|
super(
|
|
1259
|
-
`Signature type \`${type}\` is invalid for key authorizations; expected \`secp256k1\`, \`p256\`, \`webAuthn\`, or \`
|
|
1268
|
+
`Signature type \`${type}\` is invalid for key authorizations; expected \`secp256k1\`, \`p256\`, \`webAuthn\`, or \`configurable\`.`,
|
|
1260
1269
|
)
|
|
1261
1270
|
}
|
|
1262
1271
|
}
|
|
1263
1272
|
|
|
1264
|
-
/** Thrown when a
|
|
1273
|
+
/** Thrown when a configurable account key grant omits its parent account binding. */
|
|
1265
1274
|
export class MissingAccountError extends Error {
|
|
1266
1275
|
override readonly name = 'KeyAuthorization.MissingAccountError'
|
|
1267
1276
|
constructor() {
|
|
1268
|
-
super('
|
|
1277
|
+
super('Configurable account key grants require a parent account binding.')
|
|
1269
1278
|
}
|
|
1270
1279
|
}
|