permissionless 0.1.21 → 0.1.23

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 (39) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/_cjs/accounts/index.js +5 -1
  3. package/_cjs/accounts/index.js.map +1 -1
  4. package/_cjs/accounts/kernel/signerToEcdsaKernelSmartAccount.js +6 -0
  5. package/_cjs/accounts/kernel/signerToEcdsaKernelSmartAccount.js.map +1 -1
  6. package/_cjs/accounts/light/privateKeyToLightSmartAccount.js +14 -0
  7. package/_cjs/accounts/light/privateKeyToLightSmartAccount.js.map +1 -0
  8. package/_cjs/accounts/light/signerToLightSmartAccount.js +255 -0
  9. package/_cjs/accounts/light/signerToLightSmartAccount.js.map +1 -0
  10. package/_cjs/actions/bundler/getUserOperationReceipt.js +3 -0
  11. package/_cjs/actions/bundler/getUserOperationReceipt.js.map +1 -1
  12. package/_esm/accounts/index.js +3 -1
  13. package/_esm/accounts/index.js.map +1 -1
  14. package/_esm/accounts/kernel/signerToEcdsaKernelSmartAccount.js +6 -0
  15. package/_esm/accounts/kernel/signerToEcdsaKernelSmartAccount.js.map +1 -1
  16. package/_esm/accounts/light/privateKeyToLightSmartAccount.js +16 -0
  17. package/_esm/accounts/light/privateKeyToLightSmartAccount.js.map +1 -0
  18. package/_esm/accounts/light/signerToLightSmartAccount.js +257 -0
  19. package/_esm/accounts/light/signerToLightSmartAccount.js.map +1 -0
  20. package/_esm/actions/bundler/getUserOperationReceipt.js +3 -0
  21. package/_esm/actions/bundler/getUserOperationReceipt.js.map +1 -1
  22. package/_types/accounts/index.d.ts +3 -1
  23. package/_types/accounts/index.d.ts.map +1 -1
  24. package/_types/accounts/kernel/signerToEcdsaKernelSmartAccount.d.ts.map +1 -1
  25. package/_types/accounts/light/privateKeyToLightSmartAccount.d.ts +13 -0
  26. package/_types/accounts/light/privateKeyToLightSmartAccount.d.ts.map +1 -0
  27. package/_types/accounts/light/signerToLightSmartAccount.d.ts +21 -0
  28. package/_types/accounts/light/signerToLightSmartAccount.d.ts.map +1 -0
  29. package/_types/actions/bundler/getUserOperationReceipt.d.ts +3 -0
  30. package/_types/actions/bundler/getUserOperationReceipt.d.ts.map +1 -1
  31. package/_types/types/bundler.d.ts +3 -0
  32. package/_types/types/bundler.d.ts.map +1 -1
  33. package/accounts/index.ts +16 -0
  34. package/accounts/kernel/signerToEcdsaKernelSmartAccount.ts +9 -0
  35. package/accounts/light/privateKeyToLightSmartAccount.ts +37 -0
  36. package/accounts/light/signerToLightSmartAccount.ts +407 -0
  37. package/actions/bundler/getUserOperationReceipt.ts +6 -0
  38. package/package.json +1 -1
  39. package/types/bundler.ts +3 -0
@@ -0,0 +1,407 @@
1
+ import {
2
+ type Address,
3
+ type Chain,
4
+ type Client,
5
+ type Hex,
6
+ type LocalAccount,
7
+ type Transport,
8
+ type TypedData,
9
+ type TypedDataDefinition,
10
+ concatHex,
11
+ encodeFunctionData,
12
+ hashMessage,
13
+ hashTypedData
14
+ } from "viem"
15
+ import { getChainId, signMessage } from "viem/actions"
16
+ import { getAccountNonce } from "../../actions/public/getAccountNonce"
17
+ import { getSenderAddress } from "../../actions/public/getSenderAddress"
18
+ import type {
19
+ ENTRYPOINT_ADDRESS_V06_TYPE,
20
+ ENTRYPOINT_ADDRESS_V07_TYPE,
21
+ Prettify
22
+ } from "../../types"
23
+ import type { EntryPoint } from "../../types/entrypoint"
24
+ import { getEntryPointVersion } from "../../utils"
25
+ import { getUserOperationHash } from "../../utils/getUserOperationHash"
26
+ import { isSmartAccountDeployed } from "../../utils/isSmartAccountDeployed"
27
+ import { toSmartAccount } from "../toSmartAccount"
28
+ import {
29
+ SignTransactionNotSupportedBySmartAccount,
30
+ type SmartAccount,
31
+ type SmartAccountSigner
32
+ } from "../types"
33
+
34
+ export type LightSmartAccount<
35
+ entryPoint extends EntryPoint,
36
+ transport extends Transport = Transport,
37
+ chain extends Chain | undefined = Chain | undefined
38
+ > = SmartAccount<entryPoint, "LightSmartAccount", transport, chain>
39
+
40
+ const getAccountInitCode = async (
41
+ owner: Address,
42
+ index = BigInt(0)
43
+ ): Promise<Hex> => {
44
+ if (!owner) throw new Error("Owner account not found")
45
+
46
+ return encodeFunctionData({
47
+ abi: [
48
+ {
49
+ inputs: [
50
+ {
51
+ internalType: "address",
52
+ name: "owner",
53
+ type: "address"
54
+ },
55
+ {
56
+ internalType: "uint256",
57
+ name: "salt",
58
+ type: "uint256"
59
+ }
60
+ ],
61
+ name: "createAccount",
62
+ outputs: [
63
+ {
64
+ internalType: "contract LightAccount",
65
+ name: "ret",
66
+ type: "address"
67
+ }
68
+ ],
69
+ stateMutability: "nonpayable",
70
+ type: "function"
71
+ }
72
+ ],
73
+ functionName: "createAccount",
74
+ args: [owner, index]
75
+ })
76
+ }
77
+
78
+ const getAccountAddress = async <
79
+ entryPoint extends EntryPoint,
80
+ TTransport extends Transport = Transport,
81
+ TChain extends Chain | undefined = Chain | undefined
82
+ >({
83
+ client,
84
+ factoryAddress,
85
+ entryPoint: entryPointAddress,
86
+ owner,
87
+ index = BigInt(0)
88
+ }: {
89
+ client: Client<TTransport, TChain>
90
+ factoryAddress: Address
91
+ owner: Address
92
+ entryPoint: entryPoint
93
+ index?: bigint
94
+ }): Promise<Address> => {
95
+ const entryPointVersion = getEntryPointVersion(entryPointAddress)
96
+
97
+ const factoryData = await getAccountInitCode(owner, index)
98
+
99
+ if (entryPointVersion === "v0.6") {
100
+ return getSenderAddress<ENTRYPOINT_ADDRESS_V06_TYPE>(client, {
101
+ initCode: concatHex([factoryAddress, factoryData]),
102
+ entryPoint: entryPointAddress as ENTRYPOINT_ADDRESS_V06_TYPE
103
+ })
104
+ }
105
+
106
+ // Get the sender address based on the init code
107
+ return getSenderAddress<ENTRYPOINT_ADDRESS_V07_TYPE>(client, {
108
+ factory: factoryAddress,
109
+ factoryData,
110
+ entryPoint: entryPointAddress as ENTRYPOINT_ADDRESS_V07_TYPE
111
+ })
112
+ }
113
+
114
+ export type LightVersion = "v1.1.0"
115
+
116
+ export type SignerToLightSmartAccountParameters<
117
+ entryPoint extends EntryPoint,
118
+ TSource extends string = string,
119
+ TAddress extends Address = Address
120
+ > = Prettify<{
121
+ signer: SmartAccountSigner<TSource, TAddress>
122
+ lightVersion: LightVersion
123
+ entryPoint: entryPoint
124
+ factoryAddress?: Address
125
+ index?: bigint
126
+ address?: Address
127
+ }>
128
+
129
+ async function signWith1271WrapperV1<
130
+ TSource extends string = string,
131
+ TAddress extends Address = Address
132
+ >(
133
+ signer: SmartAccountSigner<TSource, TAddress>,
134
+ chainId: number,
135
+ accountAddress: Address,
136
+ hashedMessage: Hex
137
+ ): Promise<Hex> {
138
+ return signer.signTypedData({
139
+ domain: {
140
+ chainId: Number(chainId),
141
+ name: "LightAccount",
142
+ verifyingContract: accountAddress,
143
+ version: "1"
144
+ },
145
+ types: {
146
+ LightAccountMessage: [{ name: "message", type: "bytes" }]
147
+ },
148
+ message: {
149
+ message: hashedMessage
150
+ },
151
+ primaryType: "LightAccountMessage"
152
+ })
153
+ }
154
+
155
+ const LIGHT_VERSION_TO_ADDRESSES_MAP: {
156
+ [key in LightVersion]: {
157
+ factoryAddress: Address
158
+ }
159
+ } = {
160
+ "v1.1.0": {
161
+ factoryAddress: "0x00004EC70002a32400f8ae005A26081065620D20"
162
+ }
163
+ }
164
+
165
+ const getDefaultAddresses = (
166
+ lightVersion: LightVersion,
167
+ {
168
+ factoryAddress: _factoryAddress
169
+ }: {
170
+ factoryAddress?: Address
171
+ }
172
+ ) => {
173
+ const factoryAddress =
174
+ _factoryAddress ??
175
+ LIGHT_VERSION_TO_ADDRESSES_MAP[lightVersion].factoryAddress
176
+
177
+ return {
178
+ factoryAddress
179
+ }
180
+ }
181
+
182
+ /**
183
+ * @description Creates an Light Account from a private key.
184
+ *
185
+ * @returns A Private Key Light Account.
186
+ */
187
+ export async function signerToLightSmartAccount<
188
+ entryPoint extends EntryPoint,
189
+ TTransport extends Transport = Transport,
190
+ TChain extends Chain | undefined = Chain | undefined,
191
+ TSource extends string = string,
192
+ TAddress extends Address = Address
193
+ >(
194
+ client: Client<TTransport, TChain, undefined>,
195
+ {
196
+ signer,
197
+ address,
198
+ lightVersion,
199
+ entryPoint: entryPointAddress,
200
+ index = BigInt(0),
201
+ factoryAddress: _factoryAddress
202
+ }: SignerToLightSmartAccountParameters<entryPoint, TSource, TAddress>
203
+ ): Promise<LightSmartAccount<entryPoint, TTransport, TChain>> {
204
+ const viemSigner: LocalAccount = {
205
+ ...signer,
206
+ signTransaction: (_, __) => {
207
+ throw new SignTransactionNotSupportedBySmartAccount()
208
+ }
209
+ } as LocalAccount
210
+
211
+ if (lightVersion !== "v1.1.0") {
212
+ throw new Error(
213
+ "Only Light Account version v1.1.0 is supported at the moment"
214
+ )
215
+ }
216
+
217
+ const { factoryAddress } = getDefaultAddresses(lightVersion, {
218
+ factoryAddress: _factoryAddress
219
+ })
220
+
221
+ const [accountAddress, chainId] = await Promise.all([
222
+ address ??
223
+ getAccountAddress<entryPoint, TTransport, TChain>({
224
+ client,
225
+ factoryAddress,
226
+ entryPoint: entryPointAddress,
227
+ owner: viemSigner.address,
228
+ index
229
+ }),
230
+ client.chain?.id ?? getChainId(client)
231
+ ])
232
+
233
+ if (!accountAddress) throw new Error("Account address not found")
234
+
235
+ let smartAccountDeployed = await isSmartAccountDeployed(
236
+ client,
237
+ accountAddress
238
+ )
239
+
240
+ return toSmartAccount({
241
+ address: accountAddress,
242
+ signMessage: async ({ message }) => {
243
+ return signWith1271WrapperV1<TSource, TAddress>(
244
+ signer,
245
+ chainId,
246
+ accountAddress,
247
+ hashMessage(message)
248
+ )
249
+ },
250
+ signTransaction: (_, __) => {
251
+ throw new SignTransactionNotSupportedBySmartAccount()
252
+ },
253
+ async signTypedData<
254
+ const TTypedData extends TypedData | Record<string, unknown>,
255
+ TPrimaryType extends
256
+ | keyof TTypedData
257
+ | "EIP712Domain" = keyof TTypedData
258
+ >(typedData: TypedDataDefinition<TTypedData, TPrimaryType>) {
259
+ return signWith1271WrapperV1<TSource, TAddress>(
260
+ signer,
261
+ chainId,
262
+ accountAddress,
263
+ hashTypedData(typedData)
264
+ )
265
+ },
266
+ client: client,
267
+ publicKey: accountAddress,
268
+ entryPoint: entryPointAddress,
269
+ source: "LightSmartAccount",
270
+ async getNonce() {
271
+ return getAccountNonce(client, {
272
+ sender: accountAddress,
273
+ entryPoint: entryPointAddress
274
+ })
275
+ },
276
+ async signUserOperation(userOperation) {
277
+ return signMessage(client, {
278
+ account: viemSigner,
279
+ message: {
280
+ raw: getUserOperationHash({
281
+ userOperation,
282
+ entryPoint: entryPointAddress,
283
+ chainId: chainId
284
+ })
285
+ }
286
+ })
287
+ },
288
+ async getInitCode() {
289
+ if (smartAccountDeployed) return "0x"
290
+
291
+ smartAccountDeployed = await isSmartAccountDeployed(
292
+ client,
293
+ accountAddress
294
+ )
295
+
296
+ if (smartAccountDeployed) return "0x"
297
+
298
+ return concatHex([
299
+ factoryAddress,
300
+ await getAccountInitCode(viemSigner.address, index)
301
+ ])
302
+ },
303
+ async getFactory() {
304
+ if (smartAccountDeployed) return undefined
305
+ smartAccountDeployed = await isSmartAccountDeployed(
306
+ client,
307
+ accountAddress
308
+ )
309
+ if (smartAccountDeployed) return undefined
310
+ return factoryAddress
311
+ },
312
+ async getFactoryData() {
313
+ if (smartAccountDeployed) return undefined
314
+ smartAccountDeployed = await isSmartAccountDeployed(
315
+ client,
316
+ accountAddress
317
+ )
318
+ if (smartAccountDeployed) return undefined
319
+ return getAccountInitCode(viemSigner.address, index)
320
+ },
321
+ async encodeDeployCallData(_) {
322
+ throw new Error("Light account doesn't support account deployment")
323
+ },
324
+ async encodeCallData(args) {
325
+ if (Array.isArray(args)) {
326
+ const argsArray = args as {
327
+ to: Address
328
+ value: bigint
329
+ data: Hex
330
+ }[]
331
+
332
+ return encodeFunctionData({
333
+ abi: [
334
+ {
335
+ inputs: [
336
+ {
337
+ internalType: "address[]",
338
+ name: "dest",
339
+ type: "address[]"
340
+ },
341
+ {
342
+ internalType: "uint256[]",
343
+ name: "value",
344
+ type: "uint256[]"
345
+ },
346
+ {
347
+ internalType: "bytes[]",
348
+ name: "func",
349
+ type: "bytes[]"
350
+ }
351
+ ],
352
+ name: "executeBatch",
353
+ outputs: [],
354
+ stateMutability: "nonpayable",
355
+ type: "function"
356
+ }
357
+ ],
358
+ functionName: "executeBatch",
359
+ args: [
360
+ argsArray.map((a) => a.to),
361
+ argsArray.map((a) => a.value),
362
+ argsArray.map((a) => a.data)
363
+ ]
364
+ })
365
+ }
366
+
367
+ const { to, value, data } = args as {
368
+ to: Address
369
+ value: bigint
370
+ data: Hex
371
+ }
372
+
373
+ return encodeFunctionData({
374
+ abi: [
375
+ {
376
+ inputs: [
377
+ {
378
+ internalType: "address",
379
+ name: "dest",
380
+ type: "address"
381
+ },
382
+ {
383
+ internalType: "uint256",
384
+ name: "value",
385
+ type: "uint256"
386
+ },
387
+ {
388
+ internalType: "bytes",
389
+ name: "func",
390
+ type: "bytes"
391
+ }
392
+ ],
393
+ name: "execute",
394
+ outputs: [],
395
+ stateMutability: "nonpayable",
396
+ type: "function"
397
+ }
398
+ ],
399
+ functionName: "execute",
400
+ args: [to, value, data]
401
+ })
402
+ },
403
+ async getDummySignature(_userOperation) {
404
+ return "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"
405
+ }
406
+ })
407
+ }
@@ -20,11 +20,14 @@ export type GetUserOperationReceiptParameters = {
20
20
 
21
21
  export type GetUserOperationReceiptReturnType = {
22
22
  userOpHash: Hash
23
+ entryPoint: Address
23
24
  sender: Address
24
25
  nonce: bigint
26
+ paymaster?: Address
25
27
  actualGasUsed: bigint
26
28
  actualGasCost: bigint
27
29
  success: boolean
30
+ reason?: string
28
31
  receipt: {
29
32
  transactionHash: Hex
30
33
  transactionIndex: bigint
@@ -93,11 +96,14 @@ export const getUserOperationReceipt = async <
93
96
 
94
97
  const userOperationReceipt: GetUserOperationReceiptReturnType = {
95
98
  userOpHash: response.userOpHash,
99
+ entryPoint: response.entryPoint,
96
100
  sender: response.sender,
97
101
  nonce: BigInt(response.nonce),
102
+ paymaster: response.paymaster,
98
103
  actualGasUsed: BigInt(response.actualGasUsed),
99
104
  actualGasCost: BigInt(response.actualGasCost),
100
105
  success: response.success,
106
+ reason: response.reason,
101
107
  receipt: {
102
108
  transactionHash: response.receipt.transactionHash,
103
109
  transactionIndex: BigInt(response.receipt.transactionIndex),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "permissionless",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "author": "Pimlico",
5
5
  "homepage": "https://docs.pimlico.io/permissionless",
6
6
  "repository": "github:pimlicolabs/permissionless.js",
package/types/bundler.ts CHANGED
@@ -81,11 +81,14 @@ export type BundlerRpcSchema<entryPoint extends EntryPoint> = [
81
81
 
82
82
  type UserOperationReceiptWithBigIntAsHex = {
83
83
  userOpHash: Hash
84
+ entryPoint: Address
84
85
  sender: Address
85
86
  nonce: Hex
87
+ paymaster?: Address
86
88
  actualGasUsed: Hex
87
89
  actualGasCost: Hex
88
90
  success: boolean
91
+ reason?: string
89
92
  receipt: {
90
93
  transactionHash: Hex
91
94
  transactionIndex: Hex