ox 1.7.5 → 1.8.1
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 +16 -0
- package/dist/core/Frame.d.ts +290 -0
- package/dist/core/Frame.d.ts.map +1 -0
- package/dist/core/Frame.js +306 -0
- package/dist/core/Frame.js.map +1 -0
- package/dist/core/FrameReceipt.d.ts +92 -0
- package/dist/core/FrameReceipt.d.ts.map +1 -0
- package/dist/core/FrameReceipt.js +72 -0
- package/dist/core/FrameReceipt.js.map +1 -0
- package/dist/core/FrameSignature.d.ts +357 -0
- package/dist/core/FrameSignature.d.ts.map +1 -0
- package/dist/core/FrameSignature.js +411 -0
- package/dist/core/FrameSignature.js.map +1 -0
- package/dist/core/Transaction.d.ts +29 -4
- package/dist/core/Transaction.d.ts.map +1 -1
- package/dist/core/Transaction.js +25 -4
- package/dist/core/Transaction.js.map +1 -1
- package/dist/core/TransactionReceipt.d.ts +13 -4
- package/dist/core/TransactionReceipt.d.ts.map +1 -1
- package/dist/core/TransactionReceipt.js +14 -0
- package/dist/core/TransactionReceipt.js.map +1 -1
- package/dist/core/TransactionRequest.d.ts +15 -7
- package/dist/core/TransactionRequest.d.ts.map +1 -1
- package/dist/core/TransactionRequest.js +47 -1
- package/dist/core/TransactionRequest.js.map +1 -1
- package/dist/core/TxEnvelope.d.ts +35 -21
- package/dist/core/TxEnvelope.d.ts.map +1 -1
- package/dist/core/TxEnvelope.js +46 -6
- package/dist/core/TxEnvelope.js.map +1 -1
- package/dist/core/TxEnvelopeEip8141.d.ts +341 -0
- package/dist/core/TxEnvelopeEip8141.d.ts.map +1 -0
- package/dist/core/TxEnvelopeEip8141.js +484 -0
- package/dist/core/TxEnvelopeEip8141.js.map +1 -0
- package/dist/core/internal/curves.d.ts +2 -0
- package/dist/core/internal/curves.d.ts.map +1 -1
- package/dist/core/internal/curves.js +2 -0
- package/dist/core/internal/curves.js.map +1 -1
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -1
- package/dist/tempo/Transaction.d.ts +2 -0
- package/dist/tempo/Transaction.d.ts.map +1 -1
- package/dist/tempo/TransactionReceipt.d.ts +2 -0
- package/dist/tempo/TransactionReceipt.d.ts.map +1 -1
- package/dist/zod/Block.d.ts +123 -0
- package/dist/zod/Block.d.ts.map +1 -1
- package/dist/zod/Frame.d.ts +73 -0
- package/dist/zod/Frame.d.ts.map +1 -0
- package/dist/zod/Frame.js +74 -0
- package/dist/zod/Frame.js.map +1 -0
- package/dist/zod/FrameReceipt.d.ts +50 -0
- package/dist/zod/FrameReceipt.d.ts.map +1 -0
- package/dist/zod/FrameReceipt.js +37 -0
- package/dist/zod/FrameReceipt.js.map +1 -0
- package/dist/zod/FrameSignature.d.ts +63 -0
- package/dist/zod/FrameSignature.d.ts.map +1 -0
- package/dist/zod/FrameSignature.js +66 -0
- package/dist/zod/FrameSignature.js.map +1 -0
- package/dist/zod/RpcSchema.d.ts +806 -11
- package/dist/zod/RpcSchema.d.ts.map +1 -1
- package/dist/zod/Transaction.d.ts +252 -0
- package/dist/zod/Transaction.d.ts.map +1 -1
- package/dist/zod/Transaction.js +54 -0
- package/dist/zod/Transaction.js.map +1 -1
- package/dist/zod/TransactionEnvelope.d.ts +233 -4
- package/dist/zod/TransactionEnvelope.d.ts.map +1 -1
- package/dist/zod/TransactionEnvelope.js +9 -0
- package/dist/zod/TransactionEnvelope.js.map +1 -1
- package/dist/zod/TransactionReceipt.d.ts +48 -0
- package/dist/zod/TransactionReceipt.d.ts.map +1 -1
- package/dist/zod/TransactionReceipt.js +8 -3
- package/dist/zod/TransactionReceipt.js.map +1 -1
- package/dist/zod/TransactionRequest.d.ts +50 -2
- package/dist/zod/TransactionRequest.d.ts.map +1 -1
- package/dist/zod/TransactionRequest.js +10 -4
- package/dist/zod/TransactionRequest.js.map +1 -1
- package/dist/zod/TxEnvelopeEip8141.d.ts +166 -0
- package/dist/zod/TxEnvelopeEip8141.d.ts.map +1 -0
- package/dist/zod/TxEnvelopeEip8141.js +76 -0
- package/dist/zod/TxEnvelopeEip8141.js.map +1 -0
- package/dist/zod/internal/Frame.d.ts +4 -0
- package/dist/zod/internal/Frame.d.ts.map +1 -0
- package/dist/zod/internal/Frame.js +17 -0
- package/dist/zod/internal/Frame.js.map +1 -0
- package/dist/zod/internal/rpcSchemas/Eth.d.ts +842 -11
- package/dist/zod/internal/rpcSchemas/Eth.d.ts.map +1 -1
- package/dist/zod/internal/rpcSchemas/Wallet.d.ts +56 -2
- package/dist/zod/internal/rpcSchemas/Wallet.d.ts.map +1 -1
- package/dist/zod/tempo/RpcSchemaTempo.d.ts +140 -0
- package/dist/zod/tempo/RpcSchemaTempo.d.ts.map +1 -1
- package/dist/zod/tempo/Transaction.d.ts +123 -0
- package/dist/zod/tempo/Transaction.d.ts.map +1 -1
- package/dist/zod/z.d.ts +4 -0
- package/dist/zod/z.d.ts.map +1 -1
- package/dist/zod/z.js +4 -0
- package/dist/zod/z.js.map +1 -1
- package/package.json +41 -1
- package/src/core/Frame.ts +442 -0
- package/src/core/FrameReceipt.ts +117 -0
- package/src/core/FrameSignature.ts +593 -0
- package/src/core/Transaction.ts +82 -5
- package/src/core/TransactionReceipt.ts +41 -3
- package/src/core/TransactionRequest.ts +71 -4
- package/src/core/TxEnvelope.ts +159 -90
- package/src/core/TxEnvelopeEip8141.ts +714 -0
- package/src/core/_test/Frame.test-d.ts +108 -0
- package/src/core/_test/Frame.test.ts +280 -0
- package/src/core/_test/FrameReceipt.test.ts +86 -0
- package/src/core/_test/FrameSignature.test-d.ts +93 -0
- package/src/core/_test/FrameSignature.test.ts +554 -0
- package/src/core/_test/Transaction.test.ts +33 -0
- package/src/core/_test/TransactionEnvelope.test-d.ts +74 -0
- package/src/core/_test/TransactionEnvelope.test.ts +107 -0
- package/src/core/_test/TransactionReceipt.test.ts +59 -0
- package/src/core/_test/TransactionRequest.test-d.ts +50 -0
- package/src/core/_test/TransactionRequest.test.ts +88 -1
- package/src/core/_test/TxEnvelopeEip8141.test-d.ts +44 -0
- package/src/core/_test/TxEnvelopeEip8141.test.ts +1775 -0
- package/src/core/_test/curves.test.ts +6 -1
- package/src/core/_test/index.test.ts +4 -0
- package/src/core/internal/curves.ts +4 -0
- package/src/index.ts +77 -0
- package/src/version.ts +1 -1
- package/src/zod/Frame.ts +82 -0
- package/src/zod/FrameReceipt.ts +48 -0
- package/src/zod/FrameSignature.ts +78 -0
- package/src/zod/Transaction.ts +63 -0
- package/src/zod/TransactionEnvelope.ts +33 -0
- package/src/zod/TransactionReceipt.ts +14 -3
- package/src/zod/TransactionRequest.ts +18 -3
- package/src/zod/TxEnvelopeEip8141.ts +102 -0
- package/src/zod/_test/Frame.test-d.ts +41 -0
- package/src/zod/_test/Frame.test.ts +57 -0
- package/src/zod/_test/FrameReceipt.test.ts +75 -0
- package/src/zod/_test/FrameSignature.test.ts +94 -0
- package/src/zod/_test/TxEnvelopeEip8141.test.ts +116 -0
- package/src/zod/internal/Frame.ts +26 -0
- package/src/zod/z.ts +4 -0
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "ox",
|
|
3
3
|
"description": "Ethereum Standard Library",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.8.1",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"sideEffects": false,
|
|
8
8
|
"license": "MIT",
|
|
@@ -249,6 +249,21 @@
|
|
|
249
249
|
"types": "./dist/core/Filter.d.ts",
|
|
250
250
|
"default": "./dist/core/Filter.js"
|
|
251
251
|
},
|
|
252
|
+
"./Frame": {
|
|
253
|
+
"src": "./src/core/Frame.ts",
|
|
254
|
+
"types": "./dist/core/Frame.d.ts",
|
|
255
|
+
"default": "./dist/core/Frame.js"
|
|
256
|
+
},
|
|
257
|
+
"./FrameReceipt": {
|
|
258
|
+
"src": "./src/core/FrameReceipt.ts",
|
|
259
|
+
"types": "./dist/core/FrameReceipt.d.ts",
|
|
260
|
+
"default": "./dist/core/FrameReceipt.js"
|
|
261
|
+
},
|
|
262
|
+
"./FrameSignature": {
|
|
263
|
+
"src": "./src/core/FrameSignature.ts",
|
|
264
|
+
"types": "./dist/core/FrameSignature.d.ts",
|
|
265
|
+
"default": "./dist/core/FrameSignature.js"
|
|
266
|
+
},
|
|
252
267
|
"./Hash": {
|
|
253
268
|
"src": "./src/core/Hash.ts",
|
|
254
269
|
"types": "./dist/core/Hash.d.ts",
|
|
@@ -409,6 +424,11 @@
|
|
|
409
424
|
"types": "./dist/core/TxEnvelopeEip7702.d.ts",
|
|
410
425
|
"default": "./dist/core/TxEnvelopeEip7702.js"
|
|
411
426
|
},
|
|
427
|
+
"./TxEnvelopeEip8141": {
|
|
428
|
+
"src": "./src/core/TxEnvelopeEip8141.ts",
|
|
429
|
+
"types": "./dist/core/TxEnvelopeEip8141.d.ts",
|
|
430
|
+
"default": "./dist/core/TxEnvelopeEip8141.js"
|
|
431
|
+
},
|
|
412
432
|
"./TxEnvelopeLegacy": {
|
|
413
433
|
"src": "./src/core/TxEnvelopeLegacy.ts",
|
|
414
434
|
"types": "./dist/core/TxEnvelopeLegacy.d.ts",
|
|
@@ -894,6 +914,21 @@
|
|
|
894
914
|
"types": "./dist/zod/Filter.d.ts",
|
|
895
915
|
"default": "./dist/zod/Filter.js"
|
|
896
916
|
},
|
|
917
|
+
"./zod/Frame": {
|
|
918
|
+
"src": "./src/zod/Frame.ts",
|
|
919
|
+
"types": "./dist/zod/Frame.d.ts",
|
|
920
|
+
"default": "./dist/zod/Frame.js"
|
|
921
|
+
},
|
|
922
|
+
"./zod/FrameReceipt": {
|
|
923
|
+
"src": "./src/zod/FrameReceipt.ts",
|
|
924
|
+
"types": "./dist/zod/FrameReceipt.d.ts",
|
|
925
|
+
"default": "./dist/zod/FrameReceipt.js"
|
|
926
|
+
},
|
|
927
|
+
"./zod/FrameSignature": {
|
|
928
|
+
"src": "./src/zod/FrameSignature.ts",
|
|
929
|
+
"types": "./dist/zod/FrameSignature.d.ts",
|
|
930
|
+
"default": "./dist/zod/FrameSignature.js"
|
|
931
|
+
},
|
|
897
932
|
"./zod/Hash": {
|
|
898
933
|
"src": "./src/zod/Hash.ts",
|
|
899
934
|
"types": "./dist/zod/Hash.d.ts",
|
|
@@ -984,6 +1019,11 @@
|
|
|
984
1019
|
"types": "./dist/zod/TxEnvelopeEip7702.d.ts",
|
|
985
1020
|
"default": "./dist/zod/TxEnvelopeEip7702.js"
|
|
986
1021
|
},
|
|
1022
|
+
"./zod/TxEnvelopeEip8141": {
|
|
1023
|
+
"src": "./src/zod/TxEnvelopeEip8141.ts",
|
|
1024
|
+
"types": "./dist/zod/TxEnvelopeEip8141.d.ts",
|
|
1025
|
+
"default": "./dist/zod/TxEnvelopeEip8141.js"
|
|
1026
|
+
},
|
|
987
1027
|
"./zod/TxEnvelopeLegacy": {
|
|
988
1028
|
"src": "./src/zod/TxEnvelopeLegacy.ts",
|
|
989
1029
|
"types": "./dist/zod/TxEnvelopeLegacy.d.ts",
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import * as Address from './Address.js'
|
|
2
|
+
import * as Bytes from './Bytes.js'
|
|
3
|
+
import * as Errors from './Errors.js'
|
|
4
|
+
import * as Hex from './Hex.js'
|
|
5
|
+
import * as Quantity from './internal/quantity.js'
|
|
6
|
+
|
|
7
|
+
/** An EIP-8141 call frame. */
|
|
8
|
+
export type Frame<bigintType = bigint> = {
|
|
9
|
+
/**
|
|
10
|
+
* Frame calldata.
|
|
11
|
+
* @default '0x'
|
|
12
|
+
*/
|
|
13
|
+
data?: Hex.Hex | undefined
|
|
14
|
+
/**
|
|
15
|
+
* Approval scope and atomic batching bits.
|
|
16
|
+
* @default 0
|
|
17
|
+
*/
|
|
18
|
+
flags?: Flags | undefined
|
|
19
|
+
/**
|
|
20
|
+
* Execution gas budget.
|
|
21
|
+
* @default 0n
|
|
22
|
+
*/
|
|
23
|
+
gas?: bigintType | undefined
|
|
24
|
+
/**
|
|
25
|
+
* Execution context: default, verify, or sender.
|
|
26
|
+
* @default 0
|
|
27
|
+
*/
|
|
28
|
+
mode?: Mode | undefined
|
|
29
|
+
/**
|
|
30
|
+
* State gas budget.
|
|
31
|
+
* @default 0n
|
|
32
|
+
*/
|
|
33
|
+
stateGas?: bigintType | undefined
|
|
34
|
+
/** Target address. Omit to target the transaction sender. */
|
|
35
|
+
to?: Address.Address | undefined
|
|
36
|
+
/**
|
|
37
|
+
* Value transferred by a sender frame, in wei.
|
|
38
|
+
* @default 0n
|
|
39
|
+
*/
|
|
40
|
+
value?: bigintType | undefined
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** JSON-RPC representation of a frame. */
|
|
44
|
+
export type Rpc = {
|
|
45
|
+
/** Frame calldata. */
|
|
46
|
+
data: Hex.Hex
|
|
47
|
+
/** Execution gas budget. */
|
|
48
|
+
executionGasLimit: Hex.Hex
|
|
49
|
+
/** Approval scope and batching bits. */
|
|
50
|
+
flags: number
|
|
51
|
+
/** Execution mode. */
|
|
52
|
+
mode: number
|
|
53
|
+
/** State gas budget. */
|
|
54
|
+
stateGasLimit: Hex.Hex
|
|
55
|
+
/** Target address; absent for the transaction sender. */
|
|
56
|
+
target?: Address.Address | null | undefined
|
|
57
|
+
/** Value transferred in wei. */
|
|
58
|
+
value: Hex.Hex
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Frame execution modes. */
|
|
62
|
+
export const modes = { default: 0, sender: 2, verify: 1 } as const
|
|
63
|
+
|
|
64
|
+
/** A numeric or named frame execution mode. */
|
|
65
|
+
export type Mode = number | keyof typeof modes
|
|
66
|
+
|
|
67
|
+
/** Approval and atomic batching flags. */
|
|
68
|
+
export const flags = {
|
|
69
|
+
approveExecution: 2,
|
|
70
|
+
approveExecutionAndPayment: 3,
|
|
71
|
+
approvePayment: 1,
|
|
72
|
+
atomicBatch: 4,
|
|
73
|
+
none: 0,
|
|
74
|
+
} as const
|
|
75
|
+
|
|
76
|
+
/** Numeric approval and batching bits, or a named flag value. */
|
|
77
|
+
export type Flags = number | keyof typeof flags
|
|
78
|
+
|
|
79
|
+
/** RLP-ready frame tuple. Empty target bytes refer to the transaction sender. */
|
|
80
|
+
export type Tuple = readonly [
|
|
81
|
+
mode: Hex.Hex,
|
|
82
|
+
flags: Hex.Hex,
|
|
83
|
+
target: Hex.Hex,
|
|
84
|
+
limits: readonly [execution: Hex.Hex, state: Hex.Hex],
|
|
85
|
+
value: Hex.Hex,
|
|
86
|
+
data: Hex.Hex,
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Asserts that a {@link ox#Frame.Frame} satisfies frame-local constraints.
|
|
91
|
+
*
|
|
92
|
+
* Sender-dependent approval, batch adjacency, expiry, and transaction-wide gas
|
|
93
|
+
* constraints require the enclosing transaction.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ### Basic Usage
|
|
97
|
+
*
|
|
98
|
+
* Check a verification frame before including it in a transaction.
|
|
99
|
+
*
|
|
100
|
+
* ```ts twoslash
|
|
101
|
+
* import { Frame } from 'ox'
|
|
102
|
+
*
|
|
103
|
+
* Frame.assert({
|
|
104
|
+
* flags: 'approveExecutionAndPayment',
|
|
105
|
+
* gas: 50_000n,
|
|
106
|
+
* mode: 'verify'
|
|
107
|
+
* })
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* @param frame - The frame to assert.
|
|
111
|
+
*/
|
|
112
|
+
export function assert(frame: Frame): void {
|
|
113
|
+
const {
|
|
114
|
+
data = '0x',
|
|
115
|
+
flags: flagsValue = 0,
|
|
116
|
+
gas = 0n,
|
|
117
|
+
mode: modeValue = 0,
|
|
118
|
+
stateGas = 0n,
|
|
119
|
+
value = 0n,
|
|
120
|
+
} = frame
|
|
121
|
+
const mode = typeof modeValue === 'string' ? modes[modeValue] : modeValue
|
|
122
|
+
if (!Number.isInteger(mode) || mode < 0 || mode > 2)
|
|
123
|
+
throw new InvalidError('mode must be a supported name or 0, 1, or 2.')
|
|
124
|
+
const flags_ = typeof flagsValue === 'string' ? flags[flagsValue] : flagsValue
|
|
125
|
+
if (!Number.isInteger(flags_) || flags_ < 0 || flags_ > 7)
|
|
126
|
+
throw new InvalidError(
|
|
127
|
+
'flags must be a supported name or an integer from 0 to 7.',
|
|
128
|
+
)
|
|
129
|
+
if (flags_ & flags.atomicBatch) {
|
|
130
|
+
if (mode === modes.verify)
|
|
131
|
+
throw new InvalidError('VERIFY frames cannot belong to an atomic batch.')
|
|
132
|
+
if (flags_ & flags.approveExecutionAndPayment)
|
|
133
|
+
throw new InvalidError(
|
|
134
|
+
'Atomic batch frames cannot approve execution or payment.',
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
if (frame.to !== undefined) Address.assert(frame.to, { strict: false })
|
|
138
|
+
for (const [field, limit] of [
|
|
139
|
+
['gas', gas],
|
|
140
|
+
['stateGas', stateGas],
|
|
141
|
+
] as const)
|
|
142
|
+
if (typeof limit !== 'bigint' || limit < 0n || limit >= 2n ** 64n)
|
|
143
|
+
throw new InvalidError(`${field} must be an unsigned 64-bit integer.`)
|
|
144
|
+
if (gas + stateGas >= 2n ** 64n)
|
|
145
|
+
throw new InvalidError('Combined frame gas must be less than 2^64.')
|
|
146
|
+
if (typeof value !== 'bigint' || value < 0n || value >= 2n ** 256n)
|
|
147
|
+
throw new InvalidError('value must be an unsigned 256-bit integer.')
|
|
148
|
+
if (mode !== modes.sender && value !== 0n)
|
|
149
|
+
throw new InvalidError('Only SENDER frames can transfer value.')
|
|
150
|
+
Hex.assert(data, { strict: true })
|
|
151
|
+
if (data.length % 2 !== 0)
|
|
152
|
+
throw new InvalidError('data must contain whole bytes.')
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export declare namespace assert {
|
|
156
|
+
type ErrorType =
|
|
157
|
+
| InvalidError
|
|
158
|
+
| Address.assert.ErrorType
|
|
159
|
+
| Hex.assert.ErrorType
|
|
160
|
+
| Errors.GlobalErrorType
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Coerces a frame object into a {@link ox#Frame.Frame}.
|
|
165
|
+
*
|
|
166
|
+
* Validates the frame and returns a copy, preserving literal types and the supplied
|
|
167
|
+
* numeric or named mode and flags. Omitted fields stay omitted;
|
|
168
|
+
* {@link ox#Frame.(toTuple:function)} supplies their defaults when encoding.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ### Basic Usage
|
|
172
|
+
*
|
|
173
|
+
* Construct a verification frame that approves execution and payment.
|
|
174
|
+
*
|
|
175
|
+
* ```ts twoslash
|
|
176
|
+
* import { Frame } from 'ox'
|
|
177
|
+
*
|
|
178
|
+
* const frame = Frame.from({
|
|
179
|
+
* flags: 'approveExecutionAndPayment',
|
|
180
|
+
* gas: 50_000n,
|
|
181
|
+
* mode: 'verify'
|
|
182
|
+
* })
|
|
183
|
+
* ```
|
|
184
|
+
*
|
|
185
|
+
* @param frame - The frame object to convert.
|
|
186
|
+
* @returns The validated frame.
|
|
187
|
+
*/
|
|
188
|
+
export function from<const frame extends Frame>(frame: frame | Frame): frame {
|
|
189
|
+
assert(frame)
|
|
190
|
+
return { ...frame } as frame
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export declare namespace from {
|
|
194
|
+
type ErrorType = assert.ErrorType
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Converts an RPC frame to a frame.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ### Basic Usage
|
|
202
|
+
*
|
|
203
|
+
* ```ts twoslash
|
|
204
|
+
* import { Frame } from 'ox'
|
|
205
|
+
*
|
|
206
|
+
* const frame = Frame.fromRpc({
|
|
207
|
+
* data: '0x',
|
|
208
|
+
* executionGasLimit: '0xc350',
|
|
209
|
+
* flags: 3,
|
|
210
|
+
* mode: 1,
|
|
211
|
+
* stateGasLimit: '0x0',
|
|
212
|
+
* value: '0x0'
|
|
213
|
+
* })
|
|
214
|
+
* ```
|
|
215
|
+
*
|
|
216
|
+
* @param frame - The value to convert.
|
|
217
|
+
* @returns The converted value.
|
|
218
|
+
*/
|
|
219
|
+
export function fromRpc(frame: Rpc): Frame {
|
|
220
|
+
return from({
|
|
221
|
+
data: frame.data,
|
|
222
|
+
flags: frame.flags,
|
|
223
|
+
gas: Hex.toBigInt(frame.executionGasLimit),
|
|
224
|
+
mode: frame.mode,
|
|
225
|
+
stateGas: Hex.toBigInt(frame.stateGasLimit),
|
|
226
|
+
...(frame.target == null ? {} : { to: frame.target }),
|
|
227
|
+
value: Hex.toBigInt(frame.value),
|
|
228
|
+
})
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export declare namespace fromRpc {
|
|
232
|
+
type ErrorType = from.ErrorType | Hex.toBigInt.ErrorType
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Converts a frame to its JSON-RPC representation.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ### Basic Usage
|
|
240
|
+
*
|
|
241
|
+
* ```ts twoslash
|
|
242
|
+
* import { Frame } from 'ox'
|
|
243
|
+
*
|
|
244
|
+
* const frame = Frame.from({ gas: 50_000n, mode: 'verify' })
|
|
245
|
+
* const rpc = Frame.toRpc(frame)
|
|
246
|
+
* ```
|
|
247
|
+
*
|
|
248
|
+
* @param frame - The value to convert.
|
|
249
|
+
* @returns The converted value.
|
|
250
|
+
*/
|
|
251
|
+
export function toRpc(frame: toRpc.Input): Rpc {
|
|
252
|
+
const { flags: flags_ = 0, mode = 0 } = frame
|
|
253
|
+
return {
|
|
254
|
+
data: frame.data ?? '0x',
|
|
255
|
+
executionGasLimit: Quantity.fromNumberish(frame.gas ?? 0n),
|
|
256
|
+
flags: typeof flags_ === 'string' ? flags[flags_] : flags_,
|
|
257
|
+
mode: typeof mode === 'string' ? modes[mode] : mode,
|
|
258
|
+
stateGasLimit: Quantity.fromNumberish(frame.stateGas ?? 0n),
|
|
259
|
+
...(frame.to === undefined ? {} : { target: frame.to }),
|
|
260
|
+
value: Quantity.fromNumberish(frame.value ?? 0n),
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export declare namespace toRpc {
|
|
265
|
+
type Input = Frame<Hex.Hex | bigint | number>
|
|
266
|
+
type ErrorType = Hex.fromNumber.ErrorType | Errors.GlobalErrorType
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Converts a {@link ox#Frame.Tuple} to a {@link ox#Frame.Frame}.
|
|
271
|
+
*
|
|
272
|
+
* Returns numeric mode and flags. An empty target becomes an omitted `to`.
|
|
273
|
+
* Integer fields must use minimal whole-byte encodings, with empty bytes for zero.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ### Basic Usage
|
|
277
|
+
*
|
|
278
|
+
* Decode a frame tuple with separate execution and state gas limits.
|
|
279
|
+
*
|
|
280
|
+
* ```ts twoslash
|
|
281
|
+
* import { Frame } from 'ox'
|
|
282
|
+
*
|
|
283
|
+
* const frame = Frame.fromTuple([
|
|
284
|
+
* '0x01',
|
|
285
|
+
* '0x03',
|
|
286
|
+
* '0x',
|
|
287
|
+
* ['0xc350', '0x'],
|
|
288
|
+
* '0x',
|
|
289
|
+
* '0x'
|
|
290
|
+
* ])
|
|
291
|
+
* // @log: {
|
|
292
|
+
* // @log: data: '0x',
|
|
293
|
+
* // @log: flags: 3,
|
|
294
|
+
* // @log: gas: 50000n,
|
|
295
|
+
* // @log: mode: 1,
|
|
296
|
+
* // @log: stateGas: 0n,
|
|
297
|
+
* // @log: value: 0n
|
|
298
|
+
* // @log: }
|
|
299
|
+
* ```
|
|
300
|
+
*
|
|
301
|
+
* @param tuple - The frame tuple to convert.
|
|
302
|
+
* @returns The decoded frame.
|
|
303
|
+
*/
|
|
304
|
+
export function fromTuple(tuple: Tuple): Frame {
|
|
305
|
+
if (
|
|
306
|
+
!Array.isArray(tuple) ||
|
|
307
|
+
tuple.length !== 6 ||
|
|
308
|
+
!Array.isArray(tuple[3]) ||
|
|
309
|
+
tuple[3].length !== 2
|
|
310
|
+
)
|
|
311
|
+
throw new InvalidError(
|
|
312
|
+
'Expected [mode, flags, target, [execution, state], value, data].',
|
|
313
|
+
)
|
|
314
|
+
const [mode, flags, target, [execution, state], value, data] = tuple
|
|
315
|
+
Hex.assert(target, { strict: true })
|
|
316
|
+
Hex.assert(data, { strict: true })
|
|
317
|
+
const quantities = [mode, flags, execution, state, value]
|
|
318
|
+
for (const quantity of quantities) {
|
|
319
|
+
Hex.assert(quantity, { strict: true })
|
|
320
|
+
if (quantity.length % 2 !== 0 || quantity.startsWith('0x00'))
|
|
321
|
+
throw new InvalidError(
|
|
322
|
+
'Integers must use minimal whole-byte encodings, with empty bytes for zero.',
|
|
323
|
+
)
|
|
324
|
+
}
|
|
325
|
+
const frame = {
|
|
326
|
+
...(target === '0x' ? {} : { to: target }),
|
|
327
|
+
data,
|
|
328
|
+
flags: flags === '0x' ? 0 : Hex.toNumber(flags),
|
|
329
|
+
gas: execution === '0x' ? 0n : Hex.toBigInt(execution),
|
|
330
|
+
mode: mode === '0x' ? 0 : Hex.toNumber(mode),
|
|
331
|
+
stateGas: state === '0x' ? 0n : Hex.toBigInt(state),
|
|
332
|
+
value: value === '0x' ? 0n : Hex.toBigInt(value),
|
|
333
|
+
}
|
|
334
|
+
assert(frame)
|
|
335
|
+
return frame
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export declare namespace fromTuple {
|
|
339
|
+
type ErrorType =
|
|
340
|
+
| assert.ErrorType
|
|
341
|
+
| Hex.toNumber.ErrorType
|
|
342
|
+
| Hex.toBigInt.ErrorType
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Converts a {@link ox#Frame.Frame} to its RLP-ready {@link ox#Frame.Tuple}.
|
|
347
|
+
*
|
|
348
|
+
* Named mode and flags are encoded as integers. An omitted target and zero integer
|
|
349
|
+
* fields are encoded as empty bytes. Omitted mode and flags default to zero;
|
|
350
|
+
* omitted gas limits and value default to `0n`, and data defaults to `'0x'`.
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* ### Basic Usage
|
|
354
|
+
*
|
|
355
|
+
* Encode a verification frame in the field order required by EIP-8141.
|
|
356
|
+
*
|
|
357
|
+
* ```ts twoslash
|
|
358
|
+
* import { Frame } from 'ox'
|
|
359
|
+
*
|
|
360
|
+
* const tuple = Frame.toTuple({
|
|
361
|
+
* flags: 'approveExecutionAndPayment',
|
|
362
|
+
* gas: 50_000n,
|
|
363
|
+
* mode: 'verify'
|
|
364
|
+
* })
|
|
365
|
+
* // @log: ['0x01', '0x03', '0x', ['0xc350', '0x'], '0x', '0x']
|
|
366
|
+
* ```
|
|
367
|
+
*
|
|
368
|
+
* @param frame - The frame to convert.
|
|
369
|
+
* @returns The encoded frame tuple.
|
|
370
|
+
*/
|
|
371
|
+
export function toTuple(frame: Frame): Tuple {
|
|
372
|
+
assert(frame)
|
|
373
|
+
const mode =
|
|
374
|
+
typeof frame.mode === 'string' ? modes[frame.mode] : (frame.mode ?? 0)
|
|
375
|
+
const flags_ =
|
|
376
|
+
typeof frame.flags === 'string' ? flags[frame.flags] : (frame.flags ?? 0)
|
|
377
|
+
return [
|
|
378
|
+
mode ? Hex.fromBytes(Bytes.fromNumber(mode)) : '0x',
|
|
379
|
+
flags_ ? Hex.fromBytes(Bytes.fromNumber(flags_)) : '0x',
|
|
380
|
+
frame.to ?? '0x',
|
|
381
|
+
[
|
|
382
|
+
frame.gas ? Hex.fromBytes(Bytes.fromNumber(frame.gas)) : '0x',
|
|
383
|
+
frame.stateGas ? Hex.fromBytes(Bytes.fromNumber(frame.stateGas)) : '0x',
|
|
384
|
+
],
|
|
385
|
+
frame.value ? Hex.fromBytes(Bytes.fromNumber(frame.value)) : '0x',
|
|
386
|
+
frame.data ?? '0x',
|
|
387
|
+
]
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
export declare namespace toTuple {
|
|
391
|
+
type ErrorType =
|
|
392
|
+
| assert.ErrorType
|
|
393
|
+
| Bytes.fromNumber.ErrorType
|
|
394
|
+
| Hex.fromBytes.ErrorType
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Returns whether a {@link ox#Frame.Frame} satisfies frame-local constraints.
|
|
399
|
+
*
|
|
400
|
+
* Performs the same checks as {@link ox#Frame.(assert:function)}, returning `false`
|
|
401
|
+
* instead of throwing when the frame is invalid.
|
|
402
|
+
*
|
|
403
|
+
* @example
|
|
404
|
+
* ### Basic Usage
|
|
405
|
+
*
|
|
406
|
+
* Check whether a frame is structurally valid.
|
|
407
|
+
*
|
|
408
|
+
* ```ts twoslash
|
|
409
|
+
* import { Frame } from 'ox'
|
|
410
|
+
*
|
|
411
|
+
* const valid = Frame.validate({
|
|
412
|
+
* flags: 'approveExecutionAndPayment',
|
|
413
|
+
* gas: 50_000n,
|
|
414
|
+
* mode: 'verify'
|
|
415
|
+
* })
|
|
416
|
+
* // @log: true
|
|
417
|
+
* ```
|
|
418
|
+
*
|
|
419
|
+
* @param frame - The frame to validate.
|
|
420
|
+
* @returns Whether the frame satisfies frame-local constraints.
|
|
421
|
+
*/
|
|
422
|
+
export function validate(frame: Frame): boolean {
|
|
423
|
+
try {
|
|
424
|
+
assert(frame)
|
|
425
|
+
return true
|
|
426
|
+
} catch {
|
|
427
|
+
return false
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
export declare namespace validate {
|
|
432
|
+
type ErrorType = Errors.GlobalErrorType
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/** Thrown when an EIP-8141 frame is structurally invalid. */
|
|
436
|
+
export class InvalidError extends Errors.BaseError {
|
|
437
|
+
override readonly name = 'Frame.InvalidError'
|
|
438
|
+
|
|
439
|
+
constructor(details: string) {
|
|
440
|
+
super('Invalid frame.', { details })
|
|
441
|
+
}
|
|
442
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type * as Errors from './Errors.js'
|
|
2
|
+
import * as Hex from './Hex.js'
|
|
3
|
+
import * as Quantity from './internal/quantity.js'
|
|
4
|
+
import type * as Log from './Log.js'
|
|
5
|
+
|
|
6
|
+
/** Receipt for one frame. Frame logs contain only address, data, and topics. */
|
|
7
|
+
export type FrameReceipt<bigintType = bigint> = {
|
|
8
|
+
/** Execution gas used before transaction-level refunds. */
|
|
9
|
+
gasUsed: bigintType
|
|
10
|
+
/** Logs emitted by this frame. */
|
|
11
|
+
logs: readonly Pick<Log.Log, 'address' | 'data' | 'topics'>[]
|
|
12
|
+
/** Final state gas after refills and rollbacks. */
|
|
13
|
+
stateGasUsed: bigintType
|
|
14
|
+
/** Frame execution result. */
|
|
15
|
+
status: Status
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** JSON-RPC receipt for one frame. */
|
|
19
|
+
export type Rpc = {
|
|
20
|
+
/** Execution gas used. */
|
|
21
|
+
executionGasUsed: Hex.Hex
|
|
22
|
+
/** Logs emitted by this frame. */
|
|
23
|
+
logs: readonly Pick<Log.Log, 'address' | 'data' | 'topics'>[]
|
|
24
|
+
/** Final state gas used. */
|
|
25
|
+
stateGasUsed: Hex.Hex
|
|
26
|
+
/** Zero for failure, one for success, or two for a skipped frame. */
|
|
27
|
+
status: RpcStatus
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Frame execution status. */
|
|
31
|
+
export type Status = 'reverted' | 'skipped' | 'success'
|
|
32
|
+
|
|
33
|
+
/** Numeric JSON-RPC frame execution status. */
|
|
34
|
+
export type RpcStatus = 0 | 1 | 2
|
|
35
|
+
|
|
36
|
+
/** RPC status to status mapping. */
|
|
37
|
+
export const fromRpcStatus = {
|
|
38
|
+
0: 'reverted',
|
|
39
|
+
1: 'success',
|
|
40
|
+
2: 'skipped',
|
|
41
|
+
} as const
|
|
42
|
+
|
|
43
|
+
/** Status to RPC status mapping. */
|
|
44
|
+
export const toRpcStatus = {
|
|
45
|
+
reverted: 0,
|
|
46
|
+
skipped: 2,
|
|
47
|
+
success: 1,
|
|
48
|
+
} as const
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Converts an RPC frame receipt to a {@link ox#FrameReceipt.FrameReceipt}.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ### Basic Usage
|
|
55
|
+
*
|
|
56
|
+
* ```ts twoslash
|
|
57
|
+
* import { FrameReceipt } from 'ox'
|
|
58
|
+
*
|
|
59
|
+
* const receipt = FrameReceipt.fromRpc({
|
|
60
|
+
* executionGasUsed: '0x5208',
|
|
61
|
+
* logs: [],
|
|
62
|
+
* stateGasUsed: '0x0',
|
|
63
|
+
* status: 1
|
|
64
|
+
* })
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @param receipt - The RPC frame receipt.
|
|
68
|
+
* @returns The frame receipt with bigint gas and a named status.
|
|
69
|
+
*/
|
|
70
|
+
export function fromRpc(receipt: Rpc): FrameReceipt {
|
|
71
|
+
return {
|
|
72
|
+
gasUsed: Hex.toBigInt(receipt.executionGasUsed),
|
|
73
|
+
logs: receipt.logs,
|
|
74
|
+
stateGasUsed: Hex.toBigInt(receipt.stateGasUsed),
|
|
75
|
+
status: fromRpcStatus[receipt.status],
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export declare namespace fromRpc {
|
|
80
|
+
type ErrorType = Hex.toBigInt.ErrorType | Errors.GlobalErrorType
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Converts a {@link ox#FrameReceipt.FrameReceipt} to an RPC frame receipt.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ### Basic Usage
|
|
88
|
+
*
|
|
89
|
+
* ```ts twoslash
|
|
90
|
+
* import { FrameReceipt } from 'ox'
|
|
91
|
+
*
|
|
92
|
+
* const receipt = FrameReceipt.fromRpc({
|
|
93
|
+
* executionGasUsed: '0x5208',
|
|
94
|
+
* logs: [],
|
|
95
|
+
* stateGasUsed: '0x0',
|
|
96
|
+
* status: 1
|
|
97
|
+
* })
|
|
98
|
+
* const rpc = FrameReceipt.toRpc(receipt)
|
|
99
|
+
* ```
|
|
100
|
+
*
|
|
101
|
+
* @param receipt - The frame receipt. Gas accepts hex, bigint, or number values.
|
|
102
|
+
* @returns The RPC frame receipt with hex gas and a numeric status.
|
|
103
|
+
*/
|
|
104
|
+
export function toRpc(receipt: toRpc.Input): Rpc {
|
|
105
|
+
return {
|
|
106
|
+
executionGasUsed: Quantity.fromNumberish(receipt.gasUsed),
|
|
107
|
+
logs: receipt.logs,
|
|
108
|
+
stateGasUsed: Quantity.fromNumberish(receipt.stateGasUsed),
|
|
109
|
+
status: toRpcStatus[receipt.status],
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export declare namespace toRpc {
|
|
114
|
+
type Input = FrameReceipt<Hex.Hex | bigint | number>
|
|
115
|
+
|
|
116
|
+
type ErrorType = Hex.fromNumber.ErrorType | Errors.GlobalErrorType
|
|
117
|
+
}
|