@pimlico/mock-paymaster 0.0.2

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 (53) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/_cjs/helpers/abi.js +1049 -0
  3. package/_cjs/helpers/abi.js.map +1 -0
  4. package/_cjs/helpers/erc20-utils.js +52 -0
  5. package/_cjs/helpers/erc20-utils.js.map +1 -0
  6. package/_cjs/helpers/schema.js +263 -0
  7. package/_cjs/helpers/schema.js.map +1 -0
  8. package/_cjs/helpers/utils.js +38 -0
  9. package/_cjs/helpers/utils.js.map +1 -0
  10. package/_cjs/index.js +55 -0
  11. package/_cjs/index.js.map +1 -0
  12. package/_cjs/package.json +1 -0
  13. package/_cjs/relay.js +250 -0
  14. package/_cjs/relay.js.map +1 -0
  15. package/_cjs/singletonPaymasters.js +266 -0
  16. package/_cjs/singletonPaymasters.js.map +1 -0
  17. package/_esm/helpers/abi.js +1046 -0
  18. package/_esm/helpers/abi.js.map +1 -0
  19. package/_esm/helpers/erc20-utils.js +46 -0
  20. package/_esm/helpers/erc20-utils.js.map +1 -0
  21. package/_esm/helpers/schema.js +260 -0
  22. package/_esm/helpers/schema.js.map +1 -0
  23. package/_esm/helpers/utils.js +39 -0
  24. package/_esm/helpers/utils.js.map +1 -0
  25. package/_esm/index.js +52 -0
  26. package/_esm/index.js.map +1 -0
  27. package/_esm/package.json +1 -0
  28. package/_esm/relay.js +249 -0
  29. package/_esm/relay.js.map +1 -0
  30. package/_esm/singletonPaymasters.js +263 -0
  31. package/_esm/singletonPaymasters.js.map +1 -0
  32. package/_types/helpers/abi.d.ts +977 -0
  33. package/_types/helpers/abi.d.ts.map +1 -0
  34. package/_types/helpers/erc20-utils.d.ts +10 -0
  35. package/_types/helpers/erc20-utils.d.ts.map +1 -0
  36. package/_types/helpers/schema.d.ts +1091 -0
  37. package/_types/helpers/schema.d.ts.map +1 -0
  38. package/_types/helpers/utils.d.ts +15 -0
  39. package/_types/helpers/utils.d.ts.map +1 -0
  40. package/_types/index.d.ts +6 -0
  41. package/_types/index.d.ts.map +1 -0
  42. package/_types/relay.d.ts +86 -0
  43. package/_types/relay.d.ts.map +1 -0
  44. package/_types/singletonPaymasters.d.ts +93267 -0
  45. package/_types/singletonPaymasters.d.ts.map +1 -0
  46. package/helpers/abi.ts +1046 -0
  47. package/helpers/erc20-utils.ts +80 -0
  48. package/helpers/schema.ts +272 -0
  49. package/helpers/utils.ts +77 -0
  50. package/index.ts +78 -0
  51. package/package.json +38 -0
  52. package/relay.ts +430 -0
  53. package/singletonPaymasters.ts +381 -0
@@ -0,0 +1,80 @@
1
+ import {
2
+ type Account,
3
+ type Address,
4
+ type Chain,
5
+ type PublicClient,
6
+ type Transport,
7
+ type WalletClient,
8
+ concat,
9
+ encodeFunctionData,
10
+ getCreate2Address,
11
+ hexToBigInt,
12
+ pad,
13
+ parseAbi,
14
+ toHex
15
+ } from "viem"
16
+ import { getAnvilWalletClient, getPublicClient } from "./utils.js"
17
+
18
+ const ERC20_BYTECODE = concat([
19
+ "0x60a060405234801561001057600080fd5b50604051610ff0380380610ff083398101604081905261002f9161022c565b6040518060400160405280600981526020016805465737445524332360bc1b8152506040518060400160405280600381526020016205432360ec1b815250816003908161007c919061034d565b506004610089828261034d565b5050506100a63369d3c21bcecceda10000006100b160201b60201c565b60ff166080526104a3565b6001600160a01b0382166100e457600060405163ec442f0560e01b81526004016100db9190610430565b60405180910390fd5b6100f0600083836100f4565b5050565b6001600160a01b03831661011f5780600260008282546101149190610454565b9091555061017e9050565b6001600160a01b0383166000908152602081905260409020548181101561015f5783818360405163391434e360e21b81526004016100db9392919061046d565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b03821661019a576002805482900390556101b9565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516101fc9190610495565b60405180910390a3505050565b60ff8116811461021857600080fd5b50565b805161022681610209565b92915050565b60006020828403121561024157610241600080fd5b600061024d848461021b565b949350505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052602260045260246000fd5b60028104600182168061029557607f821691505b6020821081036102a7576102a761026b565b50919050565b60006102266102b98381565b90565b6102c5836102ad565b815460001960089490940293841b1916921b91909117905550565b60006102ed8184846102bc565b505050565b818110156100f0576103056000826102e0565b6001016102f2565b601f8211156102ed576000818152602090206020601f850104810160208510156103345750805b6103466020601f8601048301826102f2565b5050505050565b81516001600160401b0381111561036657610366610255565b6103708254610281565b61037b82828561030d565b6020601f8311600181146103af57600084156103975750858201515b600019600886021c1981166002860217865550610408565b600085815260208120601f198616915b828110156103df57888501518255602094850194600190920191016103bf565b868310156103fb5784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b60006001600160a01b038216610226565b61042a81610410565b82525050565b602081016102268284610421565b634e487b7160e01b600052601160045260246000fd5b808201808211156102265761022661043e565b8061042a565b6060810161047b8286610421565b6104886020830185610467565b61024d6040830184610467565b602081016102268284610467565b608051610b326104be60003960006101650152610b326000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c8063313ce56711610081578063a9059cbb1161005b578063a9059cbb146101cf578063dd62ed3e146101e2578063fb4dcefa1461022857600080fd5b8063313ce5671461016357806370a082311461019157806395d89b41146101c757600080fd5b806318160ddd116100b257806318160ddd1461012c57806323b872dd1461013d5780632d688ca81461015057600080fd5b806305ea5c22146100d957806306fdde03146100ee578063095ea7b31461010c575b600080fd5b6100ec6100e7366004610868565b61023b565b005b6100f661024b565b604051610103919061092c565b60405180910390f35b61011f61011a366004610944565b6102dd565b604051610103919061098b565b6002545b604051610103919061099f565b61011f61014b366004610868565b6102f7565b6100ec61015e366004610944565b61031b565b7f000000000000000000000000000000000000000000000000000000000000000060405161010391906109b6565b61013061019f3660046109c4565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6100f6610329565b61011f6101dd366004610944565b610338565b6101306101f03660046109ed565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6100ec6102363660046109ed565b610346565b61024683838361037c565b505050565b60606003805461025a90610a4f565b80601f016020809104026020016040519081016040528092919081815260200182805461028690610a4f565b80156102d35780601f106102a8576101008083540402835291602001916102d3565b820191906000526020600020905b8154815290600101906020018083116102b657829003601f168201915b5050505050905090565b6000336102eb81858561037c565b60019150505b92915050565b600033610305858285610389565b610310858585610441565b506001949350505050565b61032582826104ec565b5050565b60606004805461025a90610a4f565b6000336102eb818585610441565b61032582826103778573ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b610441565b6102468383836001610548565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461043b578181101561042c578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040161042393929190610a84565b60405180910390fd5b61043b84848484036000610548565b50505050565b73ffffffffffffffffffffffffffffffffffffffff83166104915760006040517f96c6fd1e0000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b73ffffffffffffffffffffffffffffffffffffffff82166104e15760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b61024683838361068e565b73ffffffffffffffffffffffffffffffffffffffff821661053c5760006040517fec442f050000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b6103256000838361068e565b73ffffffffffffffffffffffffffffffffffffffff84166105985760006040517fe602df050000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b73ffffffffffffffffffffffffffffffffffffffff83166105e85760006040517f94280d620000000000000000000000000000000000000000000000000000000081526004016104239190610aac565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600160209081526040808320938716835292905220829055801561043b578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610680919061099f565b60405180910390a350505050565b73ffffffffffffffffffffffffffffffffffffffff83166106c65780600260008282546106bb9190610ae9565b909155506107589050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020548181101561072c578381836040517fe450d38c00000000000000000000000000000000000000000000000000000000815260040161042393929190610a84565b73ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090209082900390555b73ffffffffffffffffffffffffffffffffffffffff8216610781576002805482900390556107ad565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090208054820190555b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161080a919061099f565b60405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff82166102f1565b61083e81610817565b811461084957600080fd5b50565b80356102f181610835565b8061083e565b80356102f181610857565b60008060006060848603121561088057610880600080fd5b600061088c868661084c565b935050602061089d8682870161084c565b92505060406108ae8682870161085d565b9150509250925092565b60005b838110156108d35781810151838201526020016108bb565b50506000910152565b60006108e6825190565b8084526020840193506108fd8185602086016108b8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920192915050565b6020808252810161093d81846108dc565b9392505050565b6000806040838503121561095a5761095a600080fd5b6000610966858561084c565b92505060206109778582860161085d565b9150509250929050565b8015155b82525050565b602081016102f18284610981565b80610985565b602081016102f18284610999565b60ff8116610985565b602081016102f182846109ad565b6000602082840312156109d9576109d9600080fd5b60006109e5848461084c565b949350505050565b60008060408385031215610a0357610a03600080fd5b6000610a0f858561084c565b92505060206109778582860161084c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600281046001821680610a6357607f821691505b602082108103610a7557610a75610a20565b50919050565b61098581610817565b60608101610a928286610a7b565b610a9f6020830185610999565b6109e56040830184610999565b602081016102f18284610a7b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102f1576102f1610aba56fea2646970667358221220d40f68e247510ec8b7876d327ac47b949de248d0626aaf2670151c5e84ee6b4a64736f6c634300081a0033",
20
+ pad(toHex(18n)) // constructor args (token_decimals)
21
+ ])
22
+
23
+ export const deployErc20Token = async (
24
+ walletClient: WalletClient<Transport, Chain, Account>,
25
+ publicClient: PublicClient
26
+ ) => {
27
+ if (
28
+ (await publicClient.getCode({ address: ERC20_ADDRESS })) === undefined
29
+ ) {
30
+ await walletClient.sendTransaction({
31
+ to: "0x4e59b44847b379578588920ca78fbf26c0b4956c",
32
+ data: concat([
33
+ "0x0000000000000000000000000000000000000000000000000000000000000000",
34
+ ERC20_BYTECODE
35
+ ])
36
+ })
37
+ }
38
+ }
39
+
40
+ export const tokenBalanceOf = async (holder: Address, anvilRpc: string) => {
41
+ const publicClient = getPublicClient(anvilRpc)
42
+
43
+ const balance = await publicClient.call({
44
+ to: ERC20_ADDRESS,
45
+ value: 0n,
46
+ data: encodeFunctionData({
47
+ abi: parseAbi(["function balanceOf(address)"]),
48
+ args: [holder]
49
+ })
50
+ })
51
+
52
+ return hexToBigInt(balance.data ?? "0x")
53
+ }
54
+
55
+ export const sudoMintTokens = async ({
56
+ amount,
57
+ to,
58
+ anvilRpc
59
+ }: {
60
+ amount: bigint
61
+ to: Address
62
+ anvilRpc: string
63
+ }) => {
64
+ const walletClient = getAnvilWalletClient({ addressIndex: 0, anvilRpc })
65
+
66
+ await walletClient.sendTransaction({
67
+ to: ERC20_ADDRESS,
68
+ value: 0n,
69
+ data: encodeFunctionData({
70
+ abi: parseAbi(["function sudoMint(address, uint256)"]),
71
+ args: [to, amount]
72
+ })
73
+ })
74
+ }
75
+
76
+ export const ERC20_ADDRESS = getCreate2Address({
77
+ from: "0x4e59b44847b379578588920ca78fbf26c0b4956c",
78
+ salt: "0x0000000000000000000000000000000000000000000000000000000000000000",
79
+ bytecode: ERC20_BYTECODE
80
+ })
@@ -0,0 +1,272 @@
1
+ import { type Hex, getAddress } from "viem"
2
+ import { z, type infer as zodInfer } from "zod"
3
+
4
+ export enum ValidationErrors {
5
+ InvalidFields = -32602,
6
+ InsufficientBalance = -32603,
7
+ UnsupportedEntryPoint = -32604
8
+ }
9
+
10
+ export class InternalBundlerError extends Error {
11
+ constructor(msg?: string) {
12
+ let message = msg
13
+ if (!msg) {
14
+ message = "Internal error from bundler"
15
+ }
16
+ super(message)
17
+ }
18
+ }
19
+
20
+ export class RpcError extends Error {
21
+ // error codes from: https://eips.ethereum.org/EIPS/eip-1474
22
+ constructor(
23
+ msg: string,
24
+ readonly code?: number,
25
+ readonly data: unknown = undefined
26
+ ) {
27
+ super(msg)
28
+ }
29
+ }
30
+
31
+ const hexDataPattern = /^0x[0-9A-Fa-f]*$/
32
+ const addressPattern = /^0x[0-9,a-f,A-F]{40}$/
33
+
34
+ export const addressSchema = z
35
+ .string()
36
+ .regex(addressPattern, { message: "not a valid hex address" })
37
+ .transform((val) => getAddress(val))
38
+
39
+ export const hexNumberSchema = z
40
+ .string()
41
+ .regex(hexDataPattern)
42
+ .or(z.number())
43
+ .or(z.bigint())
44
+ .superRefine((data, ctx) => {
45
+ // This function is used to refine the input and provide a context where you have access to the path.
46
+ try {
47
+ BigInt(data) // Attempt to convert to BigInt to validate it can be done
48
+ } catch {
49
+ ctx.addIssue({
50
+ code: "custom",
51
+ message:
52
+ "Invalid input, expected a value that can be converted to bigint."
53
+ })
54
+ }
55
+ })
56
+ .transform((val) => BigInt(val))
57
+
58
+ export const hexDataSchema = z
59
+ .string()
60
+ .regex(hexDataPattern, { message: "not valid hex data" })
61
+ .transform((val) => val.toLowerCase() as Hex)
62
+
63
+ const userOperationSchemaPaymasterV6 = z
64
+ .object({
65
+ sender: addressSchema,
66
+ nonce: hexNumberSchema,
67
+ initCode: hexDataSchema,
68
+ callData: hexDataSchema,
69
+ callGasLimit: hexNumberSchema.default(1n),
70
+ verificationGasLimit: hexNumberSchema.default(1n),
71
+ preVerificationGas: hexNumberSchema.default(1n),
72
+ maxPriorityFeePerGas: hexNumberSchema,
73
+ maxFeePerGas: hexNumberSchema,
74
+ paymasterAndData: hexDataSchema
75
+ .nullable()
76
+ .optional()
77
+ .transform((val) => val ?? undefined),
78
+ signature: hexDataSchema.optional().transform((val) => {
79
+ if (val === undefined) {
80
+ return "0x"
81
+ }
82
+ return val
83
+ })
84
+ })
85
+ .strict()
86
+ .transform((val) => {
87
+ return val
88
+ })
89
+
90
+ const userOperationSchemaPaymasterV7 = z
91
+ .object({
92
+ sender: addressSchema,
93
+ nonce: hexNumberSchema,
94
+ factory: addressSchema.optional().transform((val) => val ?? undefined),
95
+ factoryData: hexDataSchema
96
+ .optional()
97
+ .transform((val) => val ?? undefined),
98
+ callData: hexDataSchema,
99
+ callGasLimit: hexNumberSchema.default(1n),
100
+ verificationGasLimit: hexNumberSchema.default(1n),
101
+ preVerificationGas: hexNumberSchema.default(1n),
102
+ maxFeePerGas: hexNumberSchema,
103
+ maxPriorityFeePerGas: hexNumberSchema,
104
+ paymaster: addressSchema
105
+ .nullable()
106
+ .optional()
107
+ .transform((val) => val ?? undefined),
108
+ paymasterVerificationGasLimit: hexNumberSchema
109
+ .nullable()
110
+ .optional()
111
+ .transform((val) => val ?? undefined),
112
+ paymasterPostOpGasLimit: hexNumberSchema
113
+ .nullable()
114
+ .optional()
115
+ .transform((val) => val ?? undefined),
116
+ paymasterData: hexDataSchema
117
+ .nullable()
118
+ .optional()
119
+ .transform((val) => val ?? undefined),
120
+ signature: hexDataSchema.optional().transform((val) => {
121
+ if (val === undefined) {
122
+ return "0x"
123
+ }
124
+ return val
125
+ })
126
+ })
127
+ .strict()
128
+ .transform((val) => {
129
+ return val
130
+ })
131
+
132
+ export const jsonRpcResultSchema = z
133
+ .object({
134
+ jsonrpc: z.literal("2.0"),
135
+ id: z.number(),
136
+ result: z.unknown()
137
+ })
138
+ .strict()
139
+
140
+ export const jsonRpcSchema = z
141
+ .object({
142
+ jsonrpc: z.literal("2.0"),
143
+ id: z.number(),
144
+ method: z.string(),
145
+ params: z.array(z.unknown()).optional().default([])
146
+ })
147
+ .strict()
148
+
149
+ export const pmSponsorUserOperationParamsSchema = z.tuple([
150
+ z.union([userOperationSchemaPaymasterV6, userOperationSchemaPaymasterV7]),
151
+ addressSchema
152
+ ])
153
+
154
+ const eip7677UserOperationSchemaV6 = z
155
+ .object({
156
+ sender: addressSchema,
157
+ nonce: hexNumberSchema,
158
+ initCode: hexDataSchema,
159
+ callData: hexDataSchema,
160
+ callGasLimit: hexNumberSchema,
161
+ verificationGasLimit: hexNumberSchema,
162
+ preVerificationGas: hexNumberSchema,
163
+ maxPriorityFeePerGas: hexNumberSchema,
164
+ maxFeePerGas: hexNumberSchema,
165
+ paymasterAndData: hexDataSchema
166
+ .nullable()
167
+ .optional()
168
+ .transform((_) => {
169
+ return "0x" as Hex
170
+ }),
171
+ signature: hexDataSchema
172
+ .nullable()
173
+ .optional()
174
+ .transform((_) => {
175
+ return "0x" as Hex
176
+ })
177
+ })
178
+ .strict()
179
+ .transform((val) => {
180
+ return val
181
+ })
182
+
183
+ const eip7677UserOperationSchemaV7 = z
184
+ .object({
185
+ sender: addressSchema,
186
+ nonce: hexNumberSchema,
187
+ factory: addressSchema
188
+ .nullable()
189
+ .optional()
190
+ .transform((val) => val ?? null),
191
+ factoryData: hexDataSchema
192
+ .nullable()
193
+ .optional()
194
+ .transform((val) => val ?? null),
195
+ callData: hexDataSchema,
196
+ callGasLimit: hexNumberSchema,
197
+ verificationGasLimit: hexNumberSchema,
198
+ preVerificationGas: hexNumberSchema,
199
+ maxFeePerGas: hexNumberSchema,
200
+ maxPriorityFeePerGas: hexNumberSchema,
201
+ paymaster: addressSchema
202
+ .nullable()
203
+ .optional()
204
+ .transform((val) => val ?? null),
205
+ paymasterVerificationGasLimit: hexNumberSchema
206
+ .nullable()
207
+ .optional()
208
+ .transform((val) => val ?? null),
209
+ paymasterPostOpGasLimit: hexNumberSchema
210
+ .nullable()
211
+ .optional()
212
+ .transform((val) => val ?? null),
213
+ paymasterData: hexDataSchema
214
+ .nullable()
215
+ .optional()
216
+ .transform((val) => val ?? null),
217
+ signature: hexDataSchema.optional().transform((val) => {
218
+ if (val === undefined) {
219
+ return "0x"
220
+ }
221
+ return val
222
+ })
223
+ })
224
+ .strict()
225
+ .transform((val) => {
226
+ return val
227
+ })
228
+
229
+ const eip7677UserOperationSchema = z.union([
230
+ eip7677UserOperationSchemaV6,
231
+ eip7677UserOperationSchemaV7
232
+ ])
233
+
234
+ export const pmGetPaymasterData = z
235
+ .union([
236
+ z.tuple([
237
+ eip7677UserOperationSchema,
238
+ addressSchema,
239
+ hexNumberSchema,
240
+ z.union([z.object({ token: addressSchema }), z.null()])
241
+ ]),
242
+ z.tuple([eip7677UserOperationSchema, addressSchema, hexNumberSchema])
243
+ ])
244
+ .transform((val) => {
245
+ return [val[0], val[1], val[2], val[3] ?? null] as const
246
+ })
247
+
248
+ export const pmGetPaymasterStubDataParamsSchema = z
249
+ .union([
250
+ z.tuple([
251
+ eip7677UserOperationSchema,
252
+ addressSchema,
253
+ hexNumberSchema,
254
+ z.union([z.object({ token: addressSchema }), z.null()])
255
+ ]),
256
+ z.tuple([eip7677UserOperationSchema, addressSchema, hexNumberSchema])
257
+ ])
258
+ .transform((val) => {
259
+ return [val[0], val[1], val[2], val[3] ?? null] as const
260
+ })
261
+
262
+ export const pimlicoGetTokenQuotesSchema = z.tuple([
263
+ z.object({
264
+ tokens: z.array(addressSchema)
265
+ }),
266
+ addressSchema, // entryPoint
267
+ hexNumberSchema
268
+ ])
269
+
270
+ export type UserOperationV7 = zodInfer<typeof userOperationSchemaPaymasterV7>
271
+ export type UserOperationV6 = zodInfer<typeof userOperationSchemaPaymasterV6>
272
+ export type JsonRpcSchema = zodInfer<typeof jsonRpcSchema>
@@ -0,0 +1,77 @@
1
+ import {
2
+ http,
3
+ type Account,
4
+ type Address,
5
+ type Chain,
6
+ type PublicClient,
7
+ type Transport,
8
+ type WalletClient,
9
+ createPublicClient,
10
+ createWalletClient
11
+ } from "viem"
12
+ import { mnemonicToAccount } from "viem/accounts"
13
+ import { foundry } from "viem/chains"
14
+ import { ERC20_ADDRESS } from "./erc20-utils.js"
15
+ import { RpcError, ValidationErrors } from "./schema.js"
16
+
17
+ /// Returns the bigger of two BigInts.
18
+ export const maxBigInt = (a: bigint, b: bigint) => {
19
+ return a > b ? a : b
20
+ }
21
+
22
+ export const getPublicClient = (
23
+ anvilRpc: string
24
+ ): PublicClient<Transport, Chain> => {
25
+ const transport = http(anvilRpc, {
26
+ // onFetchRequest: async (req) => {
27
+ // console.log(await req.json(), "request")
28
+ // }
29
+ //onFetchResponse: async (response) => {
30
+ // console.log(await response.clone().json(), "response")
31
+ //}
32
+ })
33
+
34
+ return createPublicClient({
35
+ chain: foundry,
36
+ transport: transport,
37
+ pollingInterval: 100
38
+ })
39
+ }
40
+
41
+ export const getAnvilWalletClient = ({
42
+ addressIndex,
43
+ anvilRpc
44
+ }: { addressIndex: number; anvilRpc: string }): WalletClient<
45
+ Transport,
46
+ Chain,
47
+ Account
48
+ > => {
49
+ return createWalletClient({
50
+ account: mnemonicToAccount(
51
+ "test test test test test test test test test test test junk",
52
+ {
53
+ addressIndex
54
+ }
55
+ ),
56
+ chain: foundry,
57
+ transport: http(anvilRpc)
58
+ })
59
+ }
60
+
61
+ export const isTokenSupported = async (token: Address) => {
62
+ if (token !== ERC20_ADDRESS) {
63
+ throw new RpcError(
64
+ "Token is not supported",
65
+ ValidationErrors.InvalidFields
66
+ )
67
+ }
68
+ }
69
+
70
+ export type PaymasterMode =
71
+ | {
72
+ mode: "verifying"
73
+ }
74
+ | {
75
+ mode: "erc20"
76
+ token: Address
77
+ }
package/index.ts ADDED
@@ -0,0 +1,78 @@
1
+ import cors from "@fastify/cors"
2
+ import Fastify from "fastify"
3
+ import { defineInstance } from "prool"
4
+ import { http, createPublicClient } from "viem"
5
+ import { createBundlerClient } from "viem/account-abstraction"
6
+ import { foundry } from "viem/chains"
7
+ import { deployErc20Token } from "./helpers/erc20-utils.js"
8
+ import { getAnvilWalletClient } from "./helpers/utils.js"
9
+ import { createRpcHandler } from "./relay.js"
10
+ import {
11
+ SingletonPaymasterV06,
12
+ SingletonPaymasterV07
13
+ } from "./singletonPaymasters.js"
14
+
15
+ export const paymaster = defineInstance(
16
+ ({
17
+ anvilRpc,
18
+ port: _port,
19
+ altoRpc
20
+ }: { anvilRpc: string; port: number; altoRpc: string }) => {
21
+ const app = Fastify({})
22
+
23
+ return {
24
+ _internal: {},
25
+ host: "localhost",
26
+ port: _port,
27
+ name: "mock-paymaster",
28
+ start: async ({ port = _port }) => {
29
+ const walletClient = getAnvilWalletClient({
30
+ anvilRpc,
31
+ addressIndex: 1
32
+ })
33
+ const publicClient = createPublicClient({
34
+ transport: http(anvilRpc),
35
+ chain: foundry
36
+ })
37
+ const bundler = createBundlerClient({
38
+ chain: foundry,
39
+ transport: http(altoRpc)
40
+ })
41
+
42
+ const singletonPaymasterV07 = new SingletonPaymasterV07(
43
+ walletClient,
44
+ anvilRpc
45
+ )
46
+ const singletonPaymasterV06 = new SingletonPaymasterV06(
47
+ walletClient,
48
+ anvilRpc
49
+ )
50
+
51
+ await singletonPaymasterV06.setup()
52
+ await singletonPaymasterV07.setup()
53
+ await deployErc20Token(walletClient, publicClient)
54
+
55
+ app.register(cors, {
56
+ origin: "*",
57
+ methods: ["POST", "GET", "OPTIONS"]
58
+ })
59
+
60
+ const rpcHandler = createRpcHandler(
61
+ bundler,
62
+ singletonPaymasterV07,
63
+ singletonPaymasterV06
64
+ )
65
+ app.post("/", {}, rpcHandler)
66
+
67
+ app.get("/ping", async (_request, reply) => {
68
+ return reply.code(200).send({ message: "pong" })
69
+ })
70
+
71
+ await app.listen({ host: "localhost", port })
72
+ },
73
+ stop: async () => {
74
+ app.close()
75
+ }
76
+ }
77
+ }
78
+ )
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@pimlico/mock-paymaster",
3
+ "version": "0.0.2",
4
+ "author": "Pimlico",
5
+ "homepage": "https://docs.pimlico.io/permissionless",
6
+ "repository": "github:pimlicolabs/permissionless.js",
7
+ "main": "./_cjs/index.js",
8
+ "module": "./_esm/index.js",
9
+ "types": "./_types/index.d.ts",
10
+ "typings": "./_types/index.d.ts",
11
+ "type": "module",
12
+ "sideEffects": false,
13
+ "description": "A utility library that allows you to create a mock-paymaster instance with Prool",
14
+ "keywords": [
15
+ "ethereum",
16
+ "erc-4337",
17
+ "eip-4337",
18
+ "paymaster",
19
+ "prool"
20
+ ],
21
+ "license": "MIT",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./_types/index.d.ts",
25
+ "import": "./_esm/index.js",
26
+ "default": "./_cjs/index.js"
27
+ }
28
+ },
29
+ "peerDependencies": {
30
+ "viem": "^2.23.2",
31
+ "prool": "^0.0.23"
32
+ },
33
+ "dependencies": {
34
+ "@fastify/cors": "^11.0.0",
35
+ "fastify": "^5.2.1",
36
+ "zod": "^3.24.2"
37
+ }
38
+ }