permissionless 0.2.7 → 0.2.9

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 (57) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/_cjs/accounts/index.js +3 -1
  3. package/_cjs/accounts/index.js.map +1 -1
  4. package/_cjs/accounts/thirdweb/toThirdwebSmartAccount.js +118 -0
  5. package/_cjs/accounts/thirdweb/toThirdwebSmartAccount.js.map +1 -0
  6. package/_cjs/accounts/thirdweb/utils/encodeCallData.js +76 -0
  7. package/_cjs/accounts/thirdweb/utils/encodeCallData.js.map +1 -0
  8. package/_cjs/accounts/thirdweb/utils/getAccountAddress.js +37 -0
  9. package/_cjs/accounts/thirdweb/utils/getAccountAddress.js.map +1 -0
  10. package/_cjs/accounts/thirdweb/utils/getFactoryData.js +37 -0
  11. package/_cjs/accounts/thirdweb/utils/getFactoryData.js.map +1 -0
  12. package/_cjs/accounts/thirdweb/utils/signMessage.js +19 -0
  13. package/_cjs/accounts/thirdweb/utils/signMessage.js.map +1 -0
  14. package/_cjs/accounts/thirdweb/utils/signTypedData.js +40 -0
  15. package/_cjs/accounts/thirdweb/utils/signTypedData.js.map +1 -0
  16. package/_cjs/actions/public/getSenderAddress.js +7 -4
  17. package/_cjs/actions/public/getSenderAddress.js.map +1 -1
  18. package/_esm/accounts/index.js +2 -1
  19. package/_esm/accounts/index.js.map +1 -1
  20. package/_esm/accounts/thirdweb/toThirdwebSmartAccount.js +122 -0
  21. package/_esm/accounts/thirdweb/toThirdwebSmartAccount.js.map +1 -0
  22. package/_esm/accounts/thirdweb/utils/encodeCallData.js +72 -0
  23. package/_esm/accounts/thirdweb/utils/encodeCallData.js.map +1 -0
  24. package/_esm/accounts/thirdweb/utils/getAccountAddress.js +33 -0
  25. package/_esm/accounts/thirdweb/utils/getAccountAddress.js.map +1 -0
  26. package/_esm/accounts/thirdweb/utils/getFactoryData.js +33 -0
  27. package/_esm/accounts/thirdweb/utils/getFactoryData.js.map +1 -0
  28. package/_esm/accounts/thirdweb/utils/signMessage.js +17 -0
  29. package/_esm/accounts/thirdweb/utils/signMessage.js.map +1 -0
  30. package/_esm/accounts/thirdweb/utils/signTypedData.js +40 -0
  31. package/_esm/accounts/thirdweb/utils/signTypedData.js.map +1 -0
  32. package/_esm/actions/public/getSenderAddress.js +8 -6
  33. package/_esm/actions/public/getSenderAddress.js.map +1 -1
  34. package/_types/accounts/index.d.ts +2 -1
  35. package/_types/accounts/index.d.ts.map +1 -1
  36. package/_types/accounts/thirdweb/toThirdwebSmartAccount.d.ts +37 -0
  37. package/_types/accounts/thirdweb/toThirdwebSmartAccount.d.ts.map +1 -0
  38. package/_types/accounts/thirdweb/utils/encodeCallData.d.ts +6 -0
  39. package/_types/accounts/thirdweb/utils/encodeCallData.d.ts.map +1 -0
  40. package/_types/accounts/thirdweb/utils/getAccountAddress.d.ts +8 -0
  41. package/_types/accounts/thirdweb/utils/getAccountAddress.d.ts.map +1 -0
  42. package/_types/accounts/thirdweb/utils/getFactoryData.d.ts +6 -0
  43. package/_types/accounts/thirdweb/utils/getFactoryData.d.ts.map +1 -0
  44. package/_types/accounts/thirdweb/utils/signMessage.d.ts +8 -0
  45. package/_types/accounts/thirdweb/utils/signMessage.d.ts.map +1 -0
  46. package/_types/accounts/thirdweb/utils/signTypedData.d.ts +7 -0
  47. package/_types/accounts/thirdweb/utils/signTypedData.d.ts.map +1 -0
  48. package/_types/actions/public/getSenderAddress.d.ts.map +1 -1
  49. package/accounts/index.ts +12 -1
  50. package/accounts/thirdweb/toThirdwebSmartAccount.ts +203 -0
  51. package/accounts/thirdweb/utils/encodeCallData.ts +81 -0
  52. package/accounts/thirdweb/utils/getAccountAddress.ts +48 -0
  53. package/accounts/thirdweb/utils/getFactoryData.ts +40 -0
  54. package/accounts/thirdweb/utils/signMessage.ts +34 -0
  55. package/accounts/thirdweb/utils/signTypedData.ts +67 -0
  56. package/actions/public/getSenderAddress.ts +11 -8
  57. package/package.json +2 -8
@@ -0,0 +1,81 @@
1
+ import { encodeFunctionData } from "viem"
2
+
3
+ export const encodeCallData = async (
4
+ calls: readonly {
5
+ to: `0x${string}`
6
+ value?: bigint | undefined
7
+ data?: `0x${string}` | undefined
8
+ }[]
9
+ ) => {
10
+ if (calls.length > 1) {
11
+ return encodeFunctionData({
12
+ abi: [
13
+ {
14
+ inputs: [
15
+ {
16
+ internalType: "address[]",
17
+ name: "dest",
18
+ type: "address[]"
19
+ },
20
+ {
21
+ internalType: "uint256[]",
22
+ name: "value",
23
+ type: "uint256[]"
24
+ },
25
+ {
26
+ internalType: "bytes[]",
27
+ name: "func",
28
+ type: "bytes[]"
29
+ }
30
+ ],
31
+ name: "executeBatch",
32
+ outputs: [],
33
+ stateMutability: "nonpayable",
34
+ type: "function"
35
+ }
36
+ ],
37
+ functionName: "executeBatch",
38
+ args: [
39
+ calls.map((a) => a.to),
40
+ calls.map((a) => a.value ?? 0n),
41
+ calls.map((a) => a.data ?? "0x")
42
+ ]
43
+ })
44
+ }
45
+
46
+ const call = calls.length === 0 ? undefined : calls[0]
47
+
48
+ if (!call) {
49
+ throw new Error("No calls to encode")
50
+ }
51
+
52
+ return encodeFunctionData({
53
+ abi: [
54
+ {
55
+ inputs: [
56
+ {
57
+ internalType: "address",
58
+ name: "dest",
59
+ type: "address"
60
+ },
61
+ {
62
+ internalType: "uint256",
63
+ name: "value",
64
+ type: "uint256"
65
+ },
66
+ {
67
+ internalType: "bytes",
68
+ name: "func",
69
+ type: "bytes"
70
+ }
71
+ ],
72
+ name: "execute",
73
+ outputs: [],
74
+ stateMutability: "nonpayable",
75
+ type: "function"
76
+ }
77
+ ],
78
+ functionName: "execute",
79
+ args: [call.to, call.value ?? 0n, call.data ?? "0x"]
80
+ })
81
+ }
@@ -0,0 +1,48 @@
1
+ import type { Address, Client, Hex } from "viem"
2
+ import { readContract } from "viem/actions"
3
+ import { getAction } from "viem/utils"
4
+
5
+ export type GetAccountAddressParams = {
6
+ adminAddress: Address
7
+ factoryAddress: Address
8
+ salt: Hex
9
+ }
10
+
11
+ export const getAccountAddress = async (
12
+ client: Client,
13
+ args: GetAccountAddressParams
14
+ ): Promise<Address> => {
15
+ const { adminAddress, factoryAddress, salt } = args
16
+
17
+ return getAction(
18
+ client,
19
+ readContract,
20
+ "readContract"
21
+ )({
22
+ address: factoryAddress,
23
+ abi: [
24
+ {
25
+ inputs: [
26
+ {
27
+ name: "_adminSigner",
28
+ type: "address"
29
+ },
30
+ {
31
+ name: "_data",
32
+ type: "bytes"
33
+ }
34
+ ],
35
+ name: "getAddress",
36
+ outputs: [
37
+ {
38
+ type: "address"
39
+ }
40
+ ],
41
+ stateMutability: "view",
42
+ type: "function"
43
+ }
44
+ ],
45
+ functionName: "getAddress",
46
+ args: [adminAddress, salt]
47
+ })
48
+ }
@@ -0,0 +1,40 @@
1
+ import type { Address, Hex } from "viem"
2
+ import { encodeFunctionData } from "viem"
3
+
4
+ export const getFactoryData = async ({
5
+ admin,
6
+ salt
7
+ }: {
8
+ admin: Address
9
+ salt: Hex
10
+ }) => {
11
+ return encodeFunctionData({
12
+ abi: [
13
+ {
14
+ inputs: [
15
+ {
16
+ internalType: "address",
17
+ name: "_admin",
18
+ type: "address"
19
+ },
20
+ {
21
+ internalType: "bytes",
22
+ name: "_salt",
23
+ type: "bytes"
24
+ }
25
+ ],
26
+ name: "createAccount",
27
+ outputs: [
28
+ {
29
+ internalType: "address",
30
+ type: "address"
31
+ }
32
+ ],
33
+ stateMutability: "nonpayable",
34
+ type: "function"
35
+ }
36
+ ],
37
+ functionName: "createAccount",
38
+ args: [admin, salt]
39
+ })
40
+ }
@@ -0,0 +1,34 @@
1
+ import {
2
+ type Address,
3
+ type LocalAccount,
4
+ type SignMessageReturnType,
5
+ type SignableMessage,
6
+ hashMessage
7
+ } from "viem"
8
+ import { signMessage as _signMessage } from "viem/actions"
9
+
10
+ export async function signMessage({
11
+ message,
12
+ admin,
13
+ accountAddress,
14
+ chainId
15
+ }: {
16
+ chainId: number
17
+ message: SignableMessage
18
+ admin: LocalAccount
19
+ accountAddress: Address
20
+ }): Promise<SignMessageReturnType> {
21
+ const hashedMessage = hashMessage(message)
22
+
23
+ return admin.signTypedData({
24
+ domain: {
25
+ name: "Account",
26
+ version: "1",
27
+ chainId,
28
+ verifyingContract: accountAddress
29
+ },
30
+ primaryType: "AccountMessage",
31
+ types: { AccountMessage: [{ name: "message", type: "bytes" }] },
32
+ message: { message: hashedMessage }
33
+ })
34
+ }
@@ -0,0 +1,67 @@
1
+ import {
2
+ type Address,
3
+ type LocalAccount,
4
+ type SignTypedDataReturnType,
5
+ type TypedDataDefinition,
6
+ type TypedDataDomain,
7
+ encodeAbiParameters,
8
+ getTypesForEIP712Domain,
9
+ hashTypedData,
10
+ validateTypedData
11
+ } from "viem"
12
+
13
+ export async function signTypedData(
14
+ parameters: TypedDataDefinition & {
15
+ accountAddress: Address
16
+ chainId: number
17
+ admin: LocalAccount
18
+ }
19
+ ): Promise<SignTypedDataReturnType> {
20
+ const { admin, accountAddress, chainId, ...typedData } = parameters
21
+ const isSelfVerifyingContract =
22
+ (
23
+ typedData.domain as TypedDataDomain
24
+ )?.verifyingContract?.toLowerCase() === accountAddress
25
+
26
+ // If this is a self-verifying contract, we can use the admin's signature
27
+ if (isSelfVerifyingContract) {
28
+ return admin.signTypedData({
29
+ ...typedData
30
+ })
31
+ }
32
+
33
+ const { message, primaryType, types: _types, domain } = typedData
34
+ const types = {
35
+ EIP712Domain: getTypesForEIP712Domain({
36
+ domain: domain
37
+ }),
38
+ ..._types
39
+ }
40
+
41
+ // Need to do a runtime validation check on addresses, byte ranges, integer ranges, etc
42
+ // as we can't statically check this with TypeScript.
43
+ validateTypedData({
44
+ domain,
45
+ message,
46
+ primaryType,
47
+ types
48
+ })
49
+
50
+ const typedHash = hashTypedData({ message, primaryType, types, domain })
51
+ const wrappedMessageHash = encodeAbiParameters(
52
+ [{ type: "bytes32" }],
53
+ [typedHash]
54
+ )
55
+
56
+ return admin.signTypedData({
57
+ domain: {
58
+ name: "Account",
59
+ version: "1",
60
+ chainId,
61
+ verifyingContract: accountAddress
62
+ },
63
+ primaryType: "AccountMessage",
64
+ types: { AccountMessage: [{ name: "message", type: "bytes" }] },
65
+ message: { message: wrappedMessageHash }
66
+ })
67
+ }
@@ -8,6 +8,7 @@ import {
8
8
  InvalidInputRpcError,
9
9
  type OneOf,
10
10
  type Prettify,
11
+ RawContractError,
11
12
  RpcRequestError,
12
13
  UnknownRpcError,
13
14
  concat,
@@ -179,20 +180,22 @@ export const getSenderAddress = async (
179
180
  }
180
181
 
181
182
  if (revertError instanceof InvalidInputRpcError) {
182
- const hexStringRegex = /0x[a-fA-F0-9]+/
183
- // biome-ignore lint/suspicious/noExplicitAny:
184
- const match = (revertError as unknown as any).cause.data.match(
185
- hexStringRegex
186
- )
183
+ const { data: data_ } = (
184
+ e instanceof RawContractError
185
+ ? e
186
+ : e instanceof BaseError
187
+ ? e.walk((err) => "data" in (err as Error)) || e.walk()
188
+ : {}
189
+ ) as RawContractError
187
190
 
188
- if (!match) {
191
+ const data = typeof data_ === "string" ? data_ : data_?.data
192
+
193
+ if (data === undefined) {
189
194
  throw new Error(
190
195
  "Failed to parse revert bytes from RPC response"
191
196
  )
192
197
  }
193
198
 
194
- const data: Hex = match[0]
195
-
196
199
  const error = decodeErrorResult({
197
200
  abi: [
198
201
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "permissionless",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "author": "Pimlico",
5
5
  "homepage": "https://docs.pimlico.io/permissionless",
6
6
  "repository": "github:pimlicolabs/permissionless.js",
@@ -11,13 +11,7 @@
11
11
  "type": "module",
12
12
  "sideEffects": false,
13
13
  "description": "A utility library for working with ERC-4337",
14
- "keywords": [
15
- "ethereum",
16
- "erc-4337",
17
- "eip-4337",
18
- "paymaster",
19
- "bundler"
20
- ],
14
+ "keywords": ["ethereum", "erc-4337", "eip-4337", "paymaster", "bundler"],
21
15
  "license": "MIT",
22
16
  "exports": {
23
17
  ".": {