ox 1.8.1 → 1.8.3
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 +35 -0
- package/dist/core/Frame.d.ts +23 -20
- package/dist/core/Frame.d.ts.map +1 -1
- package/dist/core/Frame.js +28 -23
- package/dist/core/Frame.js.map +1 -1
- package/dist/core/FrameReceipt.d.ts +23 -14
- package/dist/core/FrameReceipt.d.ts.map +1 -1
- package/dist/core/FrameReceipt.js +15 -11
- package/dist/core/FrameReceipt.js.map +1 -1
- package/dist/core/FrameRequest.d.ts +50 -0
- package/dist/core/FrameRequest.d.ts.map +1 -0
- package/dist/core/FrameRequest.js +59 -0
- package/dist/core/FrameRequest.js.map +1 -0
- package/dist/core/FrameSignature.d.ts +17 -16
- package/dist/core/FrameSignature.d.ts.map +1 -1
- package/dist/core/FrameSignature.js +38 -21
- package/dist/core/FrameSignature.js.map +1 -1
- package/dist/core/Siwe.d.ts.map +1 -1
- package/dist/core/Siwe.js +3 -3
- package/dist/core/Siwe.js.map +1 -1
- package/dist/core/Transaction.d.ts +2 -2
- package/dist/core/Transaction.d.ts.map +1 -1
- package/dist/core/Transaction.js.map +1 -1
- package/dist/core/TransactionRequest.d.ts +5 -5
- package/dist/core/TransactionRequest.d.ts.map +1 -1
- package/dist/core/TransactionRequest.js +3 -3
- package/dist/core/TransactionRequest.js.map +1 -1
- package/dist/core/TxEnvelope.d.ts +3 -1
- package/dist/core/TxEnvelope.d.ts.map +1 -1
- package/dist/core/TxEnvelope.js +9 -1
- package/dist/core/TxEnvelope.js.map +1 -1
- package/dist/core/TxEnvelopeEip8141.d.ts +4 -4
- package/dist/core/TxEnvelopeEip8141.js +8 -8
- package/dist/core/TxEnvelopeEip8141.js.map +1 -1
- package/dist/core/internal/rpcSchemas/eth.d.ts +16 -4
- package/dist/core/internal/rpcSchemas/eth.d.ts.map +1 -1
- package/dist/index.d.ts +21 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -5
- package/dist/index.js.map +1 -1
- package/dist/zod/Block.d.ts +49 -37
- package/dist/zod/Block.d.ts.map +1 -1
- package/dist/zod/Frame.d.ts +14 -14
- package/dist/zod/Frame.js +5 -5
- package/dist/zod/Frame.js.map +1 -1
- package/dist/zod/FrameReceipt.d.ts +42 -2
- package/dist/zod/FrameReceipt.d.ts.map +1 -1
- package/dist/zod/FrameReceipt.js +11 -1
- package/dist/zod/FrameReceipt.js.map +1 -1
- package/dist/zod/FrameRequest.d.ts +40 -0
- package/dist/zod/FrameRequest.d.ts.map +1 -0
- package/dist/zod/FrameRequest.js +37 -0
- package/dist/zod/FrameRequest.js.map +1 -0
- package/dist/zod/FrameSignature.d.ts +21 -13
- package/dist/zod/FrameSignature.d.ts.map +1 -1
- package/dist/zod/FrameSignature.js +10 -7
- package/dist/zod/FrameSignature.js.map +1 -1
- package/dist/zod/RpcSchema.d.ts +447 -265
- package/dist/zod/RpcSchema.d.ts.map +1 -1
- package/dist/zod/Transaction.d.ts +98 -74
- package/dist/zod/Transaction.d.ts.map +1 -1
- package/dist/zod/Transaction.js +4 -4
- package/dist/zod/Transaction.js.map +1 -1
- package/dist/zod/TransactionEnvelope.d.ts +50 -34
- package/dist/zod/TransactionEnvelope.d.ts.map +1 -1
- package/dist/zod/TransactionReceipt.d.ts +42 -2
- package/dist/zod/TransactionReceipt.d.ts.map +1 -1
- package/dist/zod/TransactionRequest.d.ts +29 -21
- package/dist/zod/TransactionRequest.d.ts.map +1 -1
- package/dist/zod/TransactionRequest.js +3 -3
- package/dist/zod/TransactionRequest.js.map +1 -1
- package/dist/zod/TxEnvelopeEip8141.d.ts +37 -25
- package/dist/zod/TxEnvelopeEip8141.d.ts.map +1 -1
- package/dist/zod/internal/rpcSchemas/Eth.d.ts +449 -267
- package/dist/zod/internal/rpcSchemas/Eth.d.ts.map +1 -1
- package/dist/zod/internal/rpcSchemas/Eth.js +9 -0
- package/dist/zod/internal/rpcSchemas/Eth.js.map +1 -1
- package/dist/zod/internal/rpcSchemas/Wallet.d.ts +49 -21
- package/dist/zod/internal/rpcSchemas/Wallet.d.ts.map +1 -1
- package/dist/zod/tempo/RpcSchemaTempo.d.ts +64 -48
- package/dist/zod/tempo/RpcSchemaTempo.d.ts.map +1 -1
- package/dist/zod/tempo/Transaction.d.ts +49 -37
- package/dist/zod/tempo/Transaction.d.ts.map +1 -1
- package/dist/zod/z.d.ts +1 -0
- package/dist/zod/z.d.ts.map +1 -1
- package/dist/zod/z.js +1 -0
- package/dist/zod/z.js.map +1 -1
- package/package.json +11 -1
- package/src/core/Frame.ts +41 -33
- package/src/core/FrameReceipt.ts +30 -16
- package/src/core/FrameRequest.ts +78 -0
- package/src/core/FrameSignature.ts +64 -34
- package/src/core/Siwe.ts +21 -13
- package/src/core/Transaction.ts +35 -24
- package/src/core/TransactionRequest.ts +9 -7
- package/src/core/TxEnvelope.ts +9 -1
- package/src/core/TxEnvelopeEip8141.ts +8 -8
- package/src/core/_test/AbiConstructor.test.ts +2 -0
- package/src/core/_test/Frame.test-d.ts +16 -7
- package/src/core/_test/Frame.test.ts +52 -24
- package/src/core/_test/FrameReceipt.test.ts +15 -9
- package/src/core/_test/FrameRequest.test-d.ts +16 -0
- package/src/core/_test/FrameRequest.test.ts +41 -0
- package/src/core/_test/FrameRpc.test.ts +131 -0
- package/src/core/_test/FrameSignature.test-d.ts +20 -0
- package/src/core/_test/FrameSignature.test.ts +132 -11
- package/src/core/_test/RpcSchema.test-d.ts +45 -0
- package/src/core/_test/Siwe.test.ts +147 -0
- package/src/core/_test/TransactionEnvelope.test.ts +1 -1
- package/src/core/_test/TransactionReceipt.test.ts +32 -6
- package/src/core/_test/TransactionRequest.test-d.ts +10 -1
- package/src/core/_test/TransactionRequest.test.ts +3 -2
- package/src/core/_test/TxEnvelopeEip8141.test-d.ts +2 -2
- package/src/core/_test/TxEnvelopeEip8141.test.ts +92 -53
- package/src/core/_test/index.test.ts +1 -0
- package/src/core/internal/rpcSchemas/eth.ts +13 -4
- package/src/index.ts +22 -5
- package/src/version.ts +1 -1
- package/src/zod/Frame.ts +5 -5
- package/src/zod/FrameReceipt.ts +11 -1
- package/src/zod/FrameRequest.ts +46 -0
- package/src/zod/FrameSignature.ts +10 -7
- package/src/zod/Transaction.ts +4 -4
- package/src/zod/TransactionRequest.ts +3 -3
- package/src/zod/_test/Frame.test.ts +13 -11
- package/src/zod/_test/FrameReceipt.test.ts +11 -4
- package/src/zod/_test/FrameRequest.test-d.ts +15 -0
- package/src/zod/_test/FrameRequest.test.ts +44 -0
- package/src/zod/_test/FrameSignature.test.ts +73 -9
- package/src/zod/_test/RpcSchema.test.ts +106 -0
- package/src/zod/_test/TransactionRequest.test.ts +61 -0
- package/src/zod/_test/TxEnvelopeEip8141.test.ts +3 -3
- package/src/zod/internal/rpcSchemas/Eth.ts +20 -0
- package/src/zod/z.ts +1 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as Frame from './Frame.js'
|
|
2
|
+
import type { Compute, PartialBy } from './internal/types.js'
|
|
3
|
+
|
|
4
|
+
/** A frame request whose omitted gas limits are estimated by the node. */
|
|
5
|
+
export type FrameRequest<bigintType = bigint> = Frame.Frame<bigintType>
|
|
6
|
+
|
|
7
|
+
/** JSON-RPC frame request. Only the execution mode is required. */
|
|
8
|
+
export type Rpc = Compute<
|
|
9
|
+
PartialBy<Frame.Rpc, Exclude<keyof Frame.Rpc, 'mode'>>
|
|
10
|
+
>
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Converts an RPC frame request, preserving omitted gas limits for node estimation.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts twoslash
|
|
17
|
+
* import { FrameRequest } from 'ox'
|
|
18
|
+
*
|
|
19
|
+
* const frame = FrameRequest.fromRpc({
|
|
20
|
+
* mode: '0x2',
|
|
21
|
+
* stateGas: '0x0'
|
|
22
|
+
* })
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @param frame - The RPC frame request.
|
|
26
|
+
* @returns The decoded request with omitted gas limits preserved.
|
|
27
|
+
*/
|
|
28
|
+
export function fromRpc(frame: Rpc): FrameRequest {
|
|
29
|
+
const { executionGas, stateGas, ...rest } = Frame.fromRpc({
|
|
30
|
+
...frame,
|
|
31
|
+
data: frame.data ?? '0x',
|
|
32
|
+
executionGas: frame.executionGas ?? '0x0',
|
|
33
|
+
flags: frame.flags ?? '0x0',
|
|
34
|
+
stateGas: frame.stateGas ?? '0x0',
|
|
35
|
+
value: frame.value ?? '0x0',
|
|
36
|
+
})
|
|
37
|
+
return {
|
|
38
|
+
...rest,
|
|
39
|
+
...(frame.executionGas === undefined ? {} : { executionGas }),
|
|
40
|
+
...(frame.stateGas === undefined ? {} : { stateGas }),
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export declare namespace fromRpc {
|
|
45
|
+
type ErrorType = Frame.fromRpc.ErrorType
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Converts a frame request to RPC fields without filling omitted gas limits.
|
|
50
|
+
*
|
|
51
|
+
* Explicit zero limits remain zero. Omitted mode, flags, value, and data use frame defaults.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts twoslash
|
|
55
|
+
* import { FrameRequest } from 'ox'
|
|
56
|
+
*
|
|
57
|
+
* const frame = FrameRequest.toRpc({
|
|
58
|
+
* mode: 'sender',
|
|
59
|
+
* stateGas: 0n
|
|
60
|
+
* })
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @param frame - The frame request. Gas and value accept hex, bigint, or number values.
|
|
64
|
+
* @returns The RPC request with omitted gas limits preserved.
|
|
65
|
+
*/
|
|
66
|
+
export function toRpc(frame: toRpc.Input): Rpc {
|
|
67
|
+
const { executionGas, stateGas, ...rest } = Frame.toRpc(frame)
|
|
68
|
+
return {
|
|
69
|
+
...rest,
|
|
70
|
+
...(frame.executionGas === undefined ? {} : { executionGas }),
|
|
71
|
+
...(frame.stateGas === undefined ? {} : { stateGas }),
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export declare namespace toRpc {
|
|
76
|
+
type Input = Frame.toRpc.Input
|
|
77
|
+
type ErrorType = Frame.toRpc.ErrorType
|
|
78
|
+
}
|
|
@@ -26,19 +26,19 @@ export type Arbitrary = {
|
|
|
26
26
|
signer?: undefined
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
/** A
|
|
29
|
+
/** A secp256k1 signature entry. */
|
|
30
30
|
export type Secp256k1 = {
|
|
31
31
|
/** Explicit nonzero digest. Omit or use empty bytes for the transaction signing hash. */
|
|
32
32
|
payload?: Hex.Hex | undefined
|
|
33
33
|
/** secp256k1 verification scheme. */
|
|
34
34
|
scheme: 1 | 'secp256k1'
|
|
35
|
-
/** Recovered signature. Omit for an unsigned entry. */
|
|
36
|
-
signature?: Signature.Signature | undefined
|
|
35
|
+
/** Recovered signature or `Signature.toHex` bytes. Omit or use `0x` for an unsigned entry. */
|
|
36
|
+
signature?: Hex.Hex | Signature.Signature | undefined
|
|
37
37
|
/** Signer address. Omit to use the transaction sender. */
|
|
38
38
|
signer?: Address.Address | undefined
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
/** A
|
|
41
|
+
/** A P-256 signature entry. */
|
|
42
42
|
export type P256 = {
|
|
43
43
|
/** Explicit nonzero digest. Omit or use empty bytes for the transaction signing hash. */
|
|
44
44
|
payload?: Hex.Hex | undefined
|
|
@@ -50,14 +50,14 @@ export type P256 = {
|
|
|
50
50
|
| {
|
|
51
51
|
/** Uncompressed P-256 public key. */
|
|
52
52
|
publicKey: PublicKey.PublicKey
|
|
53
|
-
/** P-256 signature. */
|
|
54
|
-
signature: Signature.Signature<false>
|
|
53
|
+
/** P-256 signature or `Signature.toHex` bytes. */
|
|
54
|
+
signature: Hex.Hex | Signature.Signature<false>
|
|
55
55
|
}
|
|
56
56
|
| {
|
|
57
57
|
/** Public key, if already known. Empty wire signatures do not retain it. */
|
|
58
58
|
publicKey?: PublicKey.PublicKey | undefined
|
|
59
|
-
/** Omit for an unsigned entry. */
|
|
60
|
-
signature?: undefined
|
|
59
|
+
/** Omit or use `0x` for an unsigned entry. */
|
|
60
|
+
signature?: '0x' | undefined
|
|
61
61
|
}
|
|
62
62
|
)
|
|
63
63
|
|
|
@@ -67,13 +67,13 @@ export type FrameSignature = Arbitrary | Secp256k1 | P256
|
|
|
67
67
|
/** JSON-RPC representation of a frame signature. */
|
|
68
68
|
export type Rpc = {
|
|
69
69
|
/** Explicit digest, or empty bytes for the transaction signing hash. */
|
|
70
|
-
msg
|
|
70
|
+
msg?: Hex.Hex | undefined
|
|
71
71
|
/** Signature verification scheme. */
|
|
72
|
-
scheme:
|
|
72
|
+
scheme: '0x0' | '0x1' | '0x2'
|
|
73
73
|
/** Encoded signature bytes. */
|
|
74
|
-
signature
|
|
74
|
+
signature?: Hex.Hex | undefined
|
|
75
75
|
/** Signer address; absent for the transaction sender. */
|
|
76
|
-
signer?: Address.Address |
|
|
76
|
+
signer?: Address.Address | '0x' | undefined
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/** RLP-ready signature entry. The payload occupies the specification's `msg` field. */
|
|
@@ -164,24 +164,34 @@ export function assert(
|
|
|
164
164
|
throw new InvalidError('Public key coordinates must fit in 32 bytes.')
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
|
-
if (
|
|
167
|
+
if (
|
|
168
|
+
entry.signature !== undefined &&
|
|
169
|
+
entry.signature !== '0x' &&
|
|
170
|
+
entry.publicKey === undefined
|
|
171
|
+
)
|
|
168
172
|
throw new InvalidError('P-256 signatures require a public key.')
|
|
169
173
|
}
|
|
170
|
-
if (entry.signature === undefined) {
|
|
174
|
+
if (entry.signature === undefined || entry.signature === '0x') {
|
|
171
175
|
if (options.signed) throw new InvalidError('Signature is required.')
|
|
172
176
|
return
|
|
173
177
|
}
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
if (typeof entry.signature === 'string')
|
|
179
|
+
Hex.assert(entry.signature, { strict: true })
|
|
180
|
+
const signature =
|
|
181
|
+
typeof entry.signature === 'string'
|
|
182
|
+
? Signature.fromHex(entry.signature)
|
|
183
|
+
: entry.signature
|
|
184
|
+
Hex.assert(signature.r, { strict: true })
|
|
185
|
+
Hex.assert(signature.s, { strict: true })
|
|
176
186
|
if (
|
|
177
|
-
(scheme === 1 ||
|
|
178
|
-
|
|
179
|
-
|
|
187
|
+
(scheme === 1 || signature.yParity !== undefined) &&
|
|
188
|
+
signature.yParity !== 0 &&
|
|
189
|
+
signature.yParity !== 1
|
|
180
190
|
)
|
|
181
191
|
throw new InvalidError('Signature parity must be 0 or 1.')
|
|
182
|
-
Signature.assert(
|
|
183
|
-
const r = Hex.toBigInt(
|
|
184
|
-
const s = Hex.toBigInt(
|
|
192
|
+
Signature.assert(signature, { recovered: scheme === 1 })
|
|
193
|
+
const r = Hex.toBigInt(signature.r)
|
|
194
|
+
const s = Hex.toBigInt(signature.s)
|
|
185
195
|
const order = scheme === 1 ? secp256k1N : p256N
|
|
186
196
|
if (
|
|
187
197
|
r === 0n ||
|
|
@@ -210,13 +220,15 @@ export declare namespace assert {
|
|
|
210
220
|
| Hex.toBigInt.ErrorType
|
|
211
221
|
| PublicKey.assert.ErrorType
|
|
212
222
|
| Signature.assert.ErrorType
|
|
223
|
+
| Signature.fromHex.ErrorType
|
|
213
224
|
| Errors.GlobalErrorType
|
|
214
225
|
}
|
|
215
226
|
|
|
216
227
|
/**
|
|
217
228
|
* Coerces a value into a {@link ox#FrameSignature.FrameSignature}.
|
|
218
229
|
*
|
|
219
|
-
* Accepts arbitrary signature bytes or a
|
|
230
|
+
* Accepts arbitrary signature bytes or a signature entry. Protocol signatures accept
|
|
231
|
+
* structured objects or `Signature.toHex` bytes. P-256 entries still require a public key. Omitted
|
|
220
232
|
* `scheme` and `payload` default to `'arbitrary'` and `'0x'`, respectively.
|
|
221
233
|
* An empty payload selects the canonical transaction signing hash; an explicit
|
|
222
234
|
* payload must be a nonzero 32-byte digest.
|
|
@@ -340,7 +352,7 @@ export declare namespace from {
|
|
|
340
352
|
*
|
|
341
353
|
* const entry = FrameSignature.fromRpc({
|
|
342
354
|
* msg: '0x',
|
|
343
|
-
* scheme:
|
|
355
|
+
* scheme: '0x0',
|
|
344
356
|
* signature: '0xdeadbeef'
|
|
345
357
|
* })
|
|
346
358
|
* ```
|
|
@@ -350,15 +362,20 @@ export declare namespace from {
|
|
|
350
362
|
*/
|
|
351
363
|
export function fromRpc(entry: Rpc): FrameSignature {
|
|
352
364
|
return fromTuple([
|
|
353
|
-
entry.scheme ===
|
|
365
|
+
entry.scheme === '0x0'
|
|
366
|
+
? '0x'
|
|
367
|
+
: Hex.fromNumber(Hex.toNumber(entry.scheme), { size: 1 }),
|
|
354
368
|
entry.signer ?? '0x',
|
|
355
|
-
entry.msg,
|
|
356
|
-
entry.signature,
|
|
369
|
+
entry.msg ?? '0x',
|
|
370
|
+
entry.signature ?? '0x',
|
|
357
371
|
])
|
|
358
372
|
}
|
|
359
373
|
|
|
360
374
|
export declare namespace fromRpc {
|
|
361
|
-
type ErrorType =
|
|
375
|
+
type ErrorType =
|
|
376
|
+
| fromTuple.ErrorType
|
|
377
|
+
| Hex.fromNumber.ErrorType
|
|
378
|
+
| Hex.toNumber.ErrorType
|
|
362
379
|
}
|
|
363
380
|
|
|
364
381
|
/**
|
|
@@ -381,8 +398,10 @@ export function toRpc(entry: FrameSignature): Rpc {
|
|
|
381
398
|
const [scheme, signer, msg, signature] = toTuple(entry)
|
|
382
399
|
return {
|
|
383
400
|
msg,
|
|
384
|
-
scheme: (scheme === '0x'
|
|
385
|
-
|
|
401
|
+
scheme: (scheme === '0x'
|
|
402
|
+
? '0x0'
|
|
403
|
+
: Hex.fromNumber(Hex.toNumber(scheme))) as Rpc['scheme'],
|
|
404
|
+
...(signature === '0x' && scheme !== '0x' ? {} : { signature }),
|
|
386
405
|
...(signer === '0x' ? {} : { signer }),
|
|
387
406
|
}
|
|
388
407
|
}
|
|
@@ -509,13 +528,24 @@ export function toTuple(entry: FrameSignature): Tuple {
|
|
|
509
528
|
return entry.signature
|
|
510
529
|
case 1:
|
|
511
530
|
case 'secp256k1':
|
|
512
|
-
return entry.signature === undefined
|
|
531
|
+
return entry.signature === undefined || entry.signature === '0x'
|
|
513
532
|
? '0x'
|
|
514
|
-
: Hex.fromBytes(
|
|
533
|
+
: Hex.fromBytes(
|
|
534
|
+
Signature.toRecoveredBytes(
|
|
535
|
+
typeof entry.signature === 'string'
|
|
536
|
+
? Signature.fromHex(entry.signature)
|
|
537
|
+
: entry.signature,
|
|
538
|
+
),
|
|
539
|
+
)
|
|
515
540
|
case 2:
|
|
516
541
|
case 'p256': {
|
|
517
|
-
if (entry.signature === undefined
|
|
518
|
-
|
|
542
|
+
if (entry.signature === undefined || entry.signature === '0x')
|
|
543
|
+
return '0x'
|
|
544
|
+
const publicKey = entry.publicKey!
|
|
545
|
+
const signature =
|
|
546
|
+
typeof entry.signature === 'string'
|
|
547
|
+
? Signature.fromHex(entry.signature)
|
|
548
|
+
: entry.signature
|
|
519
549
|
const s = Hex.toBigInt(signature.s)
|
|
520
550
|
return Hex.concat(
|
|
521
551
|
Hex.fromNumber(Hex.toBigInt(signature.r), { size: 32 }),
|
package/src/core/Siwe.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const prefixRegex =
|
|
|
21
21
|
|
|
22
22
|
// https://regexr.com/80gf9
|
|
23
23
|
export const suffixRegex =
|
|
24
|
-
/(?:URI: (?<uri>.+))\n(?:Version: (?<version>.+))\n(?:Chain ID: (?<chainId>\d+))\n(?:Nonce: (?<nonce>[a-zA-Z0-9]+))\n(?:Issued At: (?<issuedAt>.+))(?:\nExpiration Time: (?<expirationTime>.+))?(?:\nNot Before: (?<notBefore>.+))?(?:\nRequest ID: (?<requestId
|
|
24
|
+
/(?:URI: (?<uri>.+))\n(?:Version: (?<version>.+))\n(?:Chain ID: (?<chainId>\d+))\n(?:Nonce: (?<nonce>[a-zA-Z0-9]+))\n(?:Issued At: (?<issuedAt>.+))(?:\nExpiration Time: (?<expirationTime>.+))?(?:\nNot Before: (?<notBefore>.+))?(?:\nRequest ID: (?<requestId>.*))?(?:\nResources:(?<resources>(?:\n- .+)*))?/
|
|
25
25
|
|
|
26
26
|
const siweDateTimeRegex =
|
|
27
27
|
/^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])[Tt]([01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:[Zz]|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/
|
|
@@ -421,18 +421,26 @@ export function parseMessage(message: string): ExactPartial<Message> {
|
|
|
421
421
|
scheme?: string
|
|
422
422
|
statement?: string
|
|
423
423
|
}
|
|
424
|
-
const {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
424
|
+
const {
|
|
425
|
+
chainId,
|
|
426
|
+
expirationTime,
|
|
427
|
+
issuedAt,
|
|
428
|
+
notBefore,
|
|
429
|
+
requestId,
|
|
430
|
+
resources: resources_,
|
|
431
|
+
...suffix
|
|
432
|
+
} = (message.match(suffixRegex)?.groups ?? {}) as {
|
|
433
|
+
chainId: string
|
|
434
|
+
expirationTime?: string
|
|
435
|
+
issuedAt?: string
|
|
436
|
+
nonce: string
|
|
437
|
+
notBefore?: string
|
|
438
|
+
requestId?: string
|
|
439
|
+
resources?: string
|
|
440
|
+
uri: string
|
|
441
|
+
version: '1'
|
|
442
|
+
}
|
|
443
|
+
const resources = resources_?.split('\n- ').slice(1)
|
|
436
444
|
return {
|
|
437
445
|
...prefix,
|
|
438
446
|
...suffix,
|
package/src/core/Transaction.ts
CHANGED
|
@@ -6,7 +6,12 @@ import * as Frame from './Frame.js'
|
|
|
6
6
|
import * as FrameSignature from './FrameSignature.js'
|
|
7
7
|
import * as Hex from './Hex.js'
|
|
8
8
|
import * as Quantity from './internal/quantity.js'
|
|
9
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
Compute,
|
|
11
|
+
ExactPartial,
|
|
12
|
+
OneOf,
|
|
13
|
+
UnionCompute,
|
|
14
|
+
} from './internal/types.js'
|
|
10
15
|
import * as Signature from './Signature.js'
|
|
11
16
|
|
|
12
17
|
/**
|
|
@@ -197,29 +202,35 @@ export type Eip8141<
|
|
|
197
202
|
> = Compute<
|
|
198
203
|
Omit<
|
|
199
204
|
Base<type, pending, bigintType, numberType>,
|
|
200
|
-
'chainId' | 'r' | 's' | 'v' | 'yParity'
|
|
201
|
-
> &
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
:
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
:
|
|
222
|
-
|
|
205
|
+
'chainId' | 'gas' | 'input' | 'to' | 'value' | 'r' | 's' | 'v' | 'yParity'
|
|
206
|
+
> &
|
|
207
|
+
ExactPartial<
|
|
208
|
+
Pick<
|
|
209
|
+
Base<type, pending, bigintType, numberType>,
|
|
210
|
+
'gas' | 'input' | 'to' | 'value'
|
|
211
|
+
>
|
|
212
|
+
> & {
|
|
213
|
+
/** Versioned blob hashes. */
|
|
214
|
+
blobVersionedHashes: readonly Hex.Hex[]
|
|
215
|
+
/** Chain ID, retaining bigint precision when needed. */
|
|
216
|
+
chainId: numberType | bigintType
|
|
217
|
+
/** Frames in execution order. */
|
|
218
|
+
frames: readonly ([bigintType] extends [Hex.Hex]
|
|
219
|
+
? Frame.Rpc
|
|
220
|
+
: Frame.Frame<bigintType>)[]
|
|
221
|
+
/** Effective gas price. */
|
|
222
|
+
gasPrice?: bigintType | undefined
|
|
223
|
+
/** Maximum fee per blob gas. */
|
|
224
|
+
maxFeePerBlobGas: bigintType
|
|
225
|
+
/** Maximum fee per gas. */
|
|
226
|
+
maxFeePerGas: bigintType
|
|
227
|
+
/** Maximum priority fee per gas. */
|
|
228
|
+
maxPriorityFeePerGas: bigintType
|
|
229
|
+
/** Frame signature entries. */
|
|
230
|
+
signatures: readonly ([bigintType] extends [Hex.Hex]
|
|
231
|
+
? FrameSignature.Rpc
|
|
232
|
+
: FrameSignature.FrameSignature)[]
|
|
233
|
+
}
|
|
223
234
|
>
|
|
224
235
|
|
|
225
236
|
/** An EIP-8141 RPC transaction. */
|
|
@@ -3,7 +3,7 @@ import type * as Address from './Address.js'
|
|
|
3
3
|
import * as Authorization from './Authorization.js'
|
|
4
4
|
import * as Blobs from './Blobs.js'
|
|
5
5
|
import * as Errors from './Errors.js'
|
|
6
|
-
import * as
|
|
6
|
+
import * as FrameRequest from './FrameRequest.js'
|
|
7
7
|
import * as FrameSignature from './FrameSignature.js'
|
|
8
8
|
import * as Hex from './Hex.js'
|
|
9
9
|
import * as Quantity from './internal/quantity.js'
|
|
@@ -19,7 +19,9 @@ export type TransactionRequest<
|
|
|
19
19
|
bigintType = bigint,
|
|
20
20
|
numberType = number,
|
|
21
21
|
type extends string = string,
|
|
22
|
-
frame = [bigintType] extends [Hex.Hex]
|
|
22
|
+
frame = [bigintType] extends [Hex.Hex]
|
|
23
|
+
? FrameRequest.Rpc
|
|
24
|
+
: FrameRequest.FrameRequest<bigintType>,
|
|
23
25
|
signature = [bigintType] extends [Hex.Hex]
|
|
24
26
|
? FrameSignature.Rpc
|
|
25
27
|
: FrameSignature.FrameSignature,
|
|
@@ -79,7 +81,7 @@ export type Rpc = TransactionRequest<
|
|
|
79
81
|
Hex.Hex,
|
|
80
82
|
Hex.Hex,
|
|
81
83
|
string,
|
|
82
|
-
|
|
84
|
+
FrameRequest.Rpc,
|
|
83
85
|
FrameSignature.Rpc
|
|
84
86
|
>
|
|
85
87
|
|
|
@@ -109,7 +111,7 @@ export function fromRpc(request: Rpc): TransactionRequest {
|
|
|
109
111
|
if (typeof request.chainId !== 'undefined')
|
|
110
112
|
request_.chainId = Hex.toNumber(request.chainId)
|
|
111
113
|
if (request.frames !== undefined)
|
|
112
|
-
request_.frames = request.frames.map(
|
|
114
|
+
request_.frames = request.frames.map(FrameRequest.fromRpc)
|
|
113
115
|
if (request.signatures !== undefined)
|
|
114
116
|
request_.signatures = request.signatures.map(FrameSignature.fromRpc)
|
|
115
117
|
if (typeof request.gas !== 'undefined')
|
|
@@ -141,7 +143,7 @@ export function fromRpc(request: Rpc): TransactionRequest {
|
|
|
141
143
|
export declare namespace fromRpc {
|
|
142
144
|
export type ErrorType =
|
|
143
145
|
| Authorization.fromRpcList.ErrorType
|
|
144
|
-
|
|
|
146
|
+
| FrameRequest.fromRpc.ErrorType
|
|
145
147
|
| FrameSignature.fromRpc.ErrorType
|
|
146
148
|
| Hex.toNumber.ErrorType
|
|
147
149
|
| Hex.toBigInt.ErrorType
|
|
@@ -210,7 +212,7 @@ export function toRpc(request: toRpc.Input): Rpc {
|
|
|
210
212
|
request_rpc.input = request.input
|
|
211
213
|
}
|
|
212
214
|
if (request.frames !== undefined)
|
|
213
|
-
request_rpc.frames = request.frames.map(
|
|
215
|
+
request_rpc.frames = request.frames.map(FrameRequest.toRpc)
|
|
214
216
|
if (request.signatures !== undefined)
|
|
215
217
|
request_rpc.signatures = request.signatures.map(FrameSignature.toRpc)
|
|
216
218
|
if (typeof request.from !== 'undefined') request_rpc.from = request.from
|
|
@@ -258,7 +260,7 @@ export declare namespace toRpc {
|
|
|
258
260
|
|
|
259
261
|
export type ErrorType =
|
|
260
262
|
| Authorization.toRpcList.ErrorType
|
|
261
|
-
|
|
|
263
|
+
| FrameRequest.toRpc.ErrorType
|
|
262
264
|
| FrameSignature.toRpc.ErrorType
|
|
263
265
|
| Hex.fromNumber.ErrorType
|
|
264
266
|
| Errors.GlobalErrorType
|
package/src/core/TxEnvelope.ts
CHANGED
|
@@ -242,7 +242,9 @@ export declare namespace deserialize {
|
|
|
242
242
|
*
|
|
243
243
|
* const envelope = TransactionEnvelope.from({
|
|
244
244
|
* chainId: 1,
|
|
245
|
-
* frames: [
|
|
245
|
+
* frames: [
|
|
246
|
+
* Frame.from({ executionGas: 50_000n, mode: 'sender' })
|
|
247
|
+
* ],
|
|
246
248
|
* sender: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8'
|
|
247
249
|
* })
|
|
248
250
|
* ```
|
|
@@ -779,6 +781,12 @@ export function toTransactionRequest(
|
|
|
779
781
|
...rest,
|
|
780
782
|
...(sidecars ? { blobs: sidecars.blobs } : {}),
|
|
781
783
|
chainId: Hex.toNumber(Hex.fromNumber(rest.chainId)),
|
|
784
|
+
// Envelopes commit to zero defaults; request omission would trigger estimation.
|
|
785
|
+
frames: rest.frames.map((frame) => ({
|
|
786
|
+
...frame,
|
|
787
|
+
executionGas: frame.executionGas ?? 0n,
|
|
788
|
+
stateGas: frame.stateGas ?? 0n,
|
|
789
|
+
})),
|
|
782
790
|
from: sender,
|
|
783
791
|
}
|
|
784
792
|
}
|
|
@@ -90,7 +90,7 @@ export type Type = typeof type
|
|
|
90
90
|
*
|
|
91
91
|
* TxEnvelopeEip8141.assert({
|
|
92
92
|
* chainId: 1,
|
|
93
|
-
* frames: [{
|
|
93
|
+
* frames: [{ executionGas: 50_000n, mode: 'verify' }],
|
|
94
94
|
* sender: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8'
|
|
95
95
|
* })
|
|
96
96
|
* ```
|
|
@@ -146,7 +146,7 @@ export function assert(envelope: PartialBy<TxEnvelopeEip8141, 'type'>): void {
|
|
|
146
146
|
}
|
|
147
147
|
if (blobVersionedHashes.length === 0 && maxFeePerBlobGas !== 0n)
|
|
148
148
|
throw new InvalidError('maxFeePerBlobGas must be zero without blobs.')
|
|
149
|
-
let
|
|
149
|
+
let executionGas = 0n
|
|
150
150
|
let stateGas = 0n
|
|
151
151
|
let previousBatch = false
|
|
152
152
|
let expiry = false
|
|
@@ -193,7 +193,7 @@ export function assert(envelope: PartialBy<TxEnvelopeEip8141, 'type'>): void {
|
|
|
193
193
|
throw new InvalidError('Invalid or duplicate expiry verifier frame.')
|
|
194
194
|
expiry = true
|
|
195
195
|
}
|
|
196
|
-
|
|
196
|
+
executionGas += frame.executionGas ?? 0n
|
|
197
197
|
stateGas += frame.stateGas ?? 0n
|
|
198
198
|
count(frame.data ?? '0x')
|
|
199
199
|
if (
|
|
@@ -210,10 +210,10 @@ export function assert(envelope: PartialBy<TxEnvelopeEip8141, 'type'>): void {
|
|
|
210
210
|
count(payload)
|
|
211
211
|
count(signature)
|
|
212
212
|
}
|
|
213
|
-
if (
|
|
213
|
+
if (executionGas + stateGas >= 2n ** 64n)
|
|
214
214
|
throw new InvalidError('Combined frame gas must be less than 2^64.')
|
|
215
215
|
if (
|
|
216
|
-
intrinsic + tokens * 4n +
|
|
216
|
+
intrinsic + tokens * 4n + executionGas > 16_777_216n ||
|
|
217
217
|
intrinsic + size * 64n > 16_777_216n
|
|
218
218
|
)
|
|
219
219
|
throw new InvalidError('Transaction execution gas exceeds 16777216.')
|
|
@@ -337,8 +337,8 @@ export declare namespace deserialize {
|
|
|
337
337
|
* chainId: 1,
|
|
338
338
|
* frames: [
|
|
339
339
|
* {
|
|
340
|
+
* executionGas: 50_000n,
|
|
340
341
|
* flags: 'approveExecutionAndPayment',
|
|
341
|
-
* gas: 50_000n,
|
|
342
342
|
* mode: 'verify'
|
|
343
343
|
* }
|
|
344
344
|
* ],
|
|
@@ -503,8 +503,8 @@ export declare namespace toRpc {
|
|
|
503
503
|
* chainId: 1,
|
|
504
504
|
* frames: [
|
|
505
505
|
* {
|
|
506
|
+
* executionGas: 50_000n,
|
|
506
507
|
* flags: 'approveExecutionAndPayment',
|
|
507
|
-
* gas: 50_000n,
|
|
508
508
|
* mode: 'verify'
|
|
509
509
|
* }
|
|
510
510
|
* ],
|
|
@@ -589,7 +589,7 @@ export declare namespace hash {
|
|
|
589
589
|
*
|
|
590
590
|
* const envelope = TxEnvelopeEip8141.from({
|
|
591
591
|
* chainId: 1,
|
|
592
|
-
* frames: [{
|
|
592
|
+
* frames: [{ executionGas: 50_000n, mode: 'sender' }],
|
|
593
593
|
* sender: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8'
|
|
594
594
|
* })
|
|
595
595
|
* const serialized = TxEnvelopeEip8141.serialize(envelope)
|
|
@@ -4,14 +4,15 @@ import { expectTypeOf, test } from 'vite-plus/test'
|
|
|
4
4
|
test('from preserves literals', () => {
|
|
5
5
|
const frame = Frame.from({
|
|
6
6
|
data: '0x',
|
|
7
|
+
executionGas: 50_000n,
|
|
7
8
|
flags: 3,
|
|
8
|
-
gas: 50_000n,
|
|
9
9
|
mode: 1,
|
|
10
10
|
stateGas: 0n,
|
|
11
11
|
value: 0n,
|
|
12
12
|
})
|
|
13
13
|
expectTypeOf(frame.mode).toEqualTypeOf<1>()
|
|
14
|
-
expectTypeOf(frame.
|
|
14
|
+
expectTypeOf(frame.executionGas).toEqualTypeOf<50_000n>()
|
|
15
|
+
expectTypeOf(frame.stateGas).toEqualTypeOf<0n>()
|
|
15
16
|
expectTypeOf(Frame.toTuple(frame)).toEqualTypeOf<Frame.Tuple>()
|
|
16
17
|
})
|
|
17
18
|
|
|
@@ -31,8 +32,8 @@ test('tuple accepts readonly input', () => {
|
|
|
31
32
|
test('rejects unsupported modes and unsafe numeric budgets', () => {
|
|
32
33
|
Frame.from({
|
|
33
34
|
data: '0x',
|
|
35
|
+
executionGas: 0n,
|
|
34
36
|
flags: 0,
|
|
35
|
-
gas: 0n,
|
|
36
37
|
// @ts-expect-error Unknown mode names are not supported.
|
|
37
38
|
mode: 'unknown',
|
|
38
39
|
stateGas: 0n,
|
|
@@ -40,9 +41,9 @@ test('rejects unsupported modes and unsafe numeric budgets', () => {
|
|
|
40
41
|
})
|
|
41
42
|
Frame.from({
|
|
42
43
|
data: '0x',
|
|
43
|
-
flags: 0,
|
|
44
44
|
// @ts-expect-error Gas budgets use bigint.
|
|
45
|
-
|
|
45
|
+
executionGas: 1,
|
|
46
|
+
flags: 0,
|
|
46
47
|
mode: 1,
|
|
47
48
|
stateGas: 0n,
|
|
48
49
|
value: 0n,
|
|
@@ -52,8 +53,8 @@ test('rejects unsupported modes and unsafe numeric budgets', () => {
|
|
|
52
53
|
test('flags accept numbers and a strict named union', () => {
|
|
53
54
|
const input = {
|
|
54
55
|
data: '0x',
|
|
56
|
+
executionGas: 0n,
|
|
55
57
|
flags: 'approvePayment',
|
|
56
|
-
gas: 0n,
|
|
57
58
|
mode: 1,
|
|
58
59
|
stateGas: 0n,
|
|
59
60
|
value: 0n,
|
|
@@ -74,8 +75,8 @@ test('flags accept numbers and a strict named union', () => {
|
|
|
74
75
|
test('mode accepts numbers and a strict named union', () => {
|
|
75
76
|
const frame = Frame.from({
|
|
76
77
|
data: '0x',
|
|
78
|
+
executionGas: 0n,
|
|
77
79
|
flags: 0,
|
|
78
|
-
gas: 0n,
|
|
79
80
|
mode: 'sender',
|
|
80
81
|
stateGas: 0n,
|
|
81
82
|
value: 1n,
|
|
@@ -95,6 +96,14 @@ test('allows omitted zero fields without widening supplied literals', () => {
|
|
|
95
96
|
).toEqualTypeOf<Frame.Tuple>()
|
|
96
97
|
})
|
|
97
98
|
|
|
99
|
+
test('execution gas is named explicitly', () => {
|
|
100
|
+
const invalid: Frame.Frame = {
|
|
101
|
+
// @ts-expect-error The execution budget is named executionGas.
|
|
102
|
+
gas: 50_000n,
|
|
103
|
+
}
|
|
104
|
+
void invalid
|
|
105
|
+
})
|
|
106
|
+
|
|
98
107
|
test('destination is named to', () => {
|
|
99
108
|
const frame = Frame.from({ to: '0x1111111111111111111111111111111111111111' })
|
|
100
109
|
expectTypeOf(
|