permissionless 0.0.13 → 0.0.15
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 +15 -0
- package/_cjs/accounts/index.js +3 -1
- package/_cjs/accounts/index.js.map +1 -1
- package/_cjs/accounts/kernel/abi/KernelAccountAbi.js +84 -0
- package/_cjs/accounts/kernel/abi/KernelAccountAbi.js.map +1 -0
- package/_cjs/accounts/kernel/signerToEcdsaKernelSmartAccount.js +211 -0
- package/_cjs/accounts/kernel/signerToEcdsaKernelSmartAccount.js.map +1 -0
- package/_cjs/accounts/signerToSafeSmartAccount.js +2 -2
- package/_cjs/actions/pimlico/sponsorUserOperation.js +12 -4
- package/_cjs/actions/pimlico/sponsorUserOperation.js.map +1 -1
- package/_cjs/actions/pimlico/validateSponsorshipPolicies.js +16 -0
- package/_cjs/actions/pimlico/validateSponsorshipPolicies.js.map +1 -0
- package/_cjs/actions/pimlico.js +3 -1
- package/_cjs/actions/pimlico.js.map +1 -1
- package/_cjs/clients/createSmartAccountClient.js.map +1 -1
- package/_cjs/clients/decorators/pimlico.js +3 -1
- package/_cjs/clients/decorators/pimlico.js.map +1 -1
- package/_cjs/utils/getRequiredPrefund.js +12 -0
- package/_cjs/utils/getRequiredPrefund.js.map +1 -0
- package/_cjs/utils/index.js +3 -1
- package/_cjs/utils/index.js.map +1 -1
- package/_esm/accounts/index.js +2 -1
- package/_esm/accounts/index.js.map +1 -1
- package/_esm/accounts/kernel/abi/KernelAccountAbi.js +87 -0
- package/_esm/accounts/kernel/abi/KernelAccountAbi.js.map +1 -0
- package/_esm/accounts/kernel/signerToEcdsaKernelSmartAccount.js +262 -0
- package/_esm/accounts/kernel/signerToEcdsaKernelSmartAccount.js.map +1 -0
- package/_esm/accounts/signerToSafeSmartAccount.js +2 -2
- package/_esm/actions/pimlico/sponsorUserOperation.js +13 -5
- package/_esm/actions/pimlico/sponsorUserOperation.js.map +1 -1
- package/_esm/actions/pimlico/validateSponsorshipPolicies.js +47 -0
- package/_esm/actions/pimlico/validateSponsorshipPolicies.js.map +1 -0
- package/_esm/actions/pimlico.js +2 -1
- package/_esm/actions/pimlico.js.map +1 -1
- package/_esm/clients/createSmartAccountClient.js +1 -1
- package/_esm/clients/createSmartAccountClient.js.map +1 -1
- package/_esm/clients/decorators/pimlico.js +38 -1
- package/_esm/clients/decorators/pimlico.js.map +1 -1
- package/_esm/utils/getRequiredPrefund.js +22 -0
- package/_esm/utils/getRequiredPrefund.js.map +1 -0
- package/_esm/utils/index.js +2 -1
- package/_esm/utils/index.js.map +1 -1
- package/_types/accounts/index.d.ts +2 -1
- package/_types/accounts/index.d.ts.map +1 -1
- package/_types/accounts/kernel/abi/KernelAccountAbi.d.ts +68 -0
- package/_types/accounts/kernel/abi/KernelAccountAbi.d.ts.map +1 -0
- package/_types/accounts/kernel/signerToEcdsaKernelSmartAccount.d.ts +25 -0
- package/_types/accounts/kernel/signerToEcdsaKernelSmartAccount.d.ts.map +1 -0
- package/_types/actions/pimlico/sponsorUserOperation.d.ts +4 -3
- package/_types/actions/pimlico/sponsorUserOperation.d.ts.map +1 -1
- package/_types/actions/pimlico/validateSponsorshipPolicies.d.ts +54 -0
- package/_types/actions/pimlico/validateSponsorshipPolicies.d.ts.map +1 -0
- package/_types/actions/pimlico.d.ts +4 -3
- package/_types/actions/pimlico.d.ts.map +1 -1
- package/_types/clients/createSmartAccountClient.d.ts +6 -1
- package/_types/clients/createSmartAccountClient.d.ts.map +1 -1
- package/_types/clients/decorators/pimlico.d.ts +40 -3
- package/_types/clients/decorators/pimlico.d.ts.map +1 -1
- package/_types/types/pimlico.d.ts +21 -1
- package/_types/types/pimlico.d.ts.map +1 -1
- package/_types/utils/getRequiredPrefund.d.ts +20 -0
- package/_types/utils/getRequiredPrefund.d.ts.map +1 -0
- package/_types/utils/index.d.ts +2 -1
- package/_types/utils/index.d.ts.map +1 -1
- package/accounts/index.ts +8 -1
- package/accounts/kernel/abi/KernelAccountAbi.ts +87 -0
- package/accounts/kernel/signerToEcdsaKernelSmartAccount.ts +363 -0
- package/accounts/signerToSafeSmartAccount.ts +2 -2
- package/actions/pimlico/sponsorUserOperation.ts +20 -7
- package/actions/pimlico/validateSponsorshipPolicies.ts +76 -0
- package/actions/pimlico.ts +13 -4
- package/clients/createSmartAccountClient.ts +6 -1
- package/clients/decorators/pimlico.ts +52 -5
- package/package.json +1 -1
- package/types/pimlico.ts +21 -1
- package/utils/getRequiredPrefund.ts +31 -0
- package/utils/index.ts +6 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Account,
|
|
3
|
+
type Address,
|
|
4
|
+
type Chain,
|
|
5
|
+
type Client,
|
|
6
|
+
type Hex,
|
|
7
|
+
type Transport,
|
|
8
|
+
concatHex,
|
|
9
|
+
encodeFunctionData,
|
|
10
|
+
isAddressEqual
|
|
11
|
+
} from "viem"
|
|
12
|
+
import { toAccount } from "viem/accounts"
|
|
13
|
+
import {
|
|
14
|
+
getBytecode,
|
|
15
|
+
getChainId,
|
|
16
|
+
readContract,
|
|
17
|
+
signMessage,
|
|
18
|
+
signTypedData
|
|
19
|
+
} from "viem/actions"
|
|
20
|
+
import { getAccountNonce } from "../../actions/public/getAccountNonce.js"
|
|
21
|
+
import { getSenderAddress } from "../../actions/public/getSenderAddress.js"
|
|
22
|
+
import { getUserOperationHash } from "../../utils/getUserOperationHash.js"
|
|
23
|
+
import type { SmartAccount } from "../types.js"
|
|
24
|
+
import {
|
|
25
|
+
SignTransactionNotSupportedBySmartAccount,
|
|
26
|
+
type SmartAccountSigner
|
|
27
|
+
} from "../types.js"
|
|
28
|
+
import { KernelExecuteAbi, KernelInitAbi } from "./abi/KernelAccountAbi.js"
|
|
29
|
+
|
|
30
|
+
export type KernelEcdsaSmartAccount<
|
|
31
|
+
transport extends Transport = Transport,
|
|
32
|
+
chain extends Chain | undefined = Chain | undefined
|
|
33
|
+
> = SmartAccount<"kernelEcdsaSmartAccount", transport, chain>
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The account creation ABI for a kernel smart account (from the KernelFactory)
|
|
37
|
+
*/
|
|
38
|
+
const createAccountAbi = [
|
|
39
|
+
{
|
|
40
|
+
inputs: [
|
|
41
|
+
{
|
|
42
|
+
internalType: "address",
|
|
43
|
+
name: "_implementation",
|
|
44
|
+
type: "address"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
internalType: "bytes",
|
|
48
|
+
name: "_data",
|
|
49
|
+
type: "bytes"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
internalType: "uint256",
|
|
53
|
+
name: "_index",
|
|
54
|
+
type: "uint256"
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
name: "createAccount",
|
|
58
|
+
outputs: [
|
|
59
|
+
{
|
|
60
|
+
internalType: "address",
|
|
61
|
+
name: "proxy",
|
|
62
|
+
type: "address"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
stateMutability: "payable",
|
|
66
|
+
type: "function"
|
|
67
|
+
}
|
|
68
|
+
] as const
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Default addresses for kernel smart account
|
|
72
|
+
*/
|
|
73
|
+
const KERNEL_ADDRESSES: {
|
|
74
|
+
ECDSA_VALIDATOR: Address
|
|
75
|
+
ACCOUNT_V2_2_LOGIC: Address
|
|
76
|
+
FACTORY_ADDRESS: Address
|
|
77
|
+
} = {
|
|
78
|
+
ECDSA_VALIDATOR: "0xd9AB5096a832b9ce79914329DAEE236f8Eea0390",
|
|
79
|
+
ACCOUNT_V2_2_LOGIC: "0x0DA6a956B9488eD4dd761E59f52FDc6c8068E6B5",
|
|
80
|
+
FACTORY_ADDRESS: "0x5de4839a76cf55d0c90e2061ef4386d962E15ae3"
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get the account initialization code for a kernel smart account
|
|
85
|
+
* @param owner
|
|
86
|
+
* @param index
|
|
87
|
+
* @param factoryAddress
|
|
88
|
+
* @param accountLogicAddress
|
|
89
|
+
* @param ecdsaValidatorAddress
|
|
90
|
+
*/
|
|
91
|
+
const getAccountInitCode = async ({
|
|
92
|
+
owner,
|
|
93
|
+
index,
|
|
94
|
+
factoryAddress,
|
|
95
|
+
accountLogicAddress,
|
|
96
|
+
ecdsaValidatorAddress
|
|
97
|
+
}: {
|
|
98
|
+
owner: Address
|
|
99
|
+
index: bigint
|
|
100
|
+
factoryAddress: Address
|
|
101
|
+
accountLogicAddress: Address
|
|
102
|
+
ecdsaValidatorAddress: Address
|
|
103
|
+
}): Promise<Hex> => {
|
|
104
|
+
if (!owner) throw new Error("Owner account not found")
|
|
105
|
+
|
|
106
|
+
// Build the account initialization data
|
|
107
|
+
const initialisationData = encodeFunctionData({
|
|
108
|
+
abi: KernelInitAbi,
|
|
109
|
+
functionName: "initialize",
|
|
110
|
+
args: [ecdsaValidatorAddress, owner]
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// Build the account init code
|
|
114
|
+
return concatHex([
|
|
115
|
+
factoryAddress,
|
|
116
|
+
encodeFunctionData({
|
|
117
|
+
abi: createAccountAbi,
|
|
118
|
+
functionName: "createAccount",
|
|
119
|
+
args: [accountLogicAddress, initialisationData, index]
|
|
120
|
+
}) as Hex
|
|
121
|
+
])
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Check the validity of an existing account address, or fetch the pre-deterministic account address for a kernel smart wallet
|
|
126
|
+
* @param client
|
|
127
|
+
* @param owner
|
|
128
|
+
* @param entryPoint
|
|
129
|
+
* @param ecdsaValidatorAddress
|
|
130
|
+
* @param initCodeProvider
|
|
131
|
+
* @param deployedAccountAddress
|
|
132
|
+
*/
|
|
133
|
+
const getAccountAddress = async <
|
|
134
|
+
TTransport extends Transport = Transport,
|
|
135
|
+
TChain extends Chain | undefined = Chain | undefined
|
|
136
|
+
>({
|
|
137
|
+
client,
|
|
138
|
+
owner,
|
|
139
|
+
entryPoint,
|
|
140
|
+
initCodeProvider,
|
|
141
|
+
ecdsaValidatorAddress,
|
|
142
|
+
deployedAccountAddress
|
|
143
|
+
}: {
|
|
144
|
+
client: Client<TTransport, TChain>
|
|
145
|
+
owner: Address
|
|
146
|
+
initCodeProvider: () => Promise<Hex>
|
|
147
|
+
entryPoint: Address
|
|
148
|
+
ecdsaValidatorAddress: Address
|
|
149
|
+
deployedAccountAddress?: Address
|
|
150
|
+
}): Promise<Address> => {
|
|
151
|
+
// If we got an already deployed account, ensure it's well deployed, and the validator & signer are correct
|
|
152
|
+
if (deployedAccountAddress !== undefined) {
|
|
153
|
+
// Get the owner of the deployed account, ensure it's the same as the owner given in params
|
|
154
|
+
const deployedAccountOwner = await readContract(client, {
|
|
155
|
+
address: ecdsaValidatorAddress,
|
|
156
|
+
abi: [
|
|
157
|
+
{
|
|
158
|
+
inputs: [
|
|
159
|
+
{
|
|
160
|
+
internalType: "address",
|
|
161
|
+
name: "",
|
|
162
|
+
type: "address"
|
|
163
|
+
}
|
|
164
|
+
],
|
|
165
|
+
name: "ecdsaValidatorStorage",
|
|
166
|
+
outputs: [
|
|
167
|
+
{
|
|
168
|
+
internalType: "address",
|
|
169
|
+
name: "owner",
|
|
170
|
+
type: "address"
|
|
171
|
+
}
|
|
172
|
+
],
|
|
173
|
+
stateMutability: "view",
|
|
174
|
+
type: "function"
|
|
175
|
+
}
|
|
176
|
+
],
|
|
177
|
+
functionName: "ecdsaValidatorStorage",
|
|
178
|
+
args: [deployedAccountAddress]
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
// Ensure the address match
|
|
182
|
+
if (!isAddressEqual(deployedAccountOwner, owner)) {
|
|
183
|
+
throw new Error("Invalid owner for the already deployed account")
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// If ok, return the address
|
|
187
|
+
return deployedAccountAddress
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Find the init code for this account
|
|
191
|
+
const initCode = await initCodeProvider()
|
|
192
|
+
|
|
193
|
+
// Get the sender address based on the init code
|
|
194
|
+
return getSenderAddress(client, {
|
|
195
|
+
initCode,
|
|
196
|
+
entryPoint
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Build a kernel smart account from a private key, that use the ECDSA signer behind the scene
|
|
202
|
+
* @param client
|
|
203
|
+
* @param privateKey
|
|
204
|
+
* @param entryPoint
|
|
205
|
+
* @param index
|
|
206
|
+
* @param factoryAddress
|
|
207
|
+
* @param accountLogicAddress
|
|
208
|
+
* @param ecdsaValidatorAddress
|
|
209
|
+
* @param deployedAccountAddress
|
|
210
|
+
*/
|
|
211
|
+
export async function signerToEcdsaKernelSmartAccount<
|
|
212
|
+
TTransport extends Transport = Transport,
|
|
213
|
+
TChain extends Chain | undefined = Chain | undefined
|
|
214
|
+
>(
|
|
215
|
+
client: Client<TTransport, TChain>,
|
|
216
|
+
{
|
|
217
|
+
signer,
|
|
218
|
+
entryPoint,
|
|
219
|
+
index = 0n,
|
|
220
|
+
factoryAddress = KERNEL_ADDRESSES.FACTORY_ADDRESS,
|
|
221
|
+
accountLogicAddress = KERNEL_ADDRESSES.ACCOUNT_V2_2_LOGIC,
|
|
222
|
+
ecdsaValidatorAddress = KERNEL_ADDRESSES.ECDSA_VALIDATOR,
|
|
223
|
+
deployedAccountAddress
|
|
224
|
+
}: {
|
|
225
|
+
signer: SmartAccountSigner
|
|
226
|
+
entryPoint: Address
|
|
227
|
+
index?: bigint
|
|
228
|
+
factoryAddress?: Address
|
|
229
|
+
accountLogicAddress?: Address
|
|
230
|
+
ecdsaValidatorAddress?: Address
|
|
231
|
+
deployedAccountAddress?: Address
|
|
232
|
+
}
|
|
233
|
+
): Promise<KernelEcdsaSmartAccount<TTransport, TChain>> {
|
|
234
|
+
// Get the private key related account
|
|
235
|
+
const viemSigner: Account =
|
|
236
|
+
signer.type === "local"
|
|
237
|
+
? ({
|
|
238
|
+
...signer,
|
|
239
|
+
signTransaction: (_, __) => {
|
|
240
|
+
throw new SignTransactionNotSupportedBySmartAccount()
|
|
241
|
+
}
|
|
242
|
+
} as Account)
|
|
243
|
+
: (signer as Account)
|
|
244
|
+
|
|
245
|
+
// Helper to generate the init code for the smart account
|
|
246
|
+
const generateInitCode = () =>
|
|
247
|
+
getAccountInitCode({
|
|
248
|
+
owner: viemSigner.address,
|
|
249
|
+
index,
|
|
250
|
+
factoryAddress,
|
|
251
|
+
accountLogicAddress,
|
|
252
|
+
ecdsaValidatorAddress
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
// Fetch account address and chain id
|
|
256
|
+
const [accountAddress, chainId] = await Promise.all([
|
|
257
|
+
getAccountAddress<TTransport, TChain>({
|
|
258
|
+
client,
|
|
259
|
+
entryPoint,
|
|
260
|
+
owner: viemSigner.address,
|
|
261
|
+
ecdsaValidatorAddress,
|
|
262
|
+
initCodeProvider: generateInitCode,
|
|
263
|
+
deployedAccountAddress
|
|
264
|
+
}),
|
|
265
|
+
getChainId(client)
|
|
266
|
+
])
|
|
267
|
+
|
|
268
|
+
if (!accountAddress) throw new Error("Account address not found")
|
|
269
|
+
|
|
270
|
+
// Build the EOA Signer
|
|
271
|
+
const account = toAccount({
|
|
272
|
+
address: accountAddress,
|
|
273
|
+
async signMessage({ message }) {
|
|
274
|
+
return signMessage(client, { account: viemSigner, message })
|
|
275
|
+
},
|
|
276
|
+
async signTransaction(_, __) {
|
|
277
|
+
throw new SignTransactionNotSupportedBySmartAccount()
|
|
278
|
+
},
|
|
279
|
+
async signTypedData(typedData) {
|
|
280
|
+
return signTypedData(client, { account: viemSigner, ...typedData })
|
|
281
|
+
}
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
return {
|
|
285
|
+
...account,
|
|
286
|
+
client: client,
|
|
287
|
+
publicKey: accountAddress,
|
|
288
|
+
entryPoint: entryPoint,
|
|
289
|
+
source: "kernelEcdsaSmartAccount",
|
|
290
|
+
|
|
291
|
+
// Get the nonce of the smart account
|
|
292
|
+
async getNonce() {
|
|
293
|
+
return getAccountNonce(client, {
|
|
294
|
+
sender: accountAddress,
|
|
295
|
+
entryPoint: entryPoint
|
|
296
|
+
})
|
|
297
|
+
},
|
|
298
|
+
|
|
299
|
+
// Sign a user operation
|
|
300
|
+
async signUserOperation(userOperation) {
|
|
301
|
+
const hash = getUserOperationHash({
|
|
302
|
+
userOperation: {
|
|
303
|
+
...userOperation,
|
|
304
|
+
signature: "0x"
|
|
305
|
+
},
|
|
306
|
+
entryPoint: entryPoint,
|
|
307
|
+
chainId: chainId
|
|
308
|
+
})
|
|
309
|
+
const signature = await signMessage(client, {
|
|
310
|
+
account: viemSigner,
|
|
311
|
+
message: { raw: hash }
|
|
312
|
+
})
|
|
313
|
+
// Always use the sudo mode, since we will use external paymaster
|
|
314
|
+
return concatHex(["0x00000000", signature])
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
// Encode the init code
|
|
318
|
+
async getInitCode() {
|
|
319
|
+
const contractCode = await getBytecode(client, {
|
|
320
|
+
address: accountAddress
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
if ((contractCode?.length ?? 0) > 2) return "0x"
|
|
324
|
+
|
|
325
|
+
return generateInitCode()
|
|
326
|
+
},
|
|
327
|
+
|
|
328
|
+
// Encode the deploy call data
|
|
329
|
+
async encodeDeployCallData(_) {
|
|
330
|
+
throw new Error("Simple account doesn't support account deployment")
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
// Encode a call
|
|
334
|
+
async encodeCallData(_tx) {
|
|
335
|
+
if (Array.isArray(_tx)) {
|
|
336
|
+
// Encode a batched call
|
|
337
|
+
return encodeFunctionData({
|
|
338
|
+
abi: KernelExecuteAbi,
|
|
339
|
+
functionName: "executeBatch",
|
|
340
|
+
args: [
|
|
341
|
+
_tx.map((tx) => ({
|
|
342
|
+
to: tx.to,
|
|
343
|
+
value: tx.value,
|
|
344
|
+
data: tx.data
|
|
345
|
+
}))
|
|
346
|
+
]
|
|
347
|
+
})
|
|
348
|
+
} else {
|
|
349
|
+
// Encode a simple call
|
|
350
|
+
return encodeFunctionData({
|
|
351
|
+
abi: KernelExecuteAbi,
|
|
352
|
+
functionName: "execute",
|
|
353
|
+
args: [_tx.to, _tx.value, _tx.data, 0]
|
|
354
|
+
})
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
// Get simple dummy signature
|
|
359
|
+
async getDummySignature() {
|
|
360
|
+
return "0x00000000fffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
@@ -61,8 +61,8 @@ const SAFE_VERSION_TO_ADDRESSES_MAP: {
|
|
|
61
61
|
}
|
|
62
62
|
} = {
|
|
63
63
|
"1.4.1": {
|
|
64
|
-
ADD_MODULES_LIB_ADDRESS: "
|
|
65
|
-
SAFE_4337_MODULE_ADDRESS: "
|
|
64
|
+
ADD_MODULES_LIB_ADDRESS: "0x8EcD4ec46D4D2a6B64fE960B3D64e8B94B2234eb",
|
|
65
|
+
SAFE_4337_MODULE_ADDRESS: "0xa581c4A4DB7175302464fF3C06380BC3270b4037",
|
|
66
66
|
SAFE_PROXY_FACTORY_ADDRESS:
|
|
67
67
|
"0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67",
|
|
68
68
|
SAFE_SINGLETON_ADDRESS: "0x41675C099F32341bf84BFc5382aF534df5C7461a",
|
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
} from "../../types/userOperation.js"
|
|
8
8
|
import { deepHexlify } from "../../utils/deepHexlify.js"
|
|
9
9
|
|
|
10
|
-
export type
|
|
10
|
+
export type PimlocoSponsorUserOperationParameters = {
|
|
11
11
|
userOperation: PartialBy<
|
|
12
12
|
UserOperation,
|
|
13
13
|
| "callGasLimit"
|
|
@@ -16,6 +16,7 @@ export type SponsorUserOperationParameters = {
|
|
|
16
16
|
| "paymasterAndData"
|
|
17
17
|
>
|
|
18
18
|
entryPoint: Address
|
|
19
|
+
sponsorshipPolicyId?: string
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export type SponsorUserOperationReturnType = {
|
|
@@ -31,7 +32,7 @@ export type SponsorUserOperationReturnType = {
|
|
|
31
32
|
* - Docs: https://docs.pimlico.io/permissionless/reference/pimlico-paymaster-actions/sponsorUserOperation
|
|
32
33
|
*
|
|
33
34
|
* @param client {@link PimlicoBundlerClient} that you created using viem's createClient whose transport url is pointing to the Pimlico's bundler.
|
|
34
|
-
* @param args {@link
|
|
35
|
+
* @param args {@link PimlocoSponsorUserOperationParameters} UserOperation you want to sponsor & entryPoint.
|
|
35
36
|
* @returns paymasterAndData & updated gas parameters, see {@link SponsorUserOperationReturnType}
|
|
36
37
|
*
|
|
37
38
|
*
|
|
@@ -56,14 +57,26 @@ export const sponsorUserOperation = async <
|
|
|
56
57
|
TAccount extends Account | undefined = Account | undefined
|
|
57
58
|
>(
|
|
58
59
|
client: Client<TTransport, TChain, TAccount, PimlicoPaymasterRpcSchema>,
|
|
59
|
-
args:
|
|
60
|
+
args: PimlocoSponsorUserOperationParameters
|
|
60
61
|
): Promise<SponsorUserOperationReturnType> => {
|
|
61
62
|
const response = await client.request({
|
|
62
63
|
method: "pm_sponsorUserOperation",
|
|
63
|
-
params:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
params: args.sponsorshipPolicyId
|
|
65
|
+
? [
|
|
66
|
+
deepHexlify(
|
|
67
|
+
args.userOperation
|
|
68
|
+
) as UserOperationWithBigIntAsHex,
|
|
69
|
+
args.entryPoint,
|
|
70
|
+
{
|
|
71
|
+
sponsorshipPolicyId: args.sponsorshipPolicyId
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
: [
|
|
75
|
+
deepHexlify(
|
|
76
|
+
args.userOperation
|
|
77
|
+
) as UserOperationWithBigIntAsHex,
|
|
78
|
+
args.entryPoint
|
|
79
|
+
]
|
|
67
80
|
})
|
|
68
81
|
|
|
69
82
|
return {
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { Account, Address, Chain, Client, Transport } from "viem"
|
|
2
|
+
import type { PimlicoPaymasterRpcSchema } from "../../types/pimlico.js"
|
|
3
|
+
import type {
|
|
4
|
+
UserOperation,
|
|
5
|
+
UserOperationWithBigIntAsHex
|
|
6
|
+
} from "../../types/userOperation.js"
|
|
7
|
+
import { deepHexlify } from "../../utils/deepHexlify.js"
|
|
8
|
+
|
|
9
|
+
export type ValidateSponsorshipPoliciesParameters = {
|
|
10
|
+
userOperation: UserOperation
|
|
11
|
+
entryPoint: Address
|
|
12
|
+
sponsorshipPolicyIds: string[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type ValidateSponsorshipPoliciesReturnType = {
|
|
16
|
+
sponsorshipPolicyId: string
|
|
17
|
+
data: {
|
|
18
|
+
name: string | null
|
|
19
|
+
author: string | null
|
|
20
|
+
icon: string | null
|
|
21
|
+
description: string | null
|
|
22
|
+
}
|
|
23
|
+
}[]
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Returns valid sponsorship policies for a userOperation from the list of ids passed
|
|
27
|
+
* - Docs: https://docs.pimlico.io/permissionless/reference/pimlico-paymaster-actions/ValidateSponsorshipPolicies
|
|
28
|
+
*
|
|
29
|
+
* @param client {@link PimlicoBundlerClient} that you created using viem's createClient whose transport url is pointing to the Pimlico's bundler.
|
|
30
|
+
* @param args {@link ValidateSponsorshipPoliciesParameters} UserOperation you want to sponsor & entryPoint.
|
|
31
|
+
* @returns valid sponsorship policies, see {@link ValidateSponsorshipPoliciesReturnType}
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* import { createClient } from "viem"
|
|
35
|
+
* import { validateSponsorshipPolicies } from "permissionless/actions/pimlico"
|
|
36
|
+
*
|
|
37
|
+
* const bundlerClient = createClient({
|
|
38
|
+
* chain: goerli,
|
|
39
|
+
* transport: http("https://api.pimlico.io/v2/goerli/rpc?apikey=YOUR_API_KEY_HERE")
|
|
40
|
+
* })
|
|
41
|
+
*
|
|
42
|
+
* await validateSponsorshipPolicies(bundlerClient, {
|
|
43
|
+
* userOperation: userOperationWithDummySignature,
|
|
44
|
+
* entryPoint: entryPoint,
|
|
45
|
+
* sponsorshipPolicyIds: ["sp_shiny_puma"]
|
|
46
|
+
* })
|
|
47
|
+
* Returns
|
|
48
|
+
* [
|
|
49
|
+
* {
|
|
50
|
+
* sponsorshipPolicyId: "sp_shiny_puma",
|
|
51
|
+
* data: {
|
|
52
|
+
* name: "Shiny Puma",
|
|
53
|
+
* author: "Pimlico",
|
|
54
|
+
* icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4...",
|
|
55
|
+
* description: "This policy is for testing purposes only"
|
|
56
|
+
* }
|
|
57
|
+
* }
|
|
58
|
+
* ]
|
|
59
|
+
*/
|
|
60
|
+
export const validateSponsorshipPolicies = async <
|
|
61
|
+
TTransport extends Transport = Transport,
|
|
62
|
+
TChain extends Chain | undefined = Chain | undefined,
|
|
63
|
+
TAccount extends Account | undefined = Account | undefined
|
|
64
|
+
>(
|
|
65
|
+
client: Client<TTransport, TChain, TAccount, PimlicoPaymasterRpcSchema>,
|
|
66
|
+
args: ValidateSponsorshipPoliciesParameters
|
|
67
|
+
): Promise<ValidateSponsorshipPoliciesReturnType> => {
|
|
68
|
+
return await client.request({
|
|
69
|
+
method: "pm_validateSponsorshipPolicies",
|
|
70
|
+
params: [
|
|
71
|
+
deepHexlify(args.userOperation) as UserOperationWithBigIntAsHex,
|
|
72
|
+
args.entryPoint,
|
|
73
|
+
args.sponsorshipPolicyIds
|
|
74
|
+
]
|
|
75
|
+
})
|
|
76
|
+
}
|
package/actions/pimlico.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
getUserOperationStatus
|
|
9
9
|
} from "./pimlico/getUserOperationStatus.js"
|
|
10
10
|
import {
|
|
11
|
-
type
|
|
11
|
+
type PimlocoSponsorUserOperationParameters,
|
|
12
12
|
type SponsorUserOperationReturnType,
|
|
13
13
|
sponsorUserOperation
|
|
14
14
|
} from "./pimlico/sponsorUserOperation.js"
|
|
@@ -22,14 +22,22 @@ import {
|
|
|
22
22
|
pimlicoPaymasterActions
|
|
23
23
|
} from "../clients/decorators/pimlico.js"
|
|
24
24
|
|
|
25
|
+
import {
|
|
26
|
+
type ValidateSponsorshipPoliciesParameters,
|
|
27
|
+
type ValidateSponsorshipPoliciesReturnType,
|
|
28
|
+
validateSponsorshipPolicies
|
|
29
|
+
} from "./pimlico/validateSponsorshipPolicies.js"
|
|
30
|
+
|
|
25
31
|
export type {
|
|
26
32
|
GetUserOperationGasPriceReturnType,
|
|
27
33
|
GetUserOperationStatusParameters,
|
|
28
34
|
GetUserOperationStatusReturnType,
|
|
29
|
-
|
|
35
|
+
PimlocoSponsorUserOperationParameters,
|
|
30
36
|
SponsorUserOperationReturnType,
|
|
31
37
|
PimlicoBundlerActions,
|
|
32
|
-
PimlicoPaymasterClientActions
|
|
38
|
+
PimlicoPaymasterClientActions,
|
|
39
|
+
ValidateSponsorshipPoliciesParameters,
|
|
40
|
+
ValidateSponsorshipPoliciesReturnType
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
export {
|
|
@@ -37,5 +45,6 @@ export {
|
|
|
37
45
|
getUserOperationStatus,
|
|
38
46
|
sponsorUserOperation,
|
|
39
47
|
pimlicoBundlerActions,
|
|
40
|
-
pimlicoPaymasterActions
|
|
48
|
+
pimlicoPaymasterActions,
|
|
49
|
+
validateSponsorshipPolicies
|
|
41
50
|
}
|
|
@@ -16,6 +16,11 @@ import {
|
|
|
16
16
|
smartAccountActions
|
|
17
17
|
} from "./decorators/smartAccount.js"
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* TODO:
|
|
21
|
+
* - Add docs
|
|
22
|
+
* - Fix typing, 'accounts' is required to signMessage, signTypedData, signTransaction, but not needed here, since account is embedded in the client
|
|
23
|
+
*/
|
|
19
24
|
export type SmartAccountClient<
|
|
20
25
|
transport extends Transport = Transport,
|
|
21
26
|
chain extends Chain | undefined = Chain | undefined,
|
|
@@ -54,7 +59,7 @@ export type SmartAccountClientConfig<
|
|
|
54
59
|
*
|
|
55
60
|
* A Bundler Client is an interface to "erc 4337" [JSON-RPC API](https://eips.ethereum.org/EIPS/eip-4337#rpc-methods-eth-namespace) methods such as sending user operation, estimating gas for a user operation, get user operation receipt, etc through Bundler Actions.
|
|
56
61
|
*
|
|
57
|
-
* @param
|
|
62
|
+
* @param parameters - {@link WalletClientConfig}
|
|
58
63
|
* @returns A Bundler Client. {@link SmartAccountClient}
|
|
59
64
|
*
|
|
60
65
|
* @example
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { Client, Hash } from "viem"
|
|
2
|
+
import {
|
|
3
|
+
type ValidateSponsorshipPoliciesParameters,
|
|
4
|
+
type ValidateSponsorshipPoliciesReturnType,
|
|
5
|
+
validateSponsorshipPolicies
|
|
6
|
+
} from "../../actions/pimlico.js"
|
|
2
7
|
import {
|
|
3
8
|
type GetUserOperationGasPriceReturnType,
|
|
4
9
|
getUserOperationGasPrice
|
|
@@ -9,7 +14,7 @@ import {
|
|
|
9
14
|
getUserOperationStatus
|
|
10
15
|
} from "../../actions/pimlico/getUserOperationStatus.js"
|
|
11
16
|
import {
|
|
12
|
-
type
|
|
17
|
+
type PimlocoSponsorUserOperationParameters,
|
|
13
18
|
type SponsorUserOperationReturnType,
|
|
14
19
|
sponsorUserOperation
|
|
15
20
|
} from "../../actions/pimlico/sponsorUserOperation.js"
|
|
@@ -78,7 +83,7 @@ export type PimlicoPaymasterClientActions = {
|
|
|
78
83
|
*
|
|
79
84
|
* https://docs.pimlico.io/permissionless/reference/pimlico-paymaster-actions/sponsorUserOperation
|
|
80
85
|
*
|
|
81
|
-
* @param args {@link
|
|
86
|
+
* @param args {@link PimlocoSponsorUserOperationParameters} UserOperation you want to sponsor & entryPoint.
|
|
82
87
|
* @returns paymasterAndData & updated gas parameters, see {@link SponsorUserOperationReturnType}
|
|
83
88
|
*
|
|
84
89
|
* @example
|
|
@@ -97,15 +102,57 @@ export type PimlicoPaymasterClientActions = {
|
|
|
97
102
|
*
|
|
98
103
|
*/
|
|
99
104
|
sponsorUserOperation: (
|
|
100
|
-
args:
|
|
105
|
+
args: PimlocoSponsorUserOperationParameters
|
|
101
106
|
) => Promise<SponsorUserOperationReturnType>
|
|
107
|
+
|
|
108
|
+
validateSponsorshipPolicies: (
|
|
109
|
+
args: ValidateSponsorshipPoliciesParameters
|
|
110
|
+
) => Promise<ValidateSponsorshipPoliciesReturnType>
|
|
102
111
|
}
|
|
103
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Returns valid sponsorship policies for a userOperation from the list of ids passed
|
|
115
|
+
* - Docs: https://docs.pimlico.io/permissionless/reference/pimlico-paymaster-actions/ValidateSponsorshipPolicies
|
|
116
|
+
*
|
|
117
|
+
* @param args {@link ValidateSponsorshipPoliciesParameters} UserOperation you want to sponsor & entryPoint.
|
|
118
|
+
* @returns valid sponsorship policies, see {@link ValidateSponsorshipPoliciesReturnType}
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* import { createClient } from "viem"
|
|
122
|
+
* import { validateSponsorshipPolicies } from "permissionless/actions/pimlico"
|
|
123
|
+
*
|
|
124
|
+
* const bundlerClient = createClient({
|
|
125
|
+
* chain: goerli,
|
|
126
|
+
* transport: http("https://api.pimlico.io/v2/goerli/rpc?apikey=YOUR_API_KEY_HERE")
|
|
127
|
+
* }).extend(pimlicoPaymasterActions)
|
|
128
|
+
|
|
129
|
+
*
|
|
130
|
+
* await bundlerClient.validateSponsorshipPolicies({
|
|
131
|
+
* userOperation: userOperationWithDummySignature,
|
|
132
|
+
* entryPoint: entryPoint,
|
|
133
|
+
* sponsorshipPolicyIds: ["sp_shiny_puma"]
|
|
134
|
+
* })
|
|
135
|
+
* Returns
|
|
136
|
+
* [
|
|
137
|
+
* {
|
|
138
|
+
* sponsorshipPolicyId: "sp_shiny_puma",
|
|
139
|
+
* data: {
|
|
140
|
+
* name: "Shiny Puma",
|
|
141
|
+
* author: "Pimlico",
|
|
142
|
+
* icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4...",
|
|
143
|
+
* description: "This policy is for testing purposes only"
|
|
144
|
+
* }
|
|
145
|
+
* }
|
|
146
|
+
* ]
|
|
147
|
+
*/
|
|
104
148
|
export const pimlicoPaymasterActions = (
|
|
105
149
|
client: Client
|
|
106
150
|
): PimlicoPaymasterClientActions => ({
|
|
107
|
-
sponsorUserOperation: async (args:
|
|
108
|
-
sponsorUserOperation(client as PimlicoPaymasterClient, args)
|
|
151
|
+
sponsorUserOperation: async (args: PimlocoSponsorUserOperationParameters) =>
|
|
152
|
+
sponsorUserOperation(client as PimlicoPaymasterClient, args),
|
|
153
|
+
validateSponsorshipPolicies: async (
|
|
154
|
+
args: ValidateSponsorshipPoliciesParameters
|
|
155
|
+
) => validateSponsorshipPolicies(client as PimlicoPaymasterClient, args)
|
|
109
156
|
})
|
|
110
157
|
|
|
111
158
|
/**
|