ox 0.14.44 → 0.14.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/Frame/package.json +6 -0
- package/FrameReceipt/package.json +6 -0
- package/FrameSignature/package.json +6 -0
- package/TxEnvelopeEip8141/package.json +6 -0
- package/_cjs/core/Frame.js +147 -0
- package/_cjs/core/Frame.js.map +1 -0
- package/_cjs/core/FrameReceipt.js +34 -0
- package/_cjs/core/FrameReceipt.js.map +1 -0
- package/_cjs/core/FrameSignature.js +203 -0
- package/_cjs/core/FrameSignature.js.map +1 -0
- package/_cjs/core/Transaction.js +18 -2
- package/_cjs/core/Transaction.js.map +1 -1
- package/_cjs/core/TransactionReceipt.js +10 -0
- package/_cjs/core/TransactionReceipt.js.map +1 -1
- package/_cjs/core/TransactionRequest.js +11 -1
- package/_cjs/core/TransactionRequest.js.map +1 -1
- package/_cjs/core/TxEnvelopeEip8141.js +283 -0
- package/_cjs/core/TxEnvelopeEip8141.js.map +1 -0
- package/_cjs/core/internal/curves.js +6 -0
- package/_cjs/core/internal/curves.js.map +1 -0
- package/_cjs/core/internal/quantity.js +10 -0
- package/_cjs/core/internal/quantity.js.map +1 -0
- package/_cjs/erc4337/UserOperationReceipt.js.map +1 -1
- package/_cjs/index.js +6 -2
- package/_cjs/index.js.map +1 -1
- package/_cjs/tempo/KeyAuthorization.js +43 -10
- package/_cjs/tempo/KeyAuthorization.js.map +1 -1
- package/_cjs/tempo/MultisigConfig.js +33 -11
- package/_cjs/tempo/MultisigConfig.js.map +1 -1
- package/_cjs/tempo/MultisigOperation.js +18 -94
- package/_cjs/tempo/MultisigOperation.js.map +1 -1
- package/_cjs/tempo/MultisigSimulation.js +18 -46
- package/_cjs/tempo/MultisigSimulation.js.map +1 -1
- package/_cjs/tempo/SignatureEnvelope.js +72 -109
- package/_cjs/tempo/SignatureEnvelope.js.map +1 -1
- package/_cjs/tempo/TransactionRequest.js +5 -1
- package/_cjs/tempo/TransactionRequest.js.map +1 -1
- package/_cjs/tempo/index.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/core/Frame.js +311 -0
- package/_esm/core/Frame.js.map +1 -0
- package/_esm/core/FrameReceipt.js +72 -0
- package/_esm/core/FrameReceipt.js.map +1 -0
- package/_esm/core/FrameSignature.js +422 -0
- package/_esm/core/FrameSignature.js.map +1 -0
- package/_esm/core/Transaction.js +18 -2
- package/_esm/core/Transaction.js.map +1 -1
- package/_esm/core/TransactionReceipt.js +10 -0
- package/_esm/core/TransactionReceipt.js.map +1 -1
- package/_esm/core/TransactionRequest.js +11 -1
- package/_esm/core/TransactionRequest.js.map +1 -1
- package/_esm/core/TxEnvelopeEip8141.js +490 -0
- package/_esm/core/TxEnvelopeEip8141.js.map +1 -0
- package/_esm/core/internal/curves.js +19 -0
- package/_esm/core/internal/curves.js.map +1 -0
- package/_esm/core/internal/quantity.js +14 -0
- package/_esm/core/internal/quantity.js.map +1 -0
- package/_esm/erc4337/UserOperationReceipt.js.map +1 -1
- package/_esm/index.js +73 -0
- package/_esm/index.js.map +1 -1
- package/_esm/tempo/KeyAuthorization.js +42 -9
- package/_esm/tempo/KeyAuthorization.js.map +1 -1
- package/_esm/tempo/MultisigConfig.js +41 -22
- package/_esm/tempo/MultisigConfig.js.map +1 -1
- package/_esm/tempo/MultisigOperation.js +20 -100
- package/_esm/tempo/MultisigOperation.js.map +1 -1
- package/_esm/tempo/MultisigSimulation.js +18 -46
- package/_esm/tempo/MultisigSimulation.js.map +1 -1
- package/_esm/tempo/SignatureEnvelope.js +107 -169
- package/_esm/tempo/SignatureEnvelope.js.map +1 -1
- package/_esm/tempo/TransactionRequest.js +5 -1
- package/_esm/tempo/TransactionRequest.js.map +1 -1
- package/_esm/tempo/index.js +3 -1
- package/_esm/tempo/index.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_types/core/Frame.d.ts +290 -0
- package/_types/core/Frame.d.ts.map +1 -0
- package/_types/core/FrameReceipt.d.ts +92 -0
- package/_types/core/FrameReceipt.d.ts.map +1 -0
- package/_types/core/FrameSignature.d.ts +357 -0
- package/_types/core/FrameSignature.d.ts.map +1 -0
- package/_types/core/Transaction.d.ts +29 -4
- package/_types/core/Transaction.d.ts.map +1 -1
- package/_types/core/TransactionReceipt.d.ts +15 -6
- package/_types/core/TransactionReceipt.d.ts.map +1 -1
- package/_types/core/TransactionRequest.d.ts +10 -4
- package/_types/core/TransactionRequest.d.ts.map +1 -1
- package/_types/core/TxEnvelopeEip8141.d.ts +343 -0
- package/_types/core/TxEnvelopeEip8141.d.ts.map +1 -0
- package/_types/core/internal/curves.d.ts +19 -0
- package/_types/core/internal/curves.d.ts.map +1 -0
- package/_types/core/internal/quantity.d.ts +10 -0
- package/_types/core/internal/quantity.d.ts.map +1 -0
- package/_types/erc4337/UserOperationReceipt.d.ts +1 -1
- package/_types/erc4337/UserOperationReceipt.d.ts.map +1 -1
- package/_types/index.d.ts +73 -0
- package/_types/index.d.ts.map +1 -1
- package/_types/tempo/KeyAuthorization.d.ts +48 -38
- package/_types/tempo/KeyAuthorization.d.ts.map +1 -1
- package/_types/tempo/MultisigConfig.d.ts +15 -14
- package/_types/tempo/MultisigConfig.d.ts.map +1 -1
- package/_types/tempo/MultisigOperation.d.ts +3 -2
- package/_types/tempo/MultisigOperation.d.ts.map +1 -1
- package/_types/tempo/MultisigSimulation.d.ts +2 -49
- package/_types/tempo/MultisigSimulation.d.ts.map +1 -1
- package/_types/tempo/SignatureEnvelope.d.ts +69 -128
- package/_types/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/_types/tempo/Transaction.d.ts +2 -0
- package/_types/tempo/Transaction.d.ts.map +1 -1
- package/_types/tempo/TransactionReceipt.d.ts +2 -0
- package/_types/tempo/TransactionReceipt.d.ts.map +1 -1
- package/_types/tempo/TransactionRequest.d.ts +5 -2
- package/_types/tempo/TransactionRequest.d.ts.map +1 -1
- package/_types/tempo/index.d.ts +3 -1
- package/_types/tempo/index.d.ts.map +1 -1
- package/_types/version.d.ts +1 -1
- package/core/Frame.ts +443 -0
- package/core/FrameReceipt.ts +117 -0
- package/core/FrameSignature.ts +606 -0
- package/core/Transaction.ts +73 -4
- package/core/TransactionReceipt.ts +41 -4
- package/core/TransactionRequest.ts +26 -2
- package/core/TxEnvelopeEip8141.ts +717 -0
- package/core/internal/curves.ts +22 -0
- package/core/internal/quantity.ts +16 -0
- package/erc4337/UserOperationReceipt.ts +1 -6
- package/index.ts +73 -0
- package/package.json +21 -1
- package/tempo/AuthorizationTempo.test.ts +8 -4
- package/tempo/KeyAuthorization.test-d.ts +68 -33
- package/tempo/KeyAuthorization.test.ts +89 -8
- package/tempo/KeyAuthorization.ts +124 -61
- package/tempo/MultisigConfig.test.ts +34 -26
- package/tempo/MultisigConfig.ts +54 -24
- package/tempo/MultisigOperation.test.ts +79 -550
- package/tempo/MultisigOperation.ts +31 -146
- package/tempo/MultisigSimulation.test-d.ts +2 -2
- package/tempo/MultisigSimulation.test.ts +21 -110
- package/tempo/MultisigSimulation.ts +25 -99
- package/tempo/SignatureEnvelope.test-d.ts +29 -67
- package/tempo/SignatureEnvelope.test.ts +301 -568
- package/tempo/SignatureEnvelope.ts +156 -274
- package/tempo/TransactionRequest.test-d.ts +6 -5
- package/tempo/TransactionRequest.test.ts +17 -80
- package/tempo/TransactionRequest.ts +23 -3
- package/tempo/index.ts +3 -1
- package/tempo/multisig.e2e.test.ts +322 -861
- package/version.ts +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curve constants, inlined so that modules needing nothing but an order do not
|
|
3
|
+
* pull a curve implementation into the bundle.
|
|
4
|
+
*
|
|
5
|
+
* These are fixed by the curve specifications and are asserted against
|
|
6
|
+
* `@noble/curves` in `src/core/_test/curves.test.ts`.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Order of the secp256r1 (P-256) curve.
|
|
13
|
+
*
|
|
14
|
+
* @see https://www.secg.org/sec2-v2.pdf
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export const p256N =
|
|
18
|
+
0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551n
|
|
19
|
+
|
|
20
|
+
/** Order of the secp256k1 curve. @internal */
|
|
21
|
+
export const secp256k1N =
|
|
22
|
+
0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as Hex from '../Hex.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Converts a "numberish" value (`Hex.Hex | bigint | number`) to an RPC quantity
|
|
5
|
+
* (`Hex.Hex`). Hex values are passed through unchanged; numbers and bigints are
|
|
6
|
+
* encoded via {@link ox#Hex.(fromNumber:function)}.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export function fromNumberish(
|
|
11
|
+
value: Hex.Hex | bigint | number,
|
|
12
|
+
options?: Hex.fromNumber.Options,
|
|
13
|
+
): Hex.Hex {
|
|
14
|
+
if (typeof value === 'string') return value
|
|
15
|
+
return Hex.fromNumber(value, options)
|
|
16
|
+
}
|
package/index.ts
CHANGED
|
@@ -1547,6 +1547,60 @@ export * as Fee from './core/Fee.js'
|
|
|
1547
1547
|
* @category Execution Spec
|
|
1548
1548
|
*/
|
|
1549
1549
|
export * as Filter from './core/Filter.js'
|
|
1550
|
+
/**
|
|
1551
|
+
* Utilities for constructing, validating, and encoding [EIP-8141](https://eips.ethereum.org/EIPS/eip-8141) call frames.
|
|
1552
|
+
*
|
|
1553
|
+
* A {@link ox#Frame.Frame} describes a call with an execution mode, approval flags,
|
|
1554
|
+
* and separate execution and state gas limits.
|
|
1555
|
+
*
|
|
1556
|
+
* @example
|
|
1557
|
+
* ### Creating Frames
|
|
1558
|
+
*
|
|
1559
|
+
* Use {@link ox#Frame.(from:function)} to construct a frame with named mode and flags.
|
|
1560
|
+
*
|
|
1561
|
+
* ```ts twoslash
|
|
1562
|
+
* import { Frame } from 'ox'
|
|
1563
|
+
*
|
|
1564
|
+
* const frame = Frame.from({
|
|
1565
|
+
* flags: 'approveExecutionAndPayment',
|
|
1566
|
+
* gas: 50_000n,
|
|
1567
|
+
* mode: 'verify'
|
|
1568
|
+
* })
|
|
1569
|
+
* ```
|
|
1570
|
+
*
|
|
1571
|
+
* @category Transaction Envelopes
|
|
1572
|
+
*/
|
|
1573
|
+
export * as Frame from './core/Frame.js'
|
|
1574
|
+
/**
|
|
1575
|
+
* Utilities for converting EIP-8141 frame receipts between RPC and decoded forms.
|
|
1576
|
+
*
|
|
1577
|
+
* Frame receipts include execution gas, state gas, logs, and execution status.
|
|
1578
|
+
*
|
|
1579
|
+
* @category Execution Spec
|
|
1580
|
+
*/
|
|
1581
|
+
export * as FrameReceipt from './core/FrameReceipt.js'
|
|
1582
|
+
/**
|
|
1583
|
+
* Utilities for constructing, validating, and encoding [EIP-8141](https://eips.ethereum.org/EIPS/eip-8141) signature entries.
|
|
1584
|
+
*
|
|
1585
|
+
* Supports {@link ox#FrameSignature.Arbitrary}, {@link ox#FrameSignature.Secp256k1},
|
|
1586
|
+
* and {@link ox#FrameSignature.P256} entries. An empty payload selects the canonical
|
|
1587
|
+
* transaction signing hash.
|
|
1588
|
+
*
|
|
1589
|
+
* @example
|
|
1590
|
+
* ### Creating Signature Entries
|
|
1591
|
+
*
|
|
1592
|
+
* Use {@link ox#FrameSignature.(from:function)} to wrap arbitrary witness bytes.
|
|
1593
|
+
*
|
|
1594
|
+
* ```ts twoslash
|
|
1595
|
+
* import { FrameSignature } from 'ox'
|
|
1596
|
+
*
|
|
1597
|
+
* const entry = FrameSignature.from('0xaabb')
|
|
1598
|
+
* // @log: { payload: '0x', scheme: 'arbitrary', signature: '0xaabb' }
|
|
1599
|
+
* ```
|
|
1600
|
+
*
|
|
1601
|
+
* @category Transaction Envelopes
|
|
1602
|
+
*/
|
|
1603
|
+
export * as FrameSignature from './core/FrameSignature.js'
|
|
1550
1604
|
/**
|
|
1551
1605
|
* Utility functions for hashing (keccak256, sha256, etc).
|
|
1552
1606
|
*
|
|
@@ -3270,6 +3324,25 @@ export * as TxEnvelopeEip4844 from './core/TxEnvelopeEip4844.js'
|
|
|
3270
3324
|
* @category Transaction Envelopes
|
|
3271
3325
|
*/
|
|
3272
3326
|
export * as TxEnvelopeEip7702 from './core/TxEnvelopeEip7702.js'
|
|
3327
|
+
/**
|
|
3328
|
+
* Utilities for constructing, signing, and encoding EIP-8141 frame transactions.
|
|
3329
|
+
*
|
|
3330
|
+
* @example
|
|
3331
|
+
* ### Basic Usage
|
|
3332
|
+
*
|
|
3333
|
+
* ```ts twoslash
|
|
3334
|
+
* import { TxEnvelopeEip8141 } from 'ox'
|
|
3335
|
+
*
|
|
3336
|
+
* const envelope = TxEnvelopeEip8141.from({
|
|
3337
|
+
* chainId: 1,
|
|
3338
|
+
* frames: [{ gas: 50_000n, mode: 'sender' }],
|
|
3339
|
+
* sender: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8'
|
|
3340
|
+
* })
|
|
3341
|
+
* ```
|
|
3342
|
+
*
|
|
3343
|
+
* @category Transaction Envelopes
|
|
3344
|
+
*/
|
|
3345
|
+
export * as TxEnvelopeEip8141 from './core/TxEnvelopeEip8141.js'
|
|
3273
3346
|
/**
|
|
3274
3347
|
* Utility functions for working
|
|
3275
3348
|
* with **Legacy Transaction Envelopes**.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ox",
|
|
3
3
|
"description": "Ethereum Standard Library",
|
|
4
|
-
"version": "0.14.
|
|
4
|
+
"version": "0.14.46",
|
|
5
5
|
"main": "./_cjs/index.js",
|
|
6
6
|
"module": "./_esm/index.js",
|
|
7
7
|
"types": "./_types/index.d.ts",
|
|
@@ -222,6 +222,21 @@
|
|
|
222
222
|
"import": "./_esm/core/Filter.js",
|
|
223
223
|
"default": "./_cjs/core/Filter.js"
|
|
224
224
|
},
|
|
225
|
+
"./Frame": {
|
|
226
|
+
"types": "./_types/core/Frame.d.ts",
|
|
227
|
+
"import": "./_esm/core/Frame.js",
|
|
228
|
+
"default": "./_cjs/core/Frame.js"
|
|
229
|
+
},
|
|
230
|
+
"./FrameReceipt": {
|
|
231
|
+
"types": "./_types/core/FrameReceipt.d.ts",
|
|
232
|
+
"import": "./_esm/core/FrameReceipt.js",
|
|
233
|
+
"default": "./_cjs/core/FrameReceipt.js"
|
|
234
|
+
},
|
|
235
|
+
"./FrameSignature": {
|
|
236
|
+
"types": "./_types/core/FrameSignature.d.ts",
|
|
237
|
+
"import": "./_esm/core/FrameSignature.js",
|
|
238
|
+
"default": "./_cjs/core/FrameSignature.js"
|
|
239
|
+
},
|
|
225
240
|
"./Hash": {
|
|
226
241
|
"types": "./_types/core/Hash.d.ts",
|
|
227
242
|
"import": "./_esm/core/Hash.js",
|
|
@@ -372,6 +387,11 @@
|
|
|
372
387
|
"import": "./_esm/core/TxEnvelopeEip7702.js",
|
|
373
388
|
"default": "./_cjs/core/TxEnvelopeEip7702.js"
|
|
374
389
|
},
|
|
390
|
+
"./TxEnvelopeEip8141": {
|
|
391
|
+
"types": "./_types/core/TxEnvelopeEip8141.d.ts",
|
|
392
|
+
"import": "./_esm/core/TxEnvelopeEip8141.js",
|
|
393
|
+
"default": "./_cjs/core/TxEnvelopeEip8141.js"
|
|
394
|
+
},
|
|
375
395
|
"./TxEnvelopeLegacy": {
|
|
376
396
|
"types": "./_types/core/TxEnvelopeLegacy.d.ts",
|
|
377
397
|
"import": "./_esm/core/TxEnvelopeLegacy.js",
|
|
@@ -326,7 +326,8 @@ describe('fromRpc', () => {
|
|
|
326
326
|
type: 'p256',
|
|
327
327
|
},
|
|
328
328
|
})
|
|
329
|
-
if (typeof result.signature === 'string')
|
|
329
|
+
if (typeof result.signature === 'string')
|
|
330
|
+
throw new Error('Expected structured primitive signature')
|
|
330
331
|
expect(result.signature.type).toBe('p256')
|
|
331
332
|
expect(result.signature).toHaveProperty('prehash', true)
|
|
332
333
|
expect(result.signature).toHaveProperty('publicKey')
|
|
@@ -349,7 +350,8 @@ describe('fromRpc', () => {
|
|
|
349
350
|
'0x49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d976305000000007b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22222c226f726967696e223a2268747470733a2f2f6578616d706c652e636f6d222c2263726f73734f726967696e223a66616c73657d',
|
|
350
351
|
},
|
|
351
352
|
})
|
|
352
|
-
if (typeof result.signature === 'string')
|
|
353
|
+
if (typeof result.signature === 'string')
|
|
354
|
+
throw new Error('Expected structured primitive signature')
|
|
353
355
|
expect(result.signature.type).toBe('webAuthn')
|
|
354
356
|
expect(result.signature).toHaveProperty('metadata')
|
|
355
357
|
expect(result.signature).toHaveProperty('publicKey')
|
|
@@ -951,7 +953,8 @@ describe('toRpc', () => {
|
|
|
951
953
|
type: 'p256',
|
|
952
954
|
},
|
|
953
955
|
})
|
|
954
|
-
if (typeof result.signature === 'string')
|
|
956
|
+
if (typeof result.signature === 'string')
|
|
957
|
+
throw new Error('Expected structured primitive signature')
|
|
955
958
|
expect(result.signature.type).toBe('p256')
|
|
956
959
|
})
|
|
957
960
|
|
|
@@ -973,7 +976,8 @@ describe('toRpc', () => {
|
|
|
973
976
|
type: 'webAuthn',
|
|
974
977
|
},
|
|
975
978
|
})
|
|
976
|
-
if (typeof result.signature === 'string')
|
|
979
|
+
if (typeof result.signature === 'string')
|
|
980
|
+
throw new Error('Expected structured primitive signature')
|
|
977
981
|
expect(result.signature.type).toBe('webAuthn')
|
|
978
982
|
})
|
|
979
983
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { expectTypeOf, test } from 'vitest'
|
|
2
2
|
import * as KeyAuthorization from './KeyAuthorization.js'
|
|
3
|
-
import * as MultisigConfig from './MultisigConfig.js'
|
|
4
3
|
import type * as SignatureEnvelope from './SignatureEnvelope.js'
|
|
4
|
+
import * as TempoAddress from './TempoAddress.js'
|
|
5
5
|
|
|
6
6
|
const authorization = {
|
|
7
7
|
address: '0x1111111111111111111111111111111111111111',
|
|
@@ -20,26 +20,18 @@ const signature = {
|
|
|
20
20
|
|
|
21
21
|
const multisig = {
|
|
22
22
|
account: '0x2222222222222222222222222222222222222222',
|
|
23
|
-
config:
|
|
23
|
+
config: {
|
|
24
|
+
salt: `0x${'00'.repeat(32)}`,
|
|
25
|
+
version: 0n,
|
|
26
|
+
threshold: 1,
|
|
24
27
|
owners: [
|
|
25
|
-
{
|
|
26
|
-
owner: '0x1111111111111111111111111111111111111111',
|
|
27
|
-
weight: 1,
|
|
28
|
-
},
|
|
28
|
+
{ owner: '0x1111111111111111111111111111111111111111', weight: 1 },
|
|
29
29
|
],
|
|
30
|
-
|
|
31
|
-
version: 1n,
|
|
32
|
-
}),
|
|
30
|
+
},
|
|
33
31
|
signatures: [signature],
|
|
34
32
|
type: 'multisig',
|
|
35
33
|
} as const satisfies SignatureEnvelope.Multisig
|
|
36
34
|
|
|
37
|
-
const keychain = {
|
|
38
|
-
inner: signature,
|
|
39
|
-
type: 'keychain',
|
|
40
|
-
userAddress: authorization.address,
|
|
41
|
-
} as const satisfies SignatureEnvelope.Keychain
|
|
42
|
-
|
|
43
35
|
test('accepts primitive signatures', () => {
|
|
44
36
|
const signed = KeyAuthorization.from(authorization, { signature })
|
|
45
37
|
|
|
@@ -48,27 +40,56 @@ test('accepts primitive signatures', () => {
|
|
|
48
40
|
>()
|
|
49
41
|
})
|
|
50
42
|
|
|
51
|
-
test('accepts multisig signatures', () => {
|
|
52
|
-
const signed = KeyAuthorization.from(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
>()
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
chainId: '0x1',
|
|
62
|
-
expiry: null,
|
|
63
|
-
keyId: authorization.address,
|
|
64
|
-
keyType: authorization.type,
|
|
65
|
-
signature: multisigRpc,
|
|
66
|
-
}
|
|
43
|
+
test('accepts multisig signatures and account-bound grants', () => {
|
|
44
|
+
const signed = KeyAuthorization.from(
|
|
45
|
+
{ ...authorization, account: multisig.account, type: 'multisig' },
|
|
46
|
+
{ signature: multisig },
|
|
47
|
+
)
|
|
48
|
+
expectTypeOf(signed).toMatchTypeOf<KeyAuthorization.Signed>()
|
|
49
|
+
expectTypeOf(
|
|
50
|
+
KeyAuthorization.toRpc(signed),
|
|
51
|
+
).toMatchTypeOf<KeyAuthorization.Rpc>()
|
|
52
|
+
})
|
|
67
53
|
|
|
68
|
-
|
|
54
|
+
test('requires an account for multisig grants', () => {
|
|
55
|
+
type Multisig = Extract<KeyAuthorization.Input, { type: 'multisig' }>
|
|
56
|
+
expectTypeOf<Multisig['account']>().toEqualTypeOf<TempoAddress.Address>()
|
|
57
|
+
expectTypeOf<
|
|
58
|
+
Extract<KeyAuthorization.Signed, { type: 'multisig' }>['account']
|
|
59
|
+
>().toEqualTypeOf<`0x${string}`>()
|
|
60
|
+
expectTypeOf<
|
|
61
|
+
Omit<Extract<KeyAuthorization.Rpc, { keyType: 'multisig' }>, 'account'>
|
|
62
|
+
>().not.toExtend<KeyAuthorization.Rpc>()
|
|
63
|
+
expectTypeOf<{
|
|
64
|
+
address: `0x${string}`
|
|
65
|
+
chainId: bigint
|
|
66
|
+
type: 'multisig'
|
|
67
|
+
}>().not.toExtend<KeyAuthorization.Input>()
|
|
68
|
+
expectTypeOf<{
|
|
69
|
+
account: undefined
|
|
70
|
+
address: `0x${string}`
|
|
71
|
+
chainId: bigint
|
|
72
|
+
type: 'multisig'
|
|
73
|
+
}>().not.toExtend<KeyAuthorization.Input>()
|
|
74
|
+
expectTypeOf<{
|
|
75
|
+
account: null
|
|
76
|
+
chainId: '0x1'
|
|
77
|
+
expiry: null
|
|
78
|
+
keyId: `0x${string}`
|
|
79
|
+
keyType: 'multisig'
|
|
80
|
+
signature: KeyAuthorization.SignatureRpc
|
|
81
|
+
}>().not.toExtend<KeyAuthorization.Rpc>()
|
|
82
|
+
expectTypeOf<
|
|
83
|
+
Extract<KeyAuthorization.Rpc, { keyType: 'multisig' }>['account']
|
|
84
|
+
>().toEqualTypeOf<`0x${string}`>()
|
|
69
85
|
})
|
|
70
86
|
|
|
71
87
|
test('rejects keychain signatures', () => {
|
|
88
|
+
const keychain = {
|
|
89
|
+
inner: signature,
|
|
90
|
+
type: 'keychain',
|
|
91
|
+
userAddress: authorization.address,
|
|
92
|
+
} as const
|
|
72
93
|
KeyAuthorization.from(authorization, {
|
|
73
94
|
// @ts-expect-error Key authorizations do not accept keychain signatures.
|
|
74
95
|
signature: keychain,
|
|
@@ -94,5 +115,19 @@ test('rejects keychain signatures', () => {
|
|
|
94
115
|
signature: keychainRpc,
|
|
95
116
|
}
|
|
96
117
|
|
|
97
|
-
expectTypeOf(rpc).
|
|
118
|
+
expectTypeOf(rpc).toMatchTypeOf<KeyAuthorization.Rpc>()
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('resolves Tempo address bindings for multisig grants', () => {
|
|
122
|
+
const signed = KeyAuthorization.from(
|
|
123
|
+
{
|
|
124
|
+
account: TempoAddress.format(authorization.address),
|
|
125
|
+
address: TempoAddress.format(authorization.address),
|
|
126
|
+
chainId: 1n,
|
|
127
|
+
type: 'multisig',
|
|
128
|
+
},
|
|
129
|
+
{ signature },
|
|
130
|
+
)
|
|
131
|
+
expectTypeOf(signed.account).toMatchTypeOf<`0x${string}`>()
|
|
132
|
+
expectTypeOf(signed.address).toMatchTypeOf<`0x${string}`>()
|
|
98
133
|
})
|
|
@@ -78,7 +78,89 @@ const signature_keychain = {
|
|
|
78
78
|
userAddress: address,
|
|
79
79
|
} as const satisfies SignatureEnvelope.Keychain
|
|
80
80
|
|
|
81
|
+
describe('multisig account binding', () => {
|
|
82
|
+
test('resolves Tempo account bindings before encoding', () => {
|
|
83
|
+
const signed = KeyAuthorization.from(
|
|
84
|
+
{ account: `tempox${address}`, address, chainId: 1n, type: 'multisig' },
|
|
85
|
+
{ signature: signature_secp256k1 },
|
|
86
|
+
)
|
|
87
|
+
expect(signed.account).toMatchInlineSnapshot(
|
|
88
|
+
`"0xBE95c3f554e9Fc85ec51bE69a3D807A0D55BCF2C"`,
|
|
89
|
+
)
|
|
90
|
+
expect(KeyAuthorization.toRpc(signed).account).toMatchInlineSnapshot(
|
|
91
|
+
`"0xBE95c3f554e9Fc85ec51bE69a3D807A0D55BCF2C"`,
|
|
92
|
+
)
|
|
93
|
+
expect(
|
|
94
|
+
KeyAuthorization.deserialize(KeyAuthorization.serialize(signed)).account,
|
|
95
|
+
).toMatchInlineSnapshot(`"0xbe95c3f554e9fc85ec51be69a3d807a0d55bcf2c"`)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test('rejects unbound grants before signing or encoding', () => {
|
|
99
|
+
const authorization = { address, chainId: 1n, type: 'multisig' } as const
|
|
100
|
+
const signed = {
|
|
101
|
+
...authorization,
|
|
102
|
+
signature: SignatureEnvelope.from(signature_secp256k1),
|
|
103
|
+
}
|
|
104
|
+
for (const encode of [
|
|
105
|
+
// @ts-expect-error Deliberately unbound multisig grant.
|
|
106
|
+
() => KeyAuthorization.from(authorization),
|
|
107
|
+
// @ts-expect-error Deliberately unbound multisig grant.
|
|
108
|
+
() => KeyAuthorization.toTuple(authorization),
|
|
109
|
+
// @ts-expect-error Deliberately unbound multisig grant.
|
|
110
|
+
() => KeyAuthorization.getSignPayload(authorization),
|
|
111
|
+
// @ts-expect-error Deliberately unbound multisig grant.
|
|
112
|
+
() => KeyAuthorization.serialize(authorization),
|
|
113
|
+
// @ts-expect-error Deliberately unbound multisig grant.
|
|
114
|
+
() => KeyAuthorization.toRpc(signed),
|
|
115
|
+
])
|
|
116
|
+
expect(encode).toThrowErrorMatchingInlineSnapshot(
|
|
117
|
+
`[KeyAuthorization.MissingAccountError: Multisig key grants require a parent account binding.]`,
|
|
118
|
+
)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test('rejects unbound RPC and RLP grants', () => {
|
|
122
|
+
const signed = KeyAuthorization.from(
|
|
123
|
+
{ account: address, address, chainId: 1n, type: 'multisig' },
|
|
124
|
+
{ signature: signature_secp256k1 },
|
|
125
|
+
)
|
|
126
|
+
const rpc = KeyAuthorization.toRpc(signed)
|
|
127
|
+
for (const account of [undefined, null]) {
|
|
128
|
+
// @ts-expect-error Deliberately unbound multisig grant.
|
|
129
|
+
expect(() => KeyAuthorization.fromRpc({ ...rpc, account })).toThrowError(
|
|
130
|
+
KeyAuthorization.MissingAccountError,
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
expect(() =>
|
|
134
|
+
KeyAuthorization.fromTuple([['0x01', '0x03', address]]),
|
|
135
|
+
).toThrowError(KeyAuthorization.MissingAccountError)
|
|
136
|
+
expect(KeyAuthorization.fromRpc(rpc).account).toBe(address)
|
|
137
|
+
expect(
|
|
138
|
+
KeyAuthorization.deserialize(KeyAuthorization.serialize(signed)).account,
|
|
139
|
+
).toBe(address)
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
|
|
81
143
|
describe('from', () => {
|
|
144
|
+
test('accepts multisig grants and delegates', () => {
|
|
145
|
+
const signed = KeyAuthorization.from(
|
|
146
|
+
{
|
|
147
|
+
address,
|
|
148
|
+
chainId: 1n,
|
|
149
|
+
type: 'multisig',
|
|
150
|
+
account: signature_multisig.account,
|
|
151
|
+
},
|
|
152
|
+
{ signature: signature_multisig },
|
|
153
|
+
)
|
|
154
|
+
expect(
|
|
155
|
+
KeyAuthorization.deserialize(KeyAuthorization.serialize(signed)),
|
|
156
|
+
).toEqual(signed)
|
|
157
|
+
expect(KeyAuthorization.fromRpc(KeyAuthorization.toRpc(signed))).toEqual(
|
|
158
|
+
signed,
|
|
159
|
+
)
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
describe('fromRpc', () => {
|
|
82
164
|
test('default', () => {
|
|
83
165
|
const authorization = KeyAuthorization.from({
|
|
84
166
|
address,
|
|
@@ -1154,7 +1236,6 @@ describe('deserialize', () => {
|
|
|
1154
1236
|
"account": "0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b",
|
|
1155
1237
|
"address": "0x1eff47bc3a10a45d4b230b5d10e37751fe6aa718",
|
|
1156
1238
|
"chainId": 4217n,
|
|
1157
|
-
"isAdmin": false,
|
|
1158
1239
|
"signature": {
|
|
1159
1240
|
"account": "0xc4a590afa7337e5cd5eb3aa60cacf91c5400044b",
|
|
1160
1241
|
"config": {
|
|
@@ -2589,11 +2670,11 @@ describe('admin keys (TIP-1049)', () => {
|
|
|
2589
2670
|
expect((authTuple as unknown as unknown[]).length).toBe(3)
|
|
2590
2671
|
})
|
|
2591
2672
|
|
|
2592
|
-
test('fromTuple:
|
|
2673
|
+
test('fromTuple: preserves isAdmin without account', () => {
|
|
2593
2674
|
const restored = KeyAuthorization.fromTuple([
|
|
2594
2675
|
['0x01', '0x', address, '0x', [], [], '0x', '0x01'],
|
|
2595
2676
|
])
|
|
2596
|
-
expect(restored.isAdmin).
|
|
2677
|
+
expect(restored.isAdmin).toBe(true)
|
|
2597
2678
|
expect(restored.account).toBeUndefined()
|
|
2598
2679
|
})
|
|
2599
2680
|
|
|
@@ -2601,7 +2682,7 @@ describe('admin keys (TIP-1049)', () => {
|
|
|
2601
2682
|
const restored = KeyAuthorization.fromTuple([
|
|
2602
2683
|
['0x01', '0x', address, '0x', [], [], '0x', '0x', account],
|
|
2603
2684
|
])
|
|
2604
|
-
expect(restored.isAdmin).
|
|
2685
|
+
expect(restored.isAdmin).toBeUndefined()
|
|
2605
2686
|
expect(restored.account).toBe(account)
|
|
2606
2687
|
})
|
|
2607
2688
|
|
|
@@ -2647,7 +2728,7 @@ describe('admin keys (TIP-1049)', () => {
|
|
|
2647
2728
|
})
|
|
2648
2729
|
const serialized = KeyAuthorization.serialize(authorization)
|
|
2649
2730
|
const restored = KeyAuthorization.deserialize(serialized)
|
|
2650
|
-
expect(restored.isAdmin).
|
|
2731
|
+
expect(restored.isAdmin).toBeUndefined()
|
|
2651
2732
|
expect(restored.account).toBe(account)
|
|
2652
2733
|
})
|
|
2653
2734
|
|
|
@@ -2670,14 +2751,14 @@ describe('admin keys (TIP-1049)', () => {
|
|
|
2670
2751
|
expect(restored.account).toBe(account)
|
|
2671
2752
|
})
|
|
2672
2753
|
|
|
2673
|
-
test('fromRpc:
|
|
2754
|
+
test('fromRpc: preserves isAdmin without account', () => {
|
|
2674
2755
|
const authorization = KeyAuthorization.from(
|
|
2675
2756
|
{ address, chainId: 1n, type: 'secp256k1' },
|
|
2676
2757
|
{ signature: SignatureEnvelope.from(signature_secp256k1) },
|
|
2677
2758
|
)
|
|
2678
2759
|
const rpc = KeyAuthorization.toRpc(authorization)
|
|
2679
2760
|
const restored = KeyAuthorization.fromRpc({ ...rpc, isAdmin: true })
|
|
2680
|
-
expect(restored.isAdmin).
|
|
2761
|
+
expect(restored.isAdmin).toBe(true)
|
|
2681
2762
|
expect(restored.account).toBeUndefined()
|
|
2682
2763
|
})
|
|
2683
2764
|
|
|
@@ -2688,7 +2769,7 @@ describe('admin keys (TIP-1049)', () => {
|
|
|
2688
2769
|
)
|
|
2689
2770
|
const rpc = KeyAuthorization.toRpc(authorization)
|
|
2690
2771
|
const restored = KeyAuthorization.fromRpc({ ...rpc, account })
|
|
2691
|
-
expect(restored.isAdmin).
|
|
2772
|
+
expect(restored.isAdmin).toBeUndefined()
|
|
2692
2773
|
expect(restored.account).toBe(account)
|
|
2693
2774
|
})
|
|
2694
2775
|
|