ox 1.8.1 → 1.8.4

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.
Files changed (152) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/core/Frame.d.ts +23 -20
  3. package/dist/core/Frame.d.ts.map +1 -1
  4. package/dist/core/Frame.js +28 -23
  5. package/dist/core/Frame.js.map +1 -1
  6. package/dist/core/FrameReceipt.d.ts +23 -14
  7. package/dist/core/FrameReceipt.d.ts.map +1 -1
  8. package/dist/core/FrameReceipt.js +15 -11
  9. package/dist/core/FrameReceipt.js.map +1 -1
  10. package/dist/core/FrameRequest.d.ts +50 -0
  11. package/dist/core/FrameRequest.d.ts.map +1 -0
  12. package/dist/core/FrameRequest.js +59 -0
  13. package/dist/core/FrameRequest.js.map +1 -0
  14. package/dist/core/FrameSignature.d.ts +17 -16
  15. package/dist/core/FrameSignature.d.ts.map +1 -1
  16. package/dist/core/FrameSignature.js +38 -21
  17. package/dist/core/FrameSignature.js.map +1 -1
  18. package/dist/core/Siwe.d.ts.map +1 -1
  19. package/dist/core/Siwe.js +3 -3
  20. package/dist/core/Siwe.js.map +1 -1
  21. package/dist/core/Transaction.d.ts +7 -4
  22. package/dist/core/Transaction.d.ts.map +1 -1
  23. package/dist/core/Transaction.js +8 -0
  24. package/dist/core/Transaction.js.map +1 -1
  25. package/dist/core/TransactionRequest.d.ts +8 -5
  26. package/dist/core/TransactionRequest.d.ts.map +1 -1
  27. package/dist/core/TransactionRequest.js +11 -3
  28. package/dist/core/TransactionRequest.js.map +1 -1
  29. package/dist/core/TxEnvelope.d.ts +4 -2
  30. package/dist/core/TxEnvelope.d.ts.map +1 -1
  31. package/dist/core/TxEnvelope.js +11 -2
  32. package/dist/core/TxEnvelope.js.map +1 -1
  33. package/dist/core/TxEnvelopeEip8141.d.ts +22 -11
  34. package/dist/core/TxEnvelopeEip8141.d.ts.map +1 -1
  35. package/dist/core/TxEnvelopeEip8141.js +45 -16
  36. package/dist/core/TxEnvelopeEip8141.js.map +1 -1
  37. package/dist/core/internal/frameNonce.d.ts +10 -0
  38. package/dist/core/internal/frameNonce.d.ts.map +1 -0
  39. package/dist/core/internal/frameNonce.js +45 -0
  40. package/dist/core/internal/frameNonce.js.map +1 -0
  41. package/dist/core/internal/rpcSchemas/eth.d.ts +16 -4
  42. package/dist/core/internal/rpcSchemas/eth.d.ts.map +1 -1
  43. package/dist/index.d.ts +21 -5
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +21 -5
  46. package/dist/index.js.map +1 -1
  47. package/dist/zod/Block.d.ts +52 -37
  48. package/dist/zod/Block.d.ts.map +1 -1
  49. package/dist/zod/Frame.d.ts +14 -14
  50. package/dist/zod/Frame.js +5 -5
  51. package/dist/zod/Frame.js.map +1 -1
  52. package/dist/zod/FrameReceipt.d.ts +42 -2
  53. package/dist/zod/FrameReceipt.d.ts.map +1 -1
  54. package/dist/zod/FrameReceipt.js +11 -1
  55. package/dist/zod/FrameReceipt.js.map +1 -1
  56. package/dist/zod/FrameRequest.d.ts +40 -0
  57. package/dist/zod/FrameRequest.d.ts.map +1 -0
  58. package/dist/zod/FrameRequest.js +37 -0
  59. package/dist/zod/FrameRequest.js.map +1 -0
  60. package/dist/zod/FrameSignature.d.ts +21 -13
  61. package/dist/zod/FrameSignature.d.ts.map +1 -1
  62. package/dist/zod/FrameSignature.js +10 -7
  63. package/dist/zod/FrameSignature.js.map +1 -1
  64. package/dist/zod/RpcSchema.d.ts +470 -265
  65. package/dist/zod/RpcSchema.d.ts.map +1 -1
  66. package/dist/zod/Transaction.d.ts +104 -74
  67. package/dist/zod/Transaction.d.ts.map +1 -1
  68. package/dist/zod/Transaction.js +22 -15
  69. package/dist/zod/Transaction.js.map +1 -1
  70. package/dist/zod/TransactionEnvelope.d.ts +60 -34
  71. package/dist/zod/TransactionEnvelope.d.ts.map +1 -1
  72. package/dist/zod/TransactionReceipt.d.ts +42 -2
  73. package/dist/zod/TransactionReceipt.d.ts.map +1 -1
  74. package/dist/zod/TransactionRequest.d.ts +31 -21
  75. package/dist/zod/TransactionRequest.d.ts.map +1 -1
  76. package/dist/zod/TransactionRequest.js +10 -4
  77. package/dist/zod/TransactionRequest.js.map +1 -1
  78. package/dist/zod/TxEnvelopeEip8141.d.ts +44 -25
  79. package/dist/zod/TxEnvelopeEip8141.d.ts.map +1 -1
  80. package/dist/zod/TxEnvelopeEip8141.js +2 -0
  81. package/dist/zod/TxEnvelopeEip8141.js.map +1 -1
  82. package/dist/zod/internal/Frame.d.ts +8 -0
  83. package/dist/zod/internal/Frame.d.ts.map +1 -1
  84. package/dist/zod/internal/Frame.js +29 -0
  85. package/dist/zod/internal/Frame.js.map +1 -1
  86. package/dist/zod/internal/rpcSchemas/Eth.d.ts +472 -267
  87. package/dist/zod/internal/rpcSchemas/Eth.d.ts.map +1 -1
  88. package/dist/zod/internal/rpcSchemas/Eth.js +9 -0
  89. package/dist/zod/internal/rpcSchemas/Eth.js.map +1 -1
  90. package/dist/zod/internal/rpcSchemas/Wallet.d.ts +51 -21
  91. package/dist/zod/internal/rpcSchemas/Wallet.d.ts.map +1 -1
  92. package/dist/zod/tempo/RpcSchemaTempo.d.ts +68 -48
  93. package/dist/zod/tempo/RpcSchemaTempo.d.ts.map +1 -1
  94. package/dist/zod/tempo/Transaction.d.ts +52 -37
  95. package/dist/zod/tempo/Transaction.d.ts.map +1 -1
  96. package/dist/zod/z.d.ts +1 -0
  97. package/dist/zod/z.d.ts.map +1 -1
  98. package/dist/zod/z.js +1 -0
  99. package/dist/zod/z.js.map +1 -1
  100. package/package.json +11 -1
  101. package/src/core/Frame.ts +41 -33
  102. package/src/core/FrameReceipt.ts +30 -16
  103. package/src/core/FrameRequest.ts +78 -0
  104. package/src/core/FrameSignature.ts +64 -34
  105. package/src/core/Siwe.ts +21 -13
  106. package/src/core/Transaction.ts +52 -24
  107. package/src/core/TransactionRequest.ts +21 -7
  108. package/src/core/TxEnvelope.ts +16 -3
  109. package/src/core/TxEnvelopeEip8141.ts +69 -21
  110. package/src/core/_test/AbiConstructor.test.ts +2 -0
  111. package/src/core/_test/Frame.test-d.ts +16 -7
  112. package/src/core/_test/Frame.test.ts +52 -24
  113. package/src/core/_test/FrameReceipt.test.ts +15 -9
  114. package/src/core/_test/FrameRequest.test-d.ts +16 -0
  115. package/src/core/_test/FrameRequest.test.ts +41 -0
  116. package/src/core/_test/FrameRpc.test.ts +131 -0
  117. package/src/core/_test/FrameSignature.test-d.ts +20 -0
  118. package/src/core/_test/FrameSignature.test.ts +132 -11
  119. package/src/core/_test/RpcSchema.test-d.ts +45 -0
  120. package/src/core/_test/Siwe.test.ts +147 -0
  121. package/src/core/_test/TransactionEnvelope.test-d.ts +27 -0
  122. package/src/core/_test/TransactionEnvelope.test.ts +27 -1
  123. package/src/core/_test/TransactionReceipt.test.ts +32 -6
  124. package/src/core/_test/TransactionRequest.test-d.ts +10 -1
  125. package/src/core/_test/TransactionRequest.test.ts +31 -2
  126. package/src/core/_test/TxEnvelopeEip8141.test-d.ts +29 -2
  127. package/src/core/_test/TxEnvelopeEip8141.test.ts +548 -55
  128. package/src/core/_test/index.test.ts +1 -0
  129. package/src/core/internal/frameNonce.ts +61 -0
  130. package/src/core/internal/rpcSchemas/eth.ts +13 -4
  131. package/src/index.ts +22 -5
  132. package/src/version.ts +1 -1
  133. package/src/zod/Frame.ts +5 -5
  134. package/src/zod/FrameReceipt.ts +11 -1
  135. package/src/zod/FrameRequest.ts +46 -0
  136. package/src/zod/FrameSignature.ts +10 -7
  137. package/src/zod/Transaction.ts +46 -27
  138. package/src/zod/TransactionRequest.ts +33 -18
  139. package/src/zod/TxEnvelopeEip8141.ts +2 -0
  140. package/src/zod/_test/Frame.test.ts +13 -11
  141. package/src/zod/_test/FrameReceipt.test.ts +11 -4
  142. package/src/zod/_test/FrameRequest.test-d.ts +15 -0
  143. package/src/zod/_test/FrameRequest.test.ts +44 -0
  144. package/src/zod/_test/FrameSignature.test.ts +73 -9
  145. package/src/zod/_test/RpcSchema.test.ts +106 -0
  146. package/src/zod/_test/TransactionRequest.test.ts +61 -0
  147. package/src/zod/_test/TxEnvelopeEip8141.nonce.test.ts +174 -0
  148. package/src/zod/_test/TxEnvelopeEip8141.test-d.ts +29 -0
  149. package/src/zod/_test/TxEnvelopeEip8141.test.ts +3 -3
  150. package/src/zod/internal/Frame.ts +45 -0
  151. package/src/zod/internal/rpcSchemas/Eth.ts +20 -0
  152. 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 structured secp256k1 signature entry. */
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 structured P-256 signature entry. */
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: Hex.Hex
70
+ msg?: Hex.Hex | undefined
71
71
  /** Signature verification scheme. */
72
- scheme: 0 | 1 | 2
72
+ scheme: '0x0' | '0x1' | '0x2'
73
73
  /** Encoded signature bytes. */
74
- signature: Hex.Hex
74
+ signature?: Hex.Hex | undefined
75
75
  /** Signer address; absent for the transaction sender. */
76
- signer?: Address.Address | null | undefined
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 (entry.signature !== undefined && entry.publicKey === undefined)
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
- Hex.assert(entry.signature.r, { strict: true })
175
- Hex.assert(entry.signature.s, { strict: true })
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 || entry.signature.yParity !== undefined) &&
178
- entry.signature.yParity !== 0 &&
179
- entry.signature.yParity !== 1
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(entry.signature, { recovered: scheme === 1 })
183
- const r = Hex.toBigInt(entry.signature.r)
184
- const s = Hex.toBigInt(entry.signature.s)
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 structured signature entry. Omitted
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: 0,
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 === 0 ? '0x' : Hex.fromNumber(entry.scheme, { size: 1 }),
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 = fromTuple.ErrorType | Hex.fromNumber.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' ? 0 : Hex.toNumber(scheme)) as Rpc['scheme'],
385
- signature,
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(Signature.toRecoveredBytes(entry.signature))
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) return '0x'
518
- const { publicKey, signature } = entry
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 { chainId, expirationTime, issuedAt, notBefore, requestId, ...suffix } =
425
- (message.match(suffixRegex)?.groups ?? {}) as {
426
- chainId: string
427
- expirationTime?: string
428
- issuedAt?: string
429
- nonce: string
430
- notBefore?: string
431
- requestId?: string
432
- uri: string
433
- version: '1'
434
- }
435
- const resources = message.split('Resources:')[1]?.split('\n- ').slice(1)
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,
@@ -5,8 +5,14 @@ import type * as Errors from './Errors.js'
5
5
  import * as Frame from './Frame.js'
6
6
  import * as FrameSignature from './FrameSignature.js'
7
7
  import * as Hex from './Hex.js'
8
+ import * as FrameNonce from './internal/frameNonce.js'
8
9
  import * as Quantity from './internal/quantity.js'
9
- import type { Compute, OneOf, UnionCompute } from './internal/types.js'
10
+ import type {
11
+ Compute,
12
+ ExactPartial,
13
+ OneOf,
14
+ UnionCompute,
15
+ } from './internal/types.js'
10
16
  import * as Signature from './Signature.js'
11
17
 
12
18
  /**
@@ -197,29 +203,37 @@ export type Eip8141<
197
203
  > = Compute<
198
204
  Omit<
199
205
  Base<type, pending, bigintType, numberType>,
200
- 'chainId' | 'r' | 's' | 'v' | 'yParity'
201
- > & {
202
- /** Versioned blob hashes. */
203
- blobVersionedHashes: readonly Hex.Hex[]
204
- /** Chain ID, retaining bigint precision when needed. */
205
- chainId: numberType | bigintType
206
- /** Frames in execution order. */
207
- frames: readonly ([bigintType] extends [Hex.Hex]
208
- ? Frame.Rpc
209
- : Frame.Frame<bigintType>)[]
210
- /** Effective gas price. */
211
- gasPrice?: bigintType | undefined
212
- /** Maximum fee per blob gas. */
213
- maxFeePerBlobGas: bigintType
214
- /** Maximum fee per gas. */
215
- maxFeePerGas: bigintType
216
- /** Maximum priority fee per gas. */
217
- maxPriorityFeePerGas: bigintType
218
- /** Frame signature entries. */
219
- signatures: readonly ([bigintType] extends [Hex.Hex]
220
- ? FrameSignature.Rpc
221
- : FrameSignature.FrameSignature)[]
222
- }
206
+ 'chainId' | 'gas' | 'input' | 'to' | 'value' | 'r' | 's' | 'v' | 'yParity'
207
+ > &
208
+ ExactPartial<
209
+ Pick<
210
+ Base<type, pending, bigintType, numberType>,
211
+ 'gas' | 'input' | 'to' | 'value'
212
+ >
213
+ > & {
214
+ /** Versioned blob hashes. */
215
+ blobVersionedHashes: readonly Hex.Hex[]
216
+ /** Chain ID, retaining bigint precision when needed. */
217
+ chainId: numberType | bigintType
218
+ /** Frames in execution order. */
219
+ frames: readonly ([bigintType] extends [Hex.Hex]
220
+ ? Frame.Rpc
221
+ : Frame.Frame<bigintType>)[]
222
+ /** Effective gas price. */
223
+ gasPrice?: bigintType | undefined
224
+ /** Maximum fee per blob gas. */
225
+ maxFeePerBlobGas: bigintType
226
+ /** Maximum fee per gas. */
227
+ maxFeePerGas: bigintType
228
+ /** Maximum priority fee per gas. */
229
+ maxPriorityFeePerGas: bigintType
230
+ /** EIP-8250 domains sharing the transaction's `nonce` sequence. */
231
+ nonceKeys?: readonly bigintType[] | undefined
232
+ /** Frame signature entries. */
233
+ signatures: readonly ([bigintType] extends [Hex.Hex]
234
+ ? FrameSignature.Rpc
235
+ : FrameSignature.FrameSignature)[]
236
+ }
223
237
  >
224
238
 
225
239
  /** An EIP-8141 RPC transaction. */
@@ -366,6 +380,16 @@ export function fromRpc<
366
380
  ? chainId
367
381
  : Number(chainId)
368
382
  }
383
+ if (transaction.type === '0x6' && transaction.nonceKeys !== undefined) {
384
+ if (transaction.nonce === undefined)
385
+ throw new FrameNonce.InvalidError(
386
+ 'A keyed transaction result requires nonce.',
387
+ )
388
+ transaction_.nonceKeys = FrameNonce.fromRpc(
389
+ transaction.nonceKeys,
390
+ transaction.nonce,
391
+ )
392
+ }
369
393
  if (transaction.type === '0x6' && transaction.frames) {
370
394
  transaction_.frames = transaction.frames.map(Frame.fromRpc)
371
395
  transaction_.signatures = (transaction.signatures ?? []).map(
@@ -402,6 +426,7 @@ export declare namespace fromRpc {
402
426
 
403
427
  type ErrorType =
404
428
  | Signature.extract.ErrorType
429
+ | FrameNonce.InvalidError
405
430
  | Frame.fromRpc.ErrorType
406
431
  | FrameSignature.fromRpc.ErrorType
407
432
  | Errors.GlobalErrorType
@@ -469,6 +494,8 @@ export function toRpc<pending extends boolean = false>(
469
494
  rpc.type = (toRpcType as any)[transaction.type] ?? transaction.type
470
495
  rpc.value = Quantity.fromNumberish(transaction.value ?? 0n)
471
496
 
497
+ if (transaction.type === 'eip8141' && transaction.nonceKeys !== undefined)
498
+ rpc.nonceKeys = FrameNonce.toRpc(transaction.nonceKeys, transaction.nonce)
472
499
  if (transaction.type === 'eip8141' && transaction.frames) {
473
500
  rpc.frames = transaction.frames.map(Frame.toRpc)
474
501
  rpc.signatures = transaction.signatures.map(FrameSignature.toRpc)
@@ -516,6 +543,7 @@ export declare namespace toRpc {
516
543
 
517
544
  type ErrorType =
518
545
  | Signature.extract.ErrorType
546
+ | FrameNonce.InvalidError
519
547
  | Frame.toRpc.ErrorType
520
548
  | FrameSignature.toRpc.ErrorType
521
549
  | Errors.GlobalErrorType
@@ -3,9 +3,10 @@ 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 Frame from './Frame.js'
6
+ import * as FrameRequest from './FrameRequest.js'
7
7
  import * as FrameSignature from './FrameSignature.js'
8
8
  import * as Hex from './Hex.js'
9
+ import * as FrameNonce from './internal/frameNonce.js'
9
10
  import * as Quantity from './internal/quantity.js'
10
11
  import type { Compute } from './internal/types.js'
11
12
  import type * as Kzg from './Kzg.js'
@@ -19,7 +20,9 @@ export type TransactionRequest<
19
20
  bigintType = bigint,
20
21
  numberType = number,
21
22
  type extends string = string,
22
- frame = [bigintType] extends [Hex.Hex] ? Frame.Rpc : Frame.Frame<bigintType>,
23
+ frame = [bigintType] extends [Hex.Hex]
24
+ ? FrameRequest.Rpc
25
+ : FrameRequest.FrameRequest<bigintType>,
23
26
  signature = [bigintType] extends [Hex.Hex]
24
27
  ? FrameSignature.Rpc
25
28
  : FrameSignature.FrameSignature,
@@ -56,6 +59,8 @@ export type TransactionRequest<
56
59
  maxPriorityFeePerGas?: bigintType | undefined
57
60
  /** Unique number identifying this transaction */
58
61
  nonce?: bigintType | undefined
62
+ /** EIP-8250 nonce domains. `nonce` is their shared sequence; omitted keys preserve EIP-8141 encoding. */
63
+ nonceKeys?: readonly bigintType[] | undefined
59
64
  /** Frame signature entries for EIP-8141 transactions. */
60
65
  signatures?: readonly signature[] | undefined
61
66
  /** Transaction recipient */
@@ -79,7 +84,7 @@ export type Rpc = TransactionRequest<
79
84
  Hex.Hex,
80
85
  Hex.Hex,
81
86
  string,
82
- Frame.Rpc,
87
+ FrameRequest.Rpc,
83
88
  FrameSignature.Rpc
84
89
  >
85
90
 
@@ -109,7 +114,7 @@ export function fromRpc(request: Rpc): TransactionRequest {
109
114
  if (typeof request.chainId !== 'undefined')
110
115
  request_.chainId = Hex.toNumber(request.chainId)
111
116
  if (request.frames !== undefined)
112
- request_.frames = request.frames.map(Frame.fromRpc)
117
+ request_.frames = request.frames.map(FrameRequest.fromRpc)
113
118
  if (request.signatures !== undefined)
114
119
  request_.signatures = request.signatures.map(FrameSignature.fromRpc)
115
120
  if (typeof request.gas !== 'undefined')
@@ -124,6 +129,8 @@ export function fromRpc(request: Rpc): TransactionRequest {
124
129
  request_.maxPriorityFeePerGas = Hex.toBigInt(request.maxPriorityFeePerGas)
125
130
  if (typeof request.nonce !== 'undefined')
126
131
  request_.nonce = Hex.toBigInt(request.nonce)
132
+ if (request.nonceKeys !== undefined)
133
+ request_.nonceKeys = FrameNonce.fromRpc(request.nonceKeys, request.nonce)
127
134
  if (typeof request.type !== 'undefined')
128
135
  request_.type =
129
136
  Transaction.fromRpcType[
@@ -141,7 +148,8 @@ export function fromRpc(request: Rpc): TransactionRequest {
141
148
  export declare namespace fromRpc {
142
149
  export type ErrorType =
143
150
  | Authorization.fromRpcList.ErrorType
144
- | Frame.fromRpc.ErrorType
151
+ | FrameNonce.InvalidError
152
+ | FrameRequest.fromRpc.ErrorType
145
153
  | FrameSignature.fromRpc.ErrorType
146
154
  | Hex.toNumber.ErrorType
147
155
  | Hex.toBigInt.ErrorType
@@ -210,7 +218,7 @@ export function toRpc(request: toRpc.Input): Rpc {
210
218
  request_rpc.input = request.input
211
219
  }
212
220
  if (request.frames !== undefined)
213
- request_rpc.frames = request.frames.map(Frame.toRpc)
221
+ request_rpc.frames = request.frames.map(FrameRequest.toRpc)
214
222
  if (request.signatures !== undefined)
215
223
  request_rpc.signatures = request.signatures.map(FrameSignature.toRpc)
216
224
  if (typeof request.from !== 'undefined') request_rpc.from = request.from
@@ -230,6 +238,8 @@ export function toRpc(request: toRpc.Input): Rpc {
230
238
  )
231
239
  if (typeof request.nonce !== 'undefined')
232
240
  request_rpc.nonce = Quantity.fromNumberish(request.nonce)
241
+ if (request.nonceKeys !== undefined)
242
+ request_rpc.nonceKeys = FrameNonce.toRpc(request.nonceKeys, request.nonce)
233
243
  if (typeof request.to !== 'undefined') request_rpc.to = request.to
234
244
  if (typeof request.type !== 'undefined')
235
245
  request_rpc.type =
@@ -258,7 +268,8 @@ export declare namespace toRpc {
258
268
 
259
269
  export type ErrorType =
260
270
  | Authorization.toRpcList.ErrorType
261
- | Frame.toRpc.ErrorType
271
+ | FrameNonce.InvalidError
272
+ | FrameRequest.toRpc.ErrorType
262
273
  | FrameSignature.toRpc.ErrorType
263
274
  | Hex.fromNumber.ErrorType
264
275
  | Errors.GlobalErrorType
@@ -400,6 +411,9 @@ export function toEnvelope(
400
411
  maxFeePerGas: request.maxFeePerGas,
401
412
  maxPriorityFeePerGas: request.maxPriorityFeePerGas,
402
413
  nonce: request.nonce,
414
+ ...(request.nonceKeys !== undefined
415
+ ? { nonceKeys: request.nonceKeys }
416
+ : {}),
403
417
  sender: request.from,
404
418
  sidecars,
405
419
  signatures: request.signatures,
@@ -242,7 +242,9 @@ export declare namespace deserialize {
242
242
  *
243
243
  * const envelope = TransactionEnvelope.from({
244
244
  * chainId: 1,
245
- * frames: [Frame.from({ gas: 50_000n, mode: 'sender' })],
245
+ * frames: [
246
+ * Frame.from({ executionGas: 50_000n, mode: 'sender' })
247
+ * ],
246
248
  * sender: '0x70997970c51812dc3a010c7d01b50e0d17dc79c8'
247
249
  * })
248
250
  * ```
@@ -410,7 +412,10 @@ export function getType<const envelope extends Typeable>(
410
412
  return type as never
411
413
  }
412
414
 
413
- if ('frames' in envelope && envelope.frames !== undefined)
415
+ if (
416
+ ('frames' in envelope && envelope.frames !== undefined) ||
417
+ ('nonceKeys' in envelope && envelope.nonceKeys !== undefined)
418
+ )
414
419
  return 'eip8141' as never
415
420
  if (
416
421
  'authorizationList' in envelope &&
@@ -444,7 +449,9 @@ export declare namespace getType {
444
449
  type: infer type extends string
445
450
  }
446
451
  ? type
447
- : HasDefined<envelope, 'frames'> extends true
452
+ : true extends
453
+ | HasDefined<envelope, 'frames'>
454
+ | HasDefined<envelope, 'nonceKeys'>
448
455
  ? TxEnvelopeEip8141.Type
449
456
  : HasDefined<envelope, 'authorizationList'> extends true
450
457
  ? TxEnvelopeEip7702.Type
@@ -779,6 +786,12 @@ export function toTransactionRequest(
779
786
  ...rest,
780
787
  ...(sidecars ? { blobs: sidecars.blobs } : {}),
781
788
  chainId: Hex.toNumber(Hex.fromNumber(rest.chainId)),
789
+ // Envelopes commit to zero defaults; request omission would trigger estimation.
790
+ frames: rest.frames.map((frame) => ({
791
+ ...frame,
792
+ executionGas: frame.executionGas ?? 0n,
793
+ stateGas: frame.stateGas ?? 0n,
794
+ })),
782
795
  from: sender,
783
796
  }
784
797
  }