permissionless 0.2.5 → 0.2.7
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/accounts/biconomy/toBiconomySmartAccount.js +37 -13
- package/_cjs/accounts/biconomy/toBiconomySmartAccount.js.map +1 -1
- package/_cjs/accounts/kernel/toEcdsaKernelSmartAccount.js +2 -2
- package/_cjs/accounts/kernel/toEcdsaKernelSmartAccount.js.map +1 -1
- package/_cjs/accounts/kernel/utils/signMessage.js +1 -2
- package/_cjs/accounts/kernel/utils/signMessage.js.map +1 -1
- package/_cjs/accounts/kernel/utils/signTypedData.js +1 -2
- package/_cjs/accounts/kernel/utils/signTypedData.js.map +1 -1
- package/_cjs/accounts/light/toLightSmartAccount.js +1 -2
- package/_cjs/accounts/light/toLightSmartAccount.js.map +1 -1
- package/_cjs/accounts/safe/toSafeSmartAccount.js +1 -2
- package/_cjs/accounts/safe/toSafeSmartAccount.js.map +1 -1
- package/_cjs/accounts/simple/toSimpleSmartAccount.js +1 -2
- package/_cjs/accounts/simple/toSimpleSmartAccount.js.map +1 -1
- package/_cjs/accounts/trust/toTrustSmartAccount.js +2 -2
- package/_cjs/accounts/trust/toTrustSmartAccount.js.map +1 -1
- package/_cjs/actions/erc7579/accountId.js +1 -2
- package/_cjs/actions/erc7579/accountId.js.map +1 -1
- package/_cjs/actions/erc7579/installModule.js +1 -2
- package/_cjs/actions/erc7579/installModule.js.map +1 -1
- package/_cjs/actions/erc7579/installModules.js +1 -2
- package/_cjs/actions/erc7579/installModules.js.map +1 -1
- package/_cjs/actions/erc7579/isModuleInstalled.js +1 -2
- package/_cjs/actions/erc7579/isModuleInstalled.js.map +1 -1
- package/_cjs/actions/erc7579/supportsExecutionMode.js +2 -3
- package/_cjs/actions/erc7579/supportsExecutionMode.js.map +1 -1
- package/_cjs/actions/erc7579/supportsModule.js +2 -3
- package/_cjs/actions/erc7579/supportsModule.js.map +1 -1
- package/_cjs/actions/erc7579/uninstallModule.js +1 -2
- package/_cjs/actions/erc7579/uninstallModule.js.map +1 -1
- package/_cjs/actions/erc7579/uninstallModules.js +1 -2
- package/_cjs/actions/erc7579/uninstallModules.js.map +1 -1
- package/_cjs/actions/erc7579.js +2 -2
- package/_cjs/actions/erc7579.js.map +1 -1
- package/_cjs/actions/smartAccount/sendTransaction.js +1 -2
- package/_cjs/actions/smartAccount/sendTransaction.js.map +1 -1
- package/_cjs/actions/smartAccount/signMessage.js +1 -2
- package/_cjs/actions/smartAccount/signMessage.js.map +1 -1
- package/_cjs/actions/smartAccount/signTypedData.js +1 -2
- package/_cjs/actions/smartAccount/signTypedData.js.map +1 -1
- package/_cjs/actions/smartAccount/writeContract.js +1 -2
- package/_cjs/actions/smartAccount/writeContract.js.map +1 -1
- package/_cjs/clients/createSmartAccountClient.js +26 -10
- package/_cjs/clients/createSmartAccountClient.js.map +1 -1
- package/_cjs/clients/decorators/smartAccount.js +1 -2
- package/_cjs/clients/decorators/smartAccount.js.map +1 -1
- package/_cjs/clients/pimlico.js +1 -2
- package/_cjs/clients/pimlico.js.map +1 -1
- package/_cjs/experimental/pimlico/index.js +6 -0
- package/_cjs/experimental/pimlico/index.js.map +1 -0
- package/_cjs/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.js +126 -0
- package/_cjs/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.js.map +1 -0
- package/_cjs/utils/decodeNonce.js +1 -2
- package/_cjs/utils/decodeNonce.js.map +1 -1
- package/_cjs/utils/deepHexlify.js +2 -2
- package/_cjs/utils/deepHexlify.js.map +1 -1
- package/_cjs/utils/encode7579Calls.js +1 -2
- package/_cjs/utils/encode7579Calls.js.map +1 -1
- package/_cjs/utils/encodeInstallModule.js +1 -2
- package/_cjs/utils/encodeInstallModule.js.map +1 -1
- package/_cjs/utils/encodeNonce.js +1 -2
- package/_cjs/utils/encodeNonce.js.map +1 -1
- package/_cjs/utils/encodeUninstallModule.js +1 -2
- package/_cjs/utils/encodeUninstallModule.js.map +1 -1
- package/_cjs/utils/getAddressFromInitCodeOrPaymasterAndData.js +1 -2
- package/_cjs/utils/getAddressFromInitCodeOrPaymasterAndData.js.map +1 -1
- package/_cjs/utils/getPackedUserOperation.js +9 -9
- package/_cjs/utils/getPackedUserOperation.js.map +1 -1
- package/_cjs/utils/toOwner.js +1 -2
- package/_cjs/utils/toOwner.js.map +1 -1
- package/_esm/accounts/biconomy/toBiconomySmartAccount.js +39 -12
- package/_esm/accounts/biconomy/toBiconomySmartAccount.js.map +1 -1
- package/_esm/accounts/safe/toSafeSmartAccount.js.map +1 -1
- package/_esm/clients/createSmartAccountClient.js +26 -9
- package/_esm/clients/createSmartAccountClient.js.map +1 -1
- package/_esm/experimental/pimlico/index.js +3 -0
- package/_esm/experimental/pimlico/index.js.map +1 -0
- package/_esm/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.js +144 -0
- package/_esm/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.js.map +1 -0
- package/_types/accounts/biconomy/toBiconomySmartAccount.d.ts +2 -0
- package/_types/accounts/biconomy/toBiconomySmartAccount.d.ts.map +1 -1
- package/_types/accounts/kernel/utils/encodeCallData.d.ts.map +1 -1
- package/_types/accounts/kernel/utils/getNonceKey.d.ts.map +1 -1
- package/_types/accounts/kernel/utils/isKernelV2.d.ts.map +1 -1
- package/_types/accounts/safe/toSafeSmartAccount.d.ts +0 -1
- package/_types/accounts/safe/toSafeSmartAccount.d.ts.map +1 -1
- package/_types/actions/erc7579.d.ts +1 -249
- package/_types/actions/erc7579.d.ts.map +1 -1
- package/_types/actions/pimlico/getTokenQuotes.d.ts.map +1 -1
- package/_types/actions/pimlico/getUserOperationGasPrice.d.ts.map +1 -1
- package/_types/actions/pimlico/getUserOperationStatus.d.ts.map +1 -1
- package/_types/actions/pimlico/sendCompressedUserOperation.d.ts.map +1 -1
- package/_types/actions/pimlico/sponsorUserOperation.d.ts.map +1 -1
- package/_types/actions/pimlico/validateSponsorshipPolicies.d.ts.map +1 -1
- package/_types/actions/public/getAccountNonce.d.ts.map +1 -1
- package/_types/actions/public/getSenderAddress.d.ts.map +1 -1
- package/_types/clients/createSmartAccountClient.d.ts +4 -2
- package/_types/clients/createSmartAccountClient.d.ts.map +1 -1
- package/_types/clients/decorators/pimlico.d.ts.map +1 -1
- package/_types/clients/decorators/smartAccount.d.ts +16 -471
- package/_types/clients/decorators/smartAccount.d.ts.map +1 -1
- package/_types/experimental/pimlico/index.d.ts +3 -0
- package/_types/experimental/pimlico/index.d.ts.map +1 -0
- package/_types/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.d.ts +4 -0
- package/_types/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.d.ts.map +1 -0
- package/_types/utils/getPackedUserOperation.d.ts.map +1 -1
- package/_types/utils/getRequiredPrefund.d.ts.map +1 -1
- package/_types/utils/isSmartAccountDeployed.d.ts.map +1 -1
- package/accounts/biconomy/toBiconomySmartAccount.ts +85 -16
- package/accounts/safe/toSafeSmartAccount.ts +0 -1
- package/actions/smartAccount/sendTransaction.test.ts +129 -0
- package/clients/createSmartAccountClient.ts +53 -22
- package/experimental/pimlico/index.ts +2 -0
- package/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.test.ts +195 -0
- package/experimental/pimlico/utils/prepareUserOperationForErc20Paymaster.ts +270 -0
- package/package.json +6 -6
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Address,
|
|
3
|
+
type Chain,
|
|
4
|
+
type Client,
|
|
5
|
+
type ContractFunctionParameters,
|
|
6
|
+
type Transport,
|
|
7
|
+
encodeFunctionData,
|
|
8
|
+
erc20Abi,
|
|
9
|
+
getAddress,
|
|
10
|
+
maxUint256
|
|
11
|
+
} from "viem"
|
|
12
|
+
import {
|
|
13
|
+
type BundlerClient,
|
|
14
|
+
type PrepareUserOperationParameters,
|
|
15
|
+
type PrepareUserOperationRequest,
|
|
16
|
+
type PrepareUserOperationReturnType,
|
|
17
|
+
type SmartAccount,
|
|
18
|
+
type UserOperation,
|
|
19
|
+
type UserOperationCall,
|
|
20
|
+
getPaymasterData as getPaymasterData_,
|
|
21
|
+
prepareUserOperation
|
|
22
|
+
} from "viem/account-abstraction"
|
|
23
|
+
import { getChainId as getChainId_ } from "viem/actions"
|
|
24
|
+
import { readContract } from "viem/actions"
|
|
25
|
+
import { getAction, parseAccount } from "viem/utils"
|
|
26
|
+
import { getTokenQuotes } from "../../../actions/pimlico"
|
|
27
|
+
|
|
28
|
+
export const prepareUserOperationForErc20Paymaster =
|
|
29
|
+
(pimlicoClient: Client) =>
|
|
30
|
+
async <
|
|
31
|
+
account extends SmartAccount | undefined,
|
|
32
|
+
const calls extends readonly unknown[],
|
|
33
|
+
const request extends PrepareUserOperationRequest<
|
|
34
|
+
account,
|
|
35
|
+
accountOverride,
|
|
36
|
+
calls
|
|
37
|
+
>,
|
|
38
|
+
accountOverride extends SmartAccount | undefined = undefined
|
|
39
|
+
>(
|
|
40
|
+
client: Client<Transport, Chain | undefined, account>,
|
|
41
|
+
parameters_: PrepareUserOperationParameters<
|
|
42
|
+
account,
|
|
43
|
+
accountOverride,
|
|
44
|
+
calls,
|
|
45
|
+
request
|
|
46
|
+
>
|
|
47
|
+
): Promise<
|
|
48
|
+
PrepareUserOperationReturnType<account, accountOverride, calls, request>
|
|
49
|
+
> => {
|
|
50
|
+
const parameters = parameters_ as PrepareUserOperationParameters
|
|
51
|
+
const account_ = client.account
|
|
52
|
+
|
|
53
|
+
if (!account_) throw new Error("Account not found")
|
|
54
|
+
const account = parseAccount(account_)
|
|
55
|
+
|
|
56
|
+
const bundlerClient = client as unknown as BundlerClient
|
|
57
|
+
|
|
58
|
+
const paymasterContext = parameters.paymasterContext
|
|
59
|
+
? parameters.paymasterContext
|
|
60
|
+
: bundlerClient?.paymasterContext
|
|
61
|
+
|
|
62
|
+
if (
|
|
63
|
+
typeof paymasterContext === "object" &&
|
|
64
|
+
paymasterContext !== null &&
|
|
65
|
+
"token" in paymasterContext &&
|
|
66
|
+
typeof paymasterContext.token === "string"
|
|
67
|
+
) {
|
|
68
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
69
|
+
// Inject custom approval before calling prepareUserOperation
|
|
70
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
71
|
+
|
|
72
|
+
const token = getAddress(paymasterContext.token)
|
|
73
|
+
|
|
74
|
+
let chainId: number | undefined
|
|
75
|
+
async function getChainId(): Promise<number> {
|
|
76
|
+
if (chainId) return chainId
|
|
77
|
+
if (client.chain) return client.chain.id
|
|
78
|
+
const chainId_ = await getAction(
|
|
79
|
+
client,
|
|
80
|
+
getChainId_,
|
|
81
|
+
"getChainId"
|
|
82
|
+
)({})
|
|
83
|
+
chainId = chainId_
|
|
84
|
+
return chainId
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const quotes = await getAction(
|
|
88
|
+
pimlicoClient,
|
|
89
|
+
getTokenQuotes,
|
|
90
|
+
"getTokenQuotes"
|
|
91
|
+
)({
|
|
92
|
+
tokens: [token],
|
|
93
|
+
chain:
|
|
94
|
+
pimlicoClient.chain ?? client.chain ?? account.client.chain,
|
|
95
|
+
entryPointAddress: account.entryPoint.address
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
const {
|
|
99
|
+
postOpGas,
|
|
100
|
+
exchangeRate,
|
|
101
|
+
paymaster: paymasterERC20Address
|
|
102
|
+
} = quotes[0]
|
|
103
|
+
|
|
104
|
+
const callsWithDummyApproval = [
|
|
105
|
+
{
|
|
106
|
+
abi: erc20Abi,
|
|
107
|
+
functionName: "approve",
|
|
108
|
+
args: [paymasterERC20Address, maxUint256], // dummy approval to ensure simulation passes
|
|
109
|
+
to: paymasterContext.token
|
|
110
|
+
},
|
|
111
|
+
...(parameters.calls ? parameters.calls : [])
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
if (parameters.callData) {
|
|
115
|
+
throw new Error(
|
|
116
|
+
"parameter callData is not supported with prepareUserOperationForErc20Paymaster"
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
121
|
+
// Call prepareUserOperation
|
|
122
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
123
|
+
|
|
124
|
+
const userOperation = await getAction(
|
|
125
|
+
client,
|
|
126
|
+
prepareUserOperation,
|
|
127
|
+
"prepareUserOperation"
|
|
128
|
+
)({
|
|
129
|
+
...parameters,
|
|
130
|
+
calls: callsWithDummyApproval
|
|
131
|
+
} as unknown as PrepareUserOperationParameters)
|
|
132
|
+
|
|
133
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
134
|
+
// Call pimlico_getTokenQuotes and calculate the approval amount needed for op
|
|
135
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
136
|
+
|
|
137
|
+
const maxFeePerGas = userOperation.maxFeePerGas
|
|
138
|
+
|
|
139
|
+
const userOperationMaxGas =
|
|
140
|
+
userOperation.preVerificationGas +
|
|
141
|
+
userOperation.callGasLimit +
|
|
142
|
+
userOperation.verificationGasLimit +
|
|
143
|
+
(userOperation.paymasterPostOpGasLimit || 0n) +
|
|
144
|
+
(userOperation.paymasterVerificationGasLimit || 0n)
|
|
145
|
+
|
|
146
|
+
const userOperationMaxCost = userOperationMaxGas * maxFeePerGas
|
|
147
|
+
|
|
148
|
+
// using formula here https://github.com/pimlicolabs/singleton-paymaster/blob/main/src/base/BaseSingletonPaymaster.sol#L334-L341
|
|
149
|
+
const maxCostInToken =
|
|
150
|
+
((userOperationMaxCost + postOpGas * maxFeePerGas) *
|
|
151
|
+
exchangeRate) /
|
|
152
|
+
BigInt(1e18)
|
|
153
|
+
|
|
154
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
155
|
+
// Check if we need to approve the token
|
|
156
|
+
// If the user has existing approval that is sufficient, skip approval injection
|
|
157
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
158
|
+
|
|
159
|
+
const publicClient = account.client
|
|
160
|
+
|
|
161
|
+
const allowance = await getAction(
|
|
162
|
+
publicClient,
|
|
163
|
+
readContract,
|
|
164
|
+
"readContract"
|
|
165
|
+
)({
|
|
166
|
+
abi: erc20Abi,
|
|
167
|
+
functionName: "allowance",
|
|
168
|
+
args: [account.address, paymasterERC20Address],
|
|
169
|
+
address: token
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
const hasSufficientApproval = allowance >= maxCostInToken
|
|
173
|
+
|
|
174
|
+
const finalCalls = hasSufficientApproval
|
|
175
|
+
? parameters.calls
|
|
176
|
+
: [
|
|
177
|
+
{
|
|
178
|
+
abi: erc20Abi,
|
|
179
|
+
functionName: "approve",
|
|
180
|
+
args: [paymasterERC20Address, maxCostInToken],
|
|
181
|
+
to: paymasterContext.token
|
|
182
|
+
},
|
|
183
|
+
...parameters.calls
|
|
184
|
+
]
|
|
185
|
+
|
|
186
|
+
userOperation.callData = await account.encodeCalls(
|
|
187
|
+
finalCalls.map((call_) => {
|
|
188
|
+
const call = call_ as
|
|
189
|
+
| UserOperationCall
|
|
190
|
+
| (ContractFunctionParameters & {
|
|
191
|
+
to: Address
|
|
192
|
+
value: bigint
|
|
193
|
+
})
|
|
194
|
+
if ("abi" in call)
|
|
195
|
+
return {
|
|
196
|
+
data: encodeFunctionData(call),
|
|
197
|
+
to: call.to,
|
|
198
|
+
value: call.value
|
|
199
|
+
} as UserOperationCall
|
|
200
|
+
return call as UserOperationCall
|
|
201
|
+
})
|
|
202
|
+
)
|
|
203
|
+
parameters.calls = finalCalls
|
|
204
|
+
|
|
205
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
206
|
+
// Declare Paymaster properties. (taken from viem)
|
|
207
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
208
|
+
|
|
209
|
+
const paymaster = parameters.paymaster ?? bundlerClient?.paymaster
|
|
210
|
+
const { getPaymasterData } = (() => {
|
|
211
|
+
// If `paymaster: true`, we will assume the Bundler Client supports Paymaster Actions.
|
|
212
|
+
if (paymaster === true)
|
|
213
|
+
return {
|
|
214
|
+
getPaymasterData: (parameters: any) =>
|
|
215
|
+
getAction(
|
|
216
|
+
bundlerClient,
|
|
217
|
+
getPaymasterData_,
|
|
218
|
+
"getPaymasterData"
|
|
219
|
+
)(parameters)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// If Actions are passed to `paymaster` (via Paymaster Client or directly), we will use them.
|
|
223
|
+
if (
|
|
224
|
+
typeof paymaster === "object" &&
|
|
225
|
+
paymaster.getPaymasterData
|
|
226
|
+
) {
|
|
227
|
+
const { getPaymasterData } = paymaster
|
|
228
|
+
return {
|
|
229
|
+
getPaymasterData
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
throw new Error(
|
|
234
|
+
"Expected paymaster: cannot sponsor ERC-20 without paymaster"
|
|
235
|
+
)
|
|
236
|
+
})()
|
|
237
|
+
|
|
238
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
239
|
+
// Re-calculate Paymaster data fields.
|
|
240
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
241
|
+
|
|
242
|
+
const paymasterData = await getPaymasterData({
|
|
243
|
+
chainId: await getChainId(),
|
|
244
|
+
entryPointAddress: account.entryPoint.address,
|
|
245
|
+
context: paymasterContext,
|
|
246
|
+
...(userOperation as UserOperation)
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
...userOperation,
|
|
251
|
+
...paymasterData
|
|
252
|
+
} as unknown as PrepareUserOperationReturnType<
|
|
253
|
+
account,
|
|
254
|
+
accountOverride,
|
|
255
|
+
calls,
|
|
256
|
+
request
|
|
257
|
+
>
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return (await getAction(
|
|
261
|
+
client,
|
|
262
|
+
prepareUserOperation,
|
|
263
|
+
"prepareUserOperation"
|
|
264
|
+
)(parameters)) as unknown as PrepareUserOperationReturnType<
|
|
265
|
+
account,
|
|
266
|
+
accountOverride,
|
|
267
|
+
calls,
|
|
268
|
+
request
|
|
269
|
+
>
|
|
270
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "permissionless",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"author": "Pimlico",
|
|
5
5
|
"homepage": "https://docs.pimlico.io/permissionless",
|
|
6
6
|
"repository": "github:pimlicolabs/permissionless.js",
|
|
@@ -70,13 +70,13 @@
|
|
|
70
70
|
"import": "./_esm/errors/index.js",
|
|
71
71
|
"default": "./_cjs/errors/index.js"
|
|
72
72
|
},
|
|
73
|
-
"./experimental": {
|
|
74
|
-
"types": "./_types/experimental/index.d.ts",
|
|
75
|
-
"import": "./_esm/experimental/index.js",
|
|
76
|
-
"default": "./_cjs/experimental/index.js"
|
|
73
|
+
"./experimental/pimlico": {
|
|
74
|
+
"types": "./_types/experimental/pimlico/index.d.ts",
|
|
75
|
+
"import": "./_esm/experimental/pimlico/index.js",
|
|
76
|
+
"default": "./_cjs/experimental/pimlico/index.js"
|
|
77
77
|
}
|
|
78
78
|
},
|
|
79
79
|
"peerDependencies": {
|
|
80
|
-
"viem": "^2.
|
|
80
|
+
"viem": "^2.21.2"
|
|
81
81
|
}
|
|
82
82
|
}
|