ox 0.4.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/_cjs/core/Siwe.js +1 -1
- package/_cjs/core/Siwe.js.map +1 -1
- package/_cjs/erc4337/EntryPoint.js +1320 -0
- package/_cjs/erc4337/EntryPoint.js.map +1 -0
- package/_cjs/erc4337/RpcSchema.js +3 -0
- package/_cjs/erc4337/RpcSchema.js.map +1 -0
- package/_cjs/erc4337/UserOperation.js +152 -0
- package/_cjs/erc4337/UserOperation.js.map +1 -0
- package/_cjs/erc4337/UserOperationGas.js +31 -0
- package/_cjs/erc4337/UserOperationGas.js.map +1 -0
- package/_cjs/erc4337/UserOperationReceipt.js +35 -0
- package/_cjs/erc4337/UserOperationReceipt.js.map +1 -0
- package/_cjs/erc4337/index.js +9 -0
- package/_cjs/erc4337/index.js.map +1 -0
- package/_cjs/index.docs.js +1 -0
- package/_cjs/index.docs.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/core/Siwe.js +1 -1
- package/_esm/core/Siwe.js.map +1 -1
- package/_esm/erc4337/EntryPoint.js +1321 -0
- package/_esm/erc4337/EntryPoint.js.map +1 -0
- package/_esm/erc4337/RpcSchema.js +2 -0
- package/_esm/erc4337/RpcSchema.js.map +1 -0
- package/_esm/erc4337/UserOperation.js +324 -0
- package/_esm/erc4337/UserOperation.js.map +1 -0
- package/_esm/erc4337/UserOperationGas.js +61 -0
- package/_esm/erc4337/UserOperationGas.js.map +1 -0
- package/_esm/erc4337/UserOperationReceipt.js +79 -0
- package/_esm/erc4337/UserOperationReceipt.js.map +1 -0
- package/_esm/erc4337/index.js +31 -0
- package/_esm/erc4337/index.js.map +1 -0
- package/_esm/index.docs.js +1 -0
- package/_esm/index.docs.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_types/erc4337/EntryPoint.d.ts +1480 -0
- package/_types/erc4337/EntryPoint.d.ts.map +1 -0
- package/_types/erc4337/RpcSchema.d.ts +159 -0
- package/_types/erc4337/RpcSchema.d.ts.map +1 -0
- package/_types/erc4337/UserOperation.d.ts +330 -0
- package/_types/erc4337/UserOperation.d.ts.map +1 -0
- package/_types/erc4337/UserOperationGas.d.ts +62 -0
- package/_types/erc4337/UserOperationGas.d.ts.map +1 -0
- package/_types/erc4337/UserOperationReceipt.d.ts +87 -0
- package/_types/erc4337/UserOperationReceipt.d.ts.map +1 -0
- package/_types/erc4337/index.d.ts +33 -0
- package/_types/erc4337/index.d.ts.map +1 -0
- package/_types/index.docs.d.ts +1 -0
- package/_types/index.docs.d.ts.map +1 -1
- package/_types/version.d.ts +1 -1
- package/core/Siwe.ts +1 -1
- package/erc4337/EntryPoint/package.json +6 -0
- package/erc4337/EntryPoint.ts +1419 -0
- package/erc4337/RpcSchema/package.json +6 -0
- package/erc4337/RpcSchema.ts +179 -0
- package/erc4337/UserOperation/package.json +6 -0
- package/erc4337/UserOperation.ts +617 -0
- package/erc4337/UserOperationGas/package.json +6 -0
- package/erc4337/UserOperationGas.ts +109 -0
- package/erc4337/UserOperationReceipt/package.json +6 -0
- package/erc4337/UserOperationReceipt.ts +139 -0
- package/erc4337/index.ts +38 -0
- package/erc4337/package.json +6 -0
- package/index.docs.ts +1 -0
- package/package.json +31 -1
- package/version.ts +1 -1
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
import * as AbiParameters from '../core/AbiParameters.js'
|
|
2
|
+
import type * as Address from '../core/Address.js'
|
|
3
|
+
import type * as Errors from '../core/Errors.js'
|
|
4
|
+
import * as Hash from '../core/Hash.js'
|
|
5
|
+
import * as Hex from '../core/Hex.js'
|
|
6
|
+
import * as Signature from '../core/Signature.js'
|
|
7
|
+
import type { Assign, Compute, OneOf } from '../core/internal/types.js'
|
|
8
|
+
import type * as EntryPoint from './EntryPoint.js'
|
|
9
|
+
|
|
10
|
+
/** User Operation. */
|
|
11
|
+
export type UserOperation<
|
|
12
|
+
entryPointVersion extends EntryPoint.Version = EntryPoint.Version,
|
|
13
|
+
signed extends boolean = boolean,
|
|
14
|
+
bigintType = bigint,
|
|
15
|
+
> = OneOf<
|
|
16
|
+
| (entryPointVersion extends '0.6' ? V06<signed, bigintType> : never)
|
|
17
|
+
| (entryPointVersion extends '0.7' ? V07<signed, bigintType> : never)
|
|
18
|
+
>
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Packed User Operation.
|
|
22
|
+
*
|
|
23
|
+
* @see https://eips.ethereum.org/EIPS/eip-4337#entrypoint-definition
|
|
24
|
+
*/
|
|
25
|
+
export type Packed = {
|
|
26
|
+
/** Concatenation of `verificationGasLimit` (16 bytes) and `callGasLimit` (16 bytes) */
|
|
27
|
+
accountGasLimits: Hex.Hex
|
|
28
|
+
/** The data to pass to the `sender` during the main execution call. */
|
|
29
|
+
callData: Hex.Hex
|
|
30
|
+
/** Concatenation of `factory` and `factoryData`. */
|
|
31
|
+
initCode: Hex.Hex
|
|
32
|
+
/** Concatenation of `maxPriorityFee` (16 bytes) and `maxFeePerGas` (16 bytes) */
|
|
33
|
+
gasFees: Hex.Hex
|
|
34
|
+
/** Anti-replay parameter. */
|
|
35
|
+
nonce: bigint
|
|
36
|
+
/** Concatenation of paymaster fields (or empty). */
|
|
37
|
+
paymasterAndData: Hex.Hex
|
|
38
|
+
/** Extra gas to pay the Bundler. */
|
|
39
|
+
preVerificationGas: bigint
|
|
40
|
+
/** The account making the operation. */
|
|
41
|
+
sender: Address.Address
|
|
42
|
+
/** Data passed into the account to verify authorization. */
|
|
43
|
+
signature: Hex.Hex
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** RPC User Operation type. */
|
|
47
|
+
export type Rpc<
|
|
48
|
+
entryPointVersion extends EntryPoint.Version = EntryPoint.Version,
|
|
49
|
+
signed extends boolean = true,
|
|
50
|
+
> = OneOf<
|
|
51
|
+
| (entryPointVersion extends '0.6' ? V06<signed, Hex.Hex> : never)
|
|
52
|
+
| (entryPointVersion extends '0.7' ? V07<signed, Hex.Hex> : never)
|
|
53
|
+
>
|
|
54
|
+
|
|
55
|
+
/** Transaction Info. */
|
|
56
|
+
export type TransactionInfo<
|
|
57
|
+
entryPointVersion extends EntryPoint.Version = EntryPoint.Version,
|
|
58
|
+
bigintType = bigint,
|
|
59
|
+
> = {
|
|
60
|
+
blockHash: Hex.Hex
|
|
61
|
+
blockNumber: bigintType
|
|
62
|
+
entryPoint: Address.Address
|
|
63
|
+
transactionHash: Hex.Hex
|
|
64
|
+
userOperation: UserOperation<entryPointVersion, true, bigintType>
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** RPC Transaction Info. */
|
|
68
|
+
export type RpcTransactionInfo<
|
|
69
|
+
entryPointVersion extends EntryPoint.Version = EntryPoint.Version,
|
|
70
|
+
> = TransactionInfo<entryPointVersion, Hex.Hex>
|
|
71
|
+
|
|
72
|
+
/** Type for User Operation on EntryPoint 0.6 */
|
|
73
|
+
export type V06<signed extends boolean = boolean, bigintType = bigint> = {
|
|
74
|
+
/** The data to pass to the `sender` during the main execution call. */
|
|
75
|
+
callData: Hex.Hex
|
|
76
|
+
/** The amount of gas to allocate the main execution call */
|
|
77
|
+
callGasLimit: bigintType
|
|
78
|
+
/** Account init code. Only for new accounts. */
|
|
79
|
+
initCode?: Hex.Hex | undefined
|
|
80
|
+
/** Maximum fee per gas. */
|
|
81
|
+
maxFeePerGas: bigintType
|
|
82
|
+
/** Maximum priority fee per gas. */
|
|
83
|
+
maxPriorityFeePerGas: bigintType
|
|
84
|
+
/** Anti-replay parameter. */
|
|
85
|
+
nonce: bigintType
|
|
86
|
+
/** Paymaster address with calldata. */
|
|
87
|
+
paymasterAndData?: Hex.Hex | undefined
|
|
88
|
+
/** Extra gas to pay the Bundler. */
|
|
89
|
+
preVerificationGas: bigintType
|
|
90
|
+
/** The account making the operation. */
|
|
91
|
+
sender: Address.Address
|
|
92
|
+
/** Data passed into the account to verify authorization. */
|
|
93
|
+
signature?: Hex.Hex | undefined
|
|
94
|
+
/** The amount of gas to allocate for the verification step. */
|
|
95
|
+
verificationGasLimit: bigintType
|
|
96
|
+
} & (signed extends true ? { signature: Hex.Hex } : {})
|
|
97
|
+
|
|
98
|
+
/** RPC User Operation on EntryPoint 0.6 */
|
|
99
|
+
export type RpcV06<signed extends boolean = true> = V06<signed, Hex.Hex>
|
|
100
|
+
|
|
101
|
+
/** Type for User Operation on EntryPoint 0.7 */
|
|
102
|
+
export type V07<signed extends boolean = boolean, bigintType = bigint> = {
|
|
103
|
+
/** The data to pass to the `sender` during the main execution call. */
|
|
104
|
+
callData: Hex.Hex
|
|
105
|
+
/** The amount of gas to allocate the main execution call */
|
|
106
|
+
callGasLimit: bigintType
|
|
107
|
+
/** Account factory. Only for new accounts. */
|
|
108
|
+
factory?: Address.Address | undefined
|
|
109
|
+
/** Data for account factory. */
|
|
110
|
+
factoryData?: Hex.Hex | undefined
|
|
111
|
+
/** Maximum fee per gas. */
|
|
112
|
+
maxFeePerGas: bigintType
|
|
113
|
+
/** Maximum priority fee per gas. */
|
|
114
|
+
maxPriorityFeePerGas: bigintType
|
|
115
|
+
/** Anti-replay parameter. */
|
|
116
|
+
nonce: bigintType
|
|
117
|
+
/** Address of paymaster contract. */
|
|
118
|
+
paymaster?: Address.Address | undefined
|
|
119
|
+
/** Data for paymaster. */
|
|
120
|
+
paymasterData?: Hex.Hex | undefined
|
|
121
|
+
/** The amount of gas to allocate for the paymaster post-operation code. */
|
|
122
|
+
paymasterPostOpGasLimit?: bigintType | undefined
|
|
123
|
+
/** The amount of gas to allocate for the paymaster validation code. */
|
|
124
|
+
paymasterVerificationGasLimit?: bigintType | undefined
|
|
125
|
+
/** Extra gas to pay the Bundler. */
|
|
126
|
+
preVerificationGas: bigintType
|
|
127
|
+
/** The account making the operation. */
|
|
128
|
+
sender: Address.Address
|
|
129
|
+
/** Data passed into the account to verify authorization. */
|
|
130
|
+
signature?: Hex.Hex | undefined
|
|
131
|
+
/** The amount of gas to allocate for the verification step. */
|
|
132
|
+
verificationGasLimit: bigintType
|
|
133
|
+
} & (signed extends true ? { signature: Hex.Hex } : {})
|
|
134
|
+
|
|
135
|
+
/** RPC User Operation on EntryPoint 0.7 */
|
|
136
|
+
export type RpcV07<signed extends boolean = true> = V07<signed, Hex.Hex>
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Instantiates a {@link ox#UserOperation.UserOperation} from a provided input.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts twoslash
|
|
143
|
+
* import { Value } from 'ox'
|
|
144
|
+
* import { UserOperation } from 'ox/erc4337'
|
|
145
|
+
*
|
|
146
|
+
* const userOperation = UserOperation.from({
|
|
147
|
+
* callData: '0xdeadbeef',
|
|
148
|
+
* callGasLimit: 300_000n,
|
|
149
|
+
* maxFeePerGas: Value.fromGwei('20'),
|
|
150
|
+
* maxPriorityFeePerGas: Value.fromGwei('2'),
|
|
151
|
+
* nonce: 69n,
|
|
152
|
+
* preVerificationGas: 100_000n,
|
|
153
|
+
* sender: '0x9f1fdab6458c5fc642fa0f4c5af7473c46837357',
|
|
154
|
+
* verificationGasLimit: 100_000n,
|
|
155
|
+
* })
|
|
156
|
+
* ```
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ### Attaching Signatures
|
|
160
|
+
*
|
|
161
|
+
* ```ts twoslash
|
|
162
|
+
* import { Secp256k1, Value } from 'ox'
|
|
163
|
+
* import { UserOperation } from 'ox/erc4337'
|
|
164
|
+
*
|
|
165
|
+
* const userOperation = UserOperation.from({
|
|
166
|
+
* callData: '0xdeadbeef',
|
|
167
|
+
* callGasLimit: 300_000n,
|
|
168
|
+
* maxFeePerGas: Value.fromGwei('20'),
|
|
169
|
+
* maxPriorityFeePerGas: Value.fromGwei('2'),
|
|
170
|
+
* nonce: 69n,
|
|
171
|
+
* preVerificationGas: 100_000n,
|
|
172
|
+
* sender: '0x9f1fdab6458c5fc642fa0f4c5af7473c46837357',
|
|
173
|
+
* verificationGasLimit: 100_000n,
|
|
174
|
+
* })
|
|
175
|
+
*
|
|
176
|
+
* const payload = UserOperation.getSignPayload(userOperation, {
|
|
177
|
+
* chainId: 1,
|
|
178
|
+
* entryPointAddress: '0x1234567890123456789012345678901234567890',
|
|
179
|
+
* entryPointVersion: '0.7',
|
|
180
|
+
* })
|
|
181
|
+
*
|
|
182
|
+
* const signature = Secp256k1.sign({ payload, privateKey: '0x...' })
|
|
183
|
+
*
|
|
184
|
+
* const userOperation_signed = UserOperation.from(userOperation, { signature }) // [!code focus]
|
|
185
|
+
* ```
|
|
186
|
+
*
|
|
187
|
+
* @param userOperation - The user operation to instantiate.
|
|
188
|
+
* @returns User Operation.
|
|
189
|
+
*/
|
|
190
|
+
export function from<
|
|
191
|
+
const userOperation extends UserOperation,
|
|
192
|
+
const signature extends Hex.Hex | undefined = undefined,
|
|
193
|
+
>(
|
|
194
|
+
userOperation: userOperation | UserOperation,
|
|
195
|
+
options: from.Options<signature> = {},
|
|
196
|
+
): from.ReturnType<userOperation, signature> {
|
|
197
|
+
const signature = (() => {
|
|
198
|
+
if (!options.signature) return undefined
|
|
199
|
+
if (typeof options.signature === 'string') return options.signature
|
|
200
|
+
return Signature.toHex(options.signature)
|
|
201
|
+
})()
|
|
202
|
+
return { ...userOperation, signature } as never
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export declare namespace from {
|
|
206
|
+
export type Options<
|
|
207
|
+
signature extends Signature.Signature | Hex.Hex | undefined = undefined,
|
|
208
|
+
> = {
|
|
209
|
+
signature?: signature | Signature.Signature | Hex.Hex | undefined
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export type ReturnType<
|
|
213
|
+
userOperation extends UserOperation = UserOperation,
|
|
214
|
+
signature extends Signature.Signature | Hex.Hex | undefined = undefined,
|
|
215
|
+
> = Compute<
|
|
216
|
+
Assign<
|
|
217
|
+
userOperation,
|
|
218
|
+
signature extends Signature.Signature | Hex.Hex
|
|
219
|
+
? Readonly<{ signature: Hex.Hex }>
|
|
220
|
+
: {}
|
|
221
|
+
>
|
|
222
|
+
>
|
|
223
|
+
|
|
224
|
+
export type ErrorType = Errors.GlobalErrorType
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Converts an {@link ox#UserOperation.Rpc} to an {@link ox#UserOperation.UserOperation}.
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* ```ts twoslash
|
|
232
|
+
* import { UserOperation } from 'ox/erc4337'
|
|
233
|
+
*
|
|
234
|
+
* const userOperation = UserOperation.fromRpc({
|
|
235
|
+
* callData: '0xdeadbeef',
|
|
236
|
+
* callGasLimit: '0x69420',
|
|
237
|
+
* maxFeePerGas: '0x2ca6ae494',
|
|
238
|
+
* maxPriorityFeePerGas: '0x41cc3c0',
|
|
239
|
+
* nonce: '0x357',
|
|
240
|
+
* preVerificationGas: '0x69420',
|
|
241
|
+
* signature: '0x',
|
|
242
|
+
* sender: '0x1234567890123456789012345678901234567890',
|
|
243
|
+
* verificationGasLimit: '0x69420',
|
|
244
|
+
* })
|
|
245
|
+
* ```
|
|
246
|
+
*
|
|
247
|
+
* @param rpc - The RPC user operation to convert.
|
|
248
|
+
* @returns An instantiated {@link ox#UserOperation.UserOperation}.
|
|
249
|
+
*/
|
|
250
|
+
export function fromRpc(rpc: Rpc): UserOperation {
|
|
251
|
+
return {
|
|
252
|
+
...rpc,
|
|
253
|
+
callGasLimit: BigInt(rpc.callGasLimit),
|
|
254
|
+
maxFeePerGas: BigInt(rpc.maxFeePerGas),
|
|
255
|
+
maxPriorityFeePerGas: BigInt(rpc.maxPriorityFeePerGas),
|
|
256
|
+
nonce: BigInt(rpc.nonce),
|
|
257
|
+
preVerificationGas: BigInt(rpc.preVerificationGas),
|
|
258
|
+
verificationGasLimit: BigInt(rpc.verificationGasLimit),
|
|
259
|
+
...(rpc.paymasterPostOpGasLimit && {
|
|
260
|
+
paymasterPostOpGasLimit: BigInt(rpc.paymasterPostOpGasLimit),
|
|
261
|
+
}),
|
|
262
|
+
...(rpc.paymasterVerificationGasLimit && {
|
|
263
|
+
paymasterVerificationGasLimit: BigInt(rpc.paymasterVerificationGasLimit),
|
|
264
|
+
}),
|
|
265
|
+
} as UserOperation
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export declare namespace fromRpc {
|
|
269
|
+
type ErrorType = Errors.GlobalErrorType
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Obtains the signing payload for a {@link ox#UserOperation.UserOperation}.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```ts twoslash
|
|
277
|
+
* import { Secp256k1, Value } from 'ox'
|
|
278
|
+
* import { UserOperation } from 'ox/erc4337'
|
|
279
|
+
*
|
|
280
|
+
* const userOperation = UserOperation.from({
|
|
281
|
+
* callData: '0xdeadbeef',
|
|
282
|
+
* callGasLimit: 300_000n,
|
|
283
|
+
* maxFeePerGas: Value.fromGwei('20'),
|
|
284
|
+
* maxPriorityFeePerGas: Value.fromGwei('2'),
|
|
285
|
+
* nonce: 69n,
|
|
286
|
+
* preVerificationGas: 100_000n,
|
|
287
|
+
* sender: '0x9f1fdab6458c5fc642fa0f4c5af7473c46837357',
|
|
288
|
+
* verificationGasLimit: 100_000n,
|
|
289
|
+
* })
|
|
290
|
+
*
|
|
291
|
+
* const payload = UserOperation.getSignPayload(userOperation, { // [!code focus]
|
|
292
|
+
* chainId: 1, // [!code focus]
|
|
293
|
+
* entryPointAddress: '0x1234567890123456789012345678901234567890', // [!code focus]
|
|
294
|
+
* entryPointVersion: '0.6', // [!code focus]
|
|
295
|
+
* }) // [!code focus]
|
|
296
|
+
*
|
|
297
|
+
* const signature = Secp256k1.sign({ payload, privateKey: '0x...' })
|
|
298
|
+
* ```
|
|
299
|
+
*
|
|
300
|
+
* @param userOperation - The user operation to get the sign payload for.
|
|
301
|
+
* @returns The signing payload for the user operation.
|
|
302
|
+
*/
|
|
303
|
+
export function getSignPayload<
|
|
304
|
+
entrypointVersion extends EntryPoint.Version = EntryPoint.Version,
|
|
305
|
+
>(
|
|
306
|
+
userOperation: UserOperation<entrypointVersion>,
|
|
307
|
+
options: getSignPayload.Options<entrypointVersion>,
|
|
308
|
+
): Hex.Hex {
|
|
309
|
+
return hash(userOperation, options)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export declare namespace getSignPayload {
|
|
313
|
+
type Options<
|
|
314
|
+
entrypointVersion extends EntryPoint.Version = EntryPoint.Version,
|
|
315
|
+
> = hash.Options<entrypointVersion>
|
|
316
|
+
|
|
317
|
+
type ErrorType = hash.ErrorType | Errors.GlobalErrorType
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Hashes a {@link ox#UserOperation.UserOperation}. This is the "user operation hash".
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```ts twoslash
|
|
325
|
+
* import { Value } from 'ox'
|
|
326
|
+
* import { UserOperation } from 'ox/erc4337'
|
|
327
|
+
*
|
|
328
|
+
* const userOperation = UserOperation.hash({
|
|
329
|
+
* callData: '0xdeadbeef',
|
|
330
|
+
* callGasLimit: 300_000n,
|
|
331
|
+
* maxFeePerGas: Value.fromGwei('20'),
|
|
332
|
+
* maxPriorityFeePerGas: Value.fromGwei('2'),
|
|
333
|
+
* nonce: 69n,
|
|
334
|
+
* preVerificationGas: 100_000n,
|
|
335
|
+
* sender: '0x9f1fdab6458c5fc642fa0f4c5af7473c46837357',
|
|
336
|
+
* verificationGasLimit: 100_000n,
|
|
337
|
+
* }, {
|
|
338
|
+
* chainId: 1,
|
|
339
|
+
* entryPointAddress: '0x1234567890123456789012345678901234567890',
|
|
340
|
+
* entryPointVersion: '0.6',
|
|
341
|
+
* })
|
|
342
|
+
* ```
|
|
343
|
+
*
|
|
344
|
+
* @param userOperation - The user operation to hash.
|
|
345
|
+
* @returns The hash of the user operation.
|
|
346
|
+
*/
|
|
347
|
+
export function hash<
|
|
348
|
+
entrypointVersion extends EntryPoint.Version = EntryPoint.Version,
|
|
349
|
+
>(
|
|
350
|
+
userOperation: UserOperation<entrypointVersion>,
|
|
351
|
+
options: hash.Options<entrypointVersion>,
|
|
352
|
+
): Hex.Hex {
|
|
353
|
+
const { chainId, entryPointAddress, entryPointVersion } = options
|
|
354
|
+
const {
|
|
355
|
+
callData,
|
|
356
|
+
callGasLimit,
|
|
357
|
+
initCode,
|
|
358
|
+
factory,
|
|
359
|
+
factoryData,
|
|
360
|
+
maxFeePerGas,
|
|
361
|
+
maxPriorityFeePerGas,
|
|
362
|
+
nonce,
|
|
363
|
+
paymaster,
|
|
364
|
+
paymasterAndData,
|
|
365
|
+
paymasterData,
|
|
366
|
+
paymasterPostOpGasLimit,
|
|
367
|
+
paymasterVerificationGasLimit,
|
|
368
|
+
preVerificationGas,
|
|
369
|
+
sender,
|
|
370
|
+
verificationGasLimit,
|
|
371
|
+
} = userOperation as UserOperation
|
|
372
|
+
|
|
373
|
+
const packedUserOp = (() => {
|
|
374
|
+
if (entryPointVersion === '0.6') {
|
|
375
|
+
return AbiParameters.encode(
|
|
376
|
+
[
|
|
377
|
+
{ type: 'address' },
|
|
378
|
+
{ type: 'uint256' },
|
|
379
|
+
{ type: 'bytes32' },
|
|
380
|
+
{ type: 'bytes32' },
|
|
381
|
+
{ type: 'uint256' },
|
|
382
|
+
{ type: 'uint256' },
|
|
383
|
+
{ type: 'uint256' },
|
|
384
|
+
{ type: 'uint256' },
|
|
385
|
+
{ type: 'uint256' },
|
|
386
|
+
{ type: 'bytes32' },
|
|
387
|
+
],
|
|
388
|
+
[
|
|
389
|
+
sender,
|
|
390
|
+
nonce,
|
|
391
|
+
Hash.keccak256(initCode ?? '0x'),
|
|
392
|
+
Hash.keccak256(callData),
|
|
393
|
+
callGasLimit,
|
|
394
|
+
verificationGasLimit,
|
|
395
|
+
preVerificationGas,
|
|
396
|
+
maxFeePerGas,
|
|
397
|
+
maxPriorityFeePerGas,
|
|
398
|
+
Hash.keccak256(paymasterAndData ?? '0x'),
|
|
399
|
+
],
|
|
400
|
+
)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (entryPointVersion === '0.7') {
|
|
404
|
+
const accountGasLimits = Hex.concat(
|
|
405
|
+
Hex.padLeft(Hex.fromNumber(verificationGasLimit), 16),
|
|
406
|
+
Hex.padLeft(Hex.fromNumber(callGasLimit), 16),
|
|
407
|
+
)
|
|
408
|
+
const gasFees = Hex.concat(
|
|
409
|
+
Hex.padLeft(Hex.fromNumber(maxPriorityFeePerGas), 16),
|
|
410
|
+
Hex.padLeft(Hex.fromNumber(maxFeePerGas), 16),
|
|
411
|
+
)
|
|
412
|
+
const initCode_hashed = Hash.keccak256(
|
|
413
|
+
factory && factoryData ? Hex.concat(factory, factoryData) : '0x',
|
|
414
|
+
)
|
|
415
|
+
const paymasterAndData_hashed = Hash.keccak256(
|
|
416
|
+
paymaster
|
|
417
|
+
? Hex.concat(
|
|
418
|
+
paymaster,
|
|
419
|
+
Hex.padLeft(
|
|
420
|
+
Hex.fromNumber(paymasterVerificationGasLimit || 0),
|
|
421
|
+
16,
|
|
422
|
+
),
|
|
423
|
+
Hex.padLeft(Hex.fromNumber(paymasterPostOpGasLimit || 0), 16),
|
|
424
|
+
paymasterData || '0x',
|
|
425
|
+
)
|
|
426
|
+
: '0x',
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
return AbiParameters.encode(
|
|
430
|
+
[
|
|
431
|
+
{ type: 'address' },
|
|
432
|
+
{ type: 'uint256' },
|
|
433
|
+
{ type: 'bytes32' },
|
|
434
|
+
{ type: 'bytes32' },
|
|
435
|
+
{ type: 'bytes32' },
|
|
436
|
+
{ type: 'uint256' },
|
|
437
|
+
{ type: 'bytes32' },
|
|
438
|
+
{ type: 'bytes32' },
|
|
439
|
+
],
|
|
440
|
+
[
|
|
441
|
+
sender,
|
|
442
|
+
nonce,
|
|
443
|
+
initCode_hashed,
|
|
444
|
+
Hash.keccak256(callData),
|
|
445
|
+
accountGasLimits,
|
|
446
|
+
preVerificationGas,
|
|
447
|
+
gasFees,
|
|
448
|
+
paymasterAndData_hashed,
|
|
449
|
+
],
|
|
450
|
+
)
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
throw new Error(`entryPointVersion "${entryPointVersion}" not supported.`)
|
|
454
|
+
})()
|
|
455
|
+
|
|
456
|
+
return Hash.keccak256(
|
|
457
|
+
AbiParameters.encode(
|
|
458
|
+
[{ type: 'bytes32' }, { type: 'address' }, { type: 'uint256' }],
|
|
459
|
+
[Hash.keccak256(packedUserOp), entryPointAddress, BigInt(chainId)],
|
|
460
|
+
),
|
|
461
|
+
)
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export declare namespace hash {
|
|
465
|
+
type Options<
|
|
466
|
+
entrypointVersion extends EntryPoint.Version = EntryPoint.Version,
|
|
467
|
+
> = {
|
|
468
|
+
chainId: number
|
|
469
|
+
entryPointAddress: Address.Address
|
|
470
|
+
entryPointVersion: entrypointVersion | EntryPoint.Version
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
type ErrorType =
|
|
474
|
+
| AbiParameters.encode.ErrorType
|
|
475
|
+
| Hash.keccak256.ErrorType
|
|
476
|
+
| Hex.concat.ErrorType
|
|
477
|
+
| Hex.fromNumber.ErrorType
|
|
478
|
+
| Hex.padLeft.ErrorType
|
|
479
|
+
| Errors.GlobalErrorType
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Transforms a User Operation into "packed" format.
|
|
484
|
+
*
|
|
485
|
+
* @example
|
|
486
|
+
* ```ts twoslash
|
|
487
|
+
* import { Value } from 'ox'
|
|
488
|
+
* import { UserOperation } from 'ox/erc4337'
|
|
489
|
+
*
|
|
490
|
+
* const packed = UserOperation.toPacked({
|
|
491
|
+
* callData: '0xdeadbeef',
|
|
492
|
+
* callGasLimit: 300_000n,
|
|
493
|
+
* maxFeePerGas: Value.fromGwei('20'),
|
|
494
|
+
* maxPriorityFeePerGas: Value.fromGwei('2'),
|
|
495
|
+
* nonce: 69n,
|
|
496
|
+
* preVerificationGas: 100_000n,
|
|
497
|
+
* sender: '0x9f1fdab6458c5fc642fa0f4c5af7473c46837357',
|
|
498
|
+
* signature: '0x...',
|
|
499
|
+
* verificationGasLimit: 100_000n,
|
|
500
|
+
* })
|
|
501
|
+
* ```
|
|
502
|
+
*
|
|
503
|
+
* @param userOperation - The user operation to transform.
|
|
504
|
+
* @returns The packed user operation.
|
|
505
|
+
*/
|
|
506
|
+
export function toPacked(userOperation: UserOperation<'0.7', true>): Packed {
|
|
507
|
+
const {
|
|
508
|
+
callGasLimit,
|
|
509
|
+
callData,
|
|
510
|
+
factory,
|
|
511
|
+
factoryData,
|
|
512
|
+
maxPriorityFeePerGas,
|
|
513
|
+
maxFeePerGas,
|
|
514
|
+
nonce,
|
|
515
|
+
paymaster,
|
|
516
|
+
paymasterData,
|
|
517
|
+
paymasterPostOpGasLimit,
|
|
518
|
+
paymasterVerificationGasLimit,
|
|
519
|
+
sender,
|
|
520
|
+
signature,
|
|
521
|
+
verificationGasLimit,
|
|
522
|
+
} = userOperation
|
|
523
|
+
|
|
524
|
+
const accountGasLimits = Hex.concat(
|
|
525
|
+
Hex.padLeft(Hex.fromNumber(verificationGasLimit || 0n), 16),
|
|
526
|
+
Hex.padLeft(Hex.fromNumber(callGasLimit || 0n), 16),
|
|
527
|
+
)
|
|
528
|
+
const initCode =
|
|
529
|
+
factory && factoryData ? Hex.concat(factory, factoryData) : '0x'
|
|
530
|
+
const gasFees = Hex.concat(
|
|
531
|
+
Hex.padLeft(Hex.fromNumber(maxPriorityFeePerGas || 0n), 16),
|
|
532
|
+
Hex.padLeft(Hex.fromNumber(maxFeePerGas || 0n), 16),
|
|
533
|
+
)
|
|
534
|
+
const paymasterAndData = paymaster
|
|
535
|
+
? Hex.concat(
|
|
536
|
+
paymaster,
|
|
537
|
+
Hex.padLeft(Hex.fromNumber(paymasterVerificationGasLimit || 0n), 16),
|
|
538
|
+
Hex.padLeft(Hex.fromNumber(paymasterPostOpGasLimit || 0n), 16),
|
|
539
|
+
paymasterData || '0x',
|
|
540
|
+
)
|
|
541
|
+
: '0x'
|
|
542
|
+
const preVerificationGas = userOperation.preVerificationGas ?? 0n
|
|
543
|
+
|
|
544
|
+
return {
|
|
545
|
+
accountGasLimits,
|
|
546
|
+
callData,
|
|
547
|
+
initCode,
|
|
548
|
+
gasFees,
|
|
549
|
+
nonce,
|
|
550
|
+
paymasterAndData,
|
|
551
|
+
preVerificationGas,
|
|
552
|
+
sender,
|
|
553
|
+
signature,
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export declare namespace toPacked {
|
|
558
|
+
export type ErrorType = Errors.GlobalErrorType
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Converts a {@link ox#UserOperation.UserOperation} to a {@link ox#UserOperation.Rpc}.
|
|
563
|
+
*
|
|
564
|
+
* @example
|
|
565
|
+
* ```ts twoslash
|
|
566
|
+
* import { Value } from 'ox'
|
|
567
|
+
* import { UserOperation } from 'ox/erc4337'
|
|
568
|
+
*
|
|
569
|
+
* const userOperation = UserOperation.toRpc({
|
|
570
|
+
* callData: '0xdeadbeef',
|
|
571
|
+
* callGasLimit: 300_000n,
|
|
572
|
+
* maxFeePerGas: Value.fromGwei('20'),
|
|
573
|
+
* maxPriorityFeePerGas: Value.fromGwei('2'),
|
|
574
|
+
* nonce: 69n,
|
|
575
|
+
* preVerificationGas: 100_000n,
|
|
576
|
+
* sender: '0x9f1fdab6458c5fc642fa0f4c5af7473c46837357',
|
|
577
|
+
* verificationGasLimit: 100_000n,
|
|
578
|
+
* })
|
|
579
|
+
* ```
|
|
580
|
+
*
|
|
581
|
+
* @param userOperation - The user operation to convert.
|
|
582
|
+
* @returns An RPC-formatted user operation.
|
|
583
|
+
*/
|
|
584
|
+
export function toRpc(userOperation: UserOperation): Rpc {
|
|
585
|
+
const rpc = {} as Rpc
|
|
586
|
+
|
|
587
|
+
rpc.callData = userOperation.callData
|
|
588
|
+
rpc.callGasLimit = Hex.fromNumber(userOperation.callGasLimit)
|
|
589
|
+
rpc.maxFeePerGas = Hex.fromNumber(userOperation.maxFeePerGas)
|
|
590
|
+
rpc.maxPriorityFeePerGas = Hex.fromNumber(userOperation.maxPriorityFeePerGas)
|
|
591
|
+
rpc.nonce = Hex.fromNumber(userOperation.nonce)
|
|
592
|
+
rpc.preVerificationGas = Hex.fromNumber(userOperation.preVerificationGas)
|
|
593
|
+
rpc.sender = userOperation.sender
|
|
594
|
+
rpc.verificationGasLimit = Hex.fromNumber(userOperation.verificationGasLimit)
|
|
595
|
+
|
|
596
|
+
if (userOperation.factory) rpc.factory = userOperation.factory
|
|
597
|
+
if (userOperation.factoryData) rpc.factoryData = userOperation.factoryData
|
|
598
|
+
if (userOperation.initCode) rpc.initCode = userOperation.initCode
|
|
599
|
+
if (userOperation.paymaster) rpc.paymaster = userOperation.paymaster
|
|
600
|
+
if (userOperation.paymasterData)
|
|
601
|
+
rpc.paymasterData = userOperation.paymasterData
|
|
602
|
+
if (typeof userOperation.paymasterPostOpGasLimit === 'bigint')
|
|
603
|
+
rpc.paymasterPostOpGasLimit = Hex.fromNumber(
|
|
604
|
+
userOperation.paymasterPostOpGasLimit,
|
|
605
|
+
)
|
|
606
|
+
if (typeof userOperation.paymasterVerificationGasLimit === 'bigint')
|
|
607
|
+
rpc.paymasterVerificationGasLimit = Hex.fromNumber(
|
|
608
|
+
userOperation.paymasterVerificationGasLimit,
|
|
609
|
+
)
|
|
610
|
+
if (userOperation.signature) rpc.signature = userOperation.signature
|
|
611
|
+
|
|
612
|
+
return rpc
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
export declare namespace toRpc {
|
|
616
|
+
export type ErrorType = Hex.fromNumber.ErrorType | Errors.GlobalErrorType
|
|
617
|
+
}
|