@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.
- package/CHANGELOG.md +7 -0
- package/_cjs/helpers/abi.js +1049 -0
- package/_cjs/helpers/abi.js.map +1 -0
- package/_cjs/helpers/erc20-utils.js +52 -0
- package/_cjs/helpers/erc20-utils.js.map +1 -0
- package/_cjs/helpers/schema.js +263 -0
- package/_cjs/helpers/schema.js.map +1 -0
- package/_cjs/helpers/utils.js +38 -0
- package/_cjs/helpers/utils.js.map +1 -0
- package/_cjs/index.js +55 -0
- package/_cjs/index.js.map +1 -0
- package/_cjs/package.json +1 -0
- package/_cjs/relay.js +250 -0
- package/_cjs/relay.js.map +1 -0
- package/_cjs/singletonPaymasters.js +266 -0
- package/_cjs/singletonPaymasters.js.map +1 -0
- package/_esm/helpers/abi.js +1046 -0
- package/_esm/helpers/abi.js.map +1 -0
- package/_esm/helpers/erc20-utils.js +46 -0
- package/_esm/helpers/erc20-utils.js.map +1 -0
- package/_esm/helpers/schema.js +260 -0
- package/_esm/helpers/schema.js.map +1 -0
- package/_esm/helpers/utils.js +39 -0
- package/_esm/helpers/utils.js.map +1 -0
- package/_esm/index.js +52 -0
- package/_esm/index.js.map +1 -0
- package/_esm/package.json +1 -0
- package/_esm/relay.js +249 -0
- package/_esm/relay.js.map +1 -0
- package/_esm/singletonPaymasters.js +263 -0
- package/_esm/singletonPaymasters.js.map +1 -0
- package/_types/helpers/abi.d.ts +977 -0
- package/_types/helpers/abi.d.ts.map +1 -0
- package/_types/helpers/erc20-utils.d.ts +10 -0
- package/_types/helpers/erc20-utils.d.ts.map +1 -0
- package/_types/helpers/schema.d.ts +1091 -0
- package/_types/helpers/schema.d.ts.map +1 -0
- package/_types/helpers/utils.d.ts +15 -0
- package/_types/helpers/utils.d.ts.map +1 -0
- package/_types/index.d.ts +6 -0
- package/_types/index.d.ts.map +1 -0
- package/_types/relay.d.ts +86 -0
- package/_types/relay.d.ts.map +1 -0
- package/_types/singletonPaymasters.d.ts +93267 -0
- package/_types/singletonPaymasters.d.ts.map +1 -0
- package/helpers/abi.ts +1046 -0
- package/helpers/erc20-utils.ts +80 -0
- package/helpers/schema.ts +272 -0
- package/helpers/utils.ts +77 -0
- package/index.ts +78 -0
- package/package.json +38 -0
- package/relay.ts +430 -0
- 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>
|
package/helpers/utils.ts
ADDED
|
@@ -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
|
+
}
|