permissionless 0.1.35 → 0.1.36

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.
@@ -0,0 +1,198 @@
1
+ import type {
2
+ Abi,
3
+ Account,
4
+ Address,
5
+ Chain,
6
+ Client,
7
+ Hash,
8
+ Hex,
9
+ SignTypedDataParameters,
10
+ Transport,
11
+ TypedData
12
+ } from "viem"
13
+ import type { SignMessageParameters } from "viem"
14
+ import { describe, expectTypeOf, test } from "vitest"
15
+ import type { SmartAccount } from "../accounts"
16
+ import type { BundlerRpcSchema } from "../types/bundler"
17
+ import type {
18
+ ENTRYPOINT_ADDRESS_V06_TYPE,
19
+ EntryPoint
20
+ } from "../types/entrypoint"
21
+ import {
22
+ type DeployContractParametersWithPaymaster,
23
+ type PrepareUserOperationRequestParameters,
24
+ type PrepareUserOperationRequestReturnType,
25
+ type SendTransactionWithPaymasterParameters,
26
+ type SendTransactionsWithPaymasterParameters,
27
+ type SendUserOperationParameters,
28
+ type WriteContractWithPaymasterParameters,
29
+ deployContract,
30
+ prepareUserOperationRequest,
31
+ sendTransaction,
32
+ sendTransactions,
33
+ sendUserOperation,
34
+ signMessage,
35
+ signTypedData,
36
+ writeContract
37
+ } from "./smartAccount"
38
+
39
+ describe("index", () => {
40
+ test("sendUserOperation", () => {
41
+ expectTypeOf(deployContract).toBeFunction()
42
+ expectTypeOf(deployContract)
43
+ .parameter(0)
44
+ .toMatchTypeOf<
45
+ Client<
46
+ Transport,
47
+ Chain | undefined,
48
+ Account | undefined,
49
+ BundlerRpcSchema<EntryPoint>
50
+ >
51
+ >()
52
+ expectTypeOf(deployContract)
53
+ .parameter(1)
54
+ .toMatchTypeOf<DeployContractParametersWithPaymaster<EntryPoint>>()
55
+ expectTypeOf(deployContract).returns.toMatchTypeOf<Promise<Hash>>()
56
+ })
57
+ test("prepareUserOperationRequest", () => {
58
+ expectTypeOf(prepareUserOperationRequest).toBeFunction()
59
+ expectTypeOf(prepareUserOperationRequest)
60
+ .parameter(0)
61
+ .toMatchTypeOf<
62
+ Client<
63
+ Transport,
64
+ Chain | undefined,
65
+ Account | undefined,
66
+ BundlerRpcSchema<EntryPoint>
67
+ >
68
+ >()
69
+ expectTypeOf(prepareUserOperationRequest)
70
+ .parameter(1)
71
+ .toMatchTypeOf<PrepareUserOperationRequestParameters<EntryPoint>>()
72
+ expectTypeOf(prepareUserOperationRequest).returns.toMatchTypeOf<
73
+ Promise<PrepareUserOperationRequestReturnType<EntryPoint>>
74
+ >()
75
+ })
76
+ test("sendTransaction", () => {
77
+ expectTypeOf(sendTransaction).toBeFunction()
78
+ expectTypeOf(sendTransaction)
79
+ .parameter(0)
80
+ .toMatchTypeOf<
81
+ Client<
82
+ Transport,
83
+ Chain | undefined,
84
+ Account | undefined,
85
+ BundlerRpcSchema<EntryPoint>
86
+ >
87
+ >()
88
+ expectTypeOf(sendTransaction)
89
+ .parameter(1)
90
+ .toMatchTypeOf<SendTransactionWithPaymasterParameters<EntryPoint>>()
91
+ expectTypeOf(sendTransaction).returns.toMatchTypeOf<Promise<Hex>>()
92
+ })
93
+ test("sendTransactions", () => {
94
+ expectTypeOf(sendTransactions).toBeFunction()
95
+ expectTypeOf(sendTransactions)
96
+ .parameter(0)
97
+ .toMatchTypeOf<
98
+ Client<
99
+ Transport,
100
+ Chain | undefined,
101
+ Account | undefined,
102
+ BundlerRpcSchema<EntryPoint>
103
+ >
104
+ >()
105
+ expectTypeOf(sendTransactions)
106
+ .parameter(1)
107
+ .toMatchTypeOf<
108
+ SendTransactionsWithPaymasterParameters<EntryPoint>
109
+ >()
110
+ expectTypeOf(sendTransactions).returns.toMatchTypeOf<Promise<Hex>>()
111
+ })
112
+ test("writeContract", () => {
113
+ expectTypeOf(writeContract).toBeFunction()
114
+ expectTypeOf(writeContract)
115
+ .parameter(0)
116
+ .toMatchTypeOf<
117
+ Client<
118
+ Transport,
119
+ Chain | undefined,
120
+ Account | undefined,
121
+ BundlerRpcSchema<EntryPoint>
122
+ >
123
+ >()
124
+ expectTypeOf(
125
+ writeContract<
126
+ ENTRYPOINT_ADDRESS_V06_TYPE,
127
+ Chain,
128
+ SmartAccount<ENTRYPOINT_ADDRESS_V06_TYPE>,
129
+ Abi
130
+ >
131
+ )
132
+ .parameter(1)
133
+ .toMatchTypeOf<
134
+ WriteContractWithPaymasterParameters<
135
+ ENTRYPOINT_ADDRESS_V06_TYPE,
136
+ Chain,
137
+ SmartAccount<ENTRYPOINT_ADDRESS_V06_TYPE>,
138
+ Abi
139
+ >
140
+ >()
141
+ expectTypeOf(writeContract).returns.toMatchTypeOf<Promise<Hex>>()
142
+ })
143
+ test("sendUserOperation", () => {
144
+ expectTypeOf(sendUserOperation).toBeFunction()
145
+ expectTypeOf(sendUserOperation)
146
+ .parameter(0)
147
+ .toMatchTypeOf<
148
+ Client<
149
+ Transport,
150
+ Chain | undefined,
151
+ Account | undefined,
152
+ BundlerRpcSchema<EntryPoint>
153
+ >
154
+ >()
155
+ expectTypeOf(sendUserOperation)
156
+ .parameter(1)
157
+ .toMatchTypeOf<SendUserOperationParameters<EntryPoint>>()
158
+ expectTypeOf(sendUserOperation).returns.toMatchTypeOf<Promise<Hex>>()
159
+ })
160
+ test("signMessage", () => {
161
+ expectTypeOf(signMessage).toBeFunction()
162
+ expectTypeOf(signMessage)
163
+ .parameter(0)
164
+ .toMatchTypeOf<
165
+ Client<
166
+ Transport,
167
+ Chain | undefined,
168
+ Account | undefined,
169
+ BundlerRpcSchema<EntryPoint>
170
+ >
171
+ >()
172
+ expectTypeOf(signMessage)
173
+ .parameter(1)
174
+ .toMatchTypeOf<SignMessageParameters<SmartAccount<EntryPoint>>>()
175
+ expectTypeOf(signMessage).returns.toMatchTypeOf<Promise<Hex>>()
176
+ })
177
+ test("signTypedData", () => {
178
+ expectTypeOf(signTypedData).toBeFunction()
179
+ expectTypeOf(signTypedData)
180
+ .parameter(0)
181
+ .toMatchTypeOf<
182
+ Client<
183
+ Transport,
184
+ Chain | undefined,
185
+ Account | undefined,
186
+ BundlerRpcSchema<EntryPoint>
187
+ >
188
+ >()
189
+ expectTypeOf(
190
+ signTypedData<EntryPoint, TypedData, string, undefined, undefined>
191
+ )
192
+ .parameter(1)
193
+ .toMatchTypeOf<
194
+ SignTypedDataParameters<TypedData, string, undefined>
195
+ >()
196
+ expectTypeOf(signTypedData).returns.toMatchTypeOf<Promise<Hex>>()
197
+ })
198
+ })
@@ -0,0 +1,26 @@
1
+ import { http } from "viem"
2
+ import { describe, expect } from "vitest"
3
+ import { testWithRpc } from "../../permissionless-test/src/testWithRpc"
4
+ import { ENTRYPOINT_ADDRESS_V06, ENTRYPOINT_ADDRESS_V07 } from "../utils"
5
+ import { createBundlerClient } from "./createBundlerClient"
6
+
7
+ describe("createBundlerClient", () => {
8
+ testWithRpc("createBundlerClient_V06", async ({ rpc }) => {
9
+ const bundlerClientV06 = createBundlerClient({
10
+ transport: http(rpc.altoRpc),
11
+ entryPoint: ENTRYPOINT_ADDRESS_V06
12
+ })
13
+
14
+ const entryPoints = await bundlerClientV06.supportedEntryPoints()
15
+ expect(entryPoints).contain(ENTRYPOINT_ADDRESS_V06)
16
+ })
17
+
18
+ testWithRpc("createBundlerClient_V07", async ({ rpc }) => {
19
+ const bundlerClientV07 = createBundlerClient({
20
+ transport: http(rpc.altoRpc),
21
+ entryPoint: ENTRYPOINT_ADDRESS_V07
22
+ })
23
+ const entryPoints = await bundlerClientV07.supportedEntryPoints()
24
+ expect(entryPoints).contain(ENTRYPOINT_ADDRESS_V07)
25
+ })
26
+ })
@@ -0,0 +1,55 @@
1
+ import { http } from "viem"
2
+ import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
3
+ import { foundry } from "viem/chains"
4
+ import { describe, expect } from "vitest"
5
+ import { testWithRpc } from "../../permissionless-test/src/testWithRpc"
6
+ import { getPublicClient } from "../../permissionless-test/src/utils"
7
+ import { signerToSimpleSmartAccount } from "../accounts"
8
+ import { ENTRYPOINT_ADDRESS_V06, ENTRYPOINT_ADDRESS_V07 } from "../utils"
9
+ import { createSmartAccountClient } from "./createSmartAccountClient"
10
+
11
+ describe("createSmartAccountClient", () => {
12
+ testWithRpc("createSmartAccountClient_V06", async ({ rpc }) => {
13
+ const publicClient = getPublicClient(rpc.anvilRpc)
14
+
15
+ const simpleSmartAccount = await signerToSimpleSmartAccount(
16
+ publicClient,
17
+ {
18
+ entryPoint: ENTRYPOINT_ADDRESS_V06,
19
+ signer: privateKeyToAccount(generatePrivateKey())
20
+ }
21
+ )
22
+
23
+ const smartAccountClient = createSmartAccountClient({
24
+ chain: foundry,
25
+ account: simpleSmartAccount,
26
+ bundlerTransport: http(rpc.altoRpc)
27
+ })
28
+
29
+ expect(smartAccountClient.account.address).toBe(
30
+ simpleSmartAccount.address
31
+ )
32
+ })
33
+
34
+ testWithRpc("createSmartAccountClient_V07", async ({ rpc }) => {
35
+ const publicClient = getPublicClient(rpc.anvilRpc)
36
+
37
+ const simpleSmartAccount = await signerToSimpleSmartAccount(
38
+ publicClient,
39
+ {
40
+ entryPoint: ENTRYPOINT_ADDRESS_V07,
41
+ signer: privateKeyToAccount(generatePrivateKey())
42
+ }
43
+ )
44
+
45
+ const smartAccountClient = createSmartAccountClient({
46
+ chain: foundry,
47
+ account: simpleSmartAccount,
48
+ bundlerTransport: http(rpc.altoRpc)
49
+ })
50
+
51
+ expect(smartAccountClient.account.address).toBe(
52
+ simpleSmartAccount.address
53
+ )
54
+ })
55
+ })
@@ -0,0 +1,55 @@
1
+ import { http } from "viem"
2
+ import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
3
+ import { foundry } from "viem/chains"
4
+ import { describe, expect } from "vitest"
5
+ import { testWithRpc } from "../../../permissionless-test/src/testWithRpc"
6
+ import { getPublicClient } from "../../../permissionless-test/src/utils"
7
+ import { signerToSimpleSmartAccount } from "../../accounts"
8
+ import { ENTRYPOINT_ADDRESS_V06, ENTRYPOINT_ADDRESS_V07 } from "../../utils"
9
+ import { createSmartAccountClient } from "../createSmartAccountClient"
10
+
11
+ describe("createSmartAccountClient", () => {
12
+ testWithRpc("createSmartAccountClient_V06", async ({ rpc }) => {
13
+ const publicClient = getPublicClient(rpc.anvilRpc)
14
+
15
+ const simpleSmartAccount = await signerToSimpleSmartAccount(
16
+ publicClient,
17
+ {
18
+ entryPoint: ENTRYPOINT_ADDRESS_V06,
19
+ signer: privateKeyToAccount(generatePrivateKey())
20
+ }
21
+ )
22
+
23
+ const smartAccountClient = createSmartAccountClient({
24
+ chain: foundry,
25
+ account: simpleSmartAccount,
26
+ bundlerTransport: http(rpc.altoRpc)
27
+ })
28
+
29
+ expect(smartAccountClient.account.address).toBe(
30
+ simpleSmartAccount.address
31
+ )
32
+ })
33
+
34
+ testWithRpc("createSmartAccountClient_V07", async ({ rpc }) => {
35
+ const publicClient = getPublicClient(rpc.anvilRpc)
36
+
37
+ const simpleSmartAccount = await signerToSimpleSmartAccount(
38
+ publicClient,
39
+ {
40
+ entryPoint: ENTRYPOINT_ADDRESS_V07,
41
+ signer: privateKeyToAccount(generatePrivateKey())
42
+ }
43
+ )
44
+
45
+ const smartAccountClient = createSmartAccountClient({
46
+ chain: foundry,
47
+ account: simpleSmartAccount,
48
+ bundlerTransport: http(rpc.altoRpc)
49
+ })
50
+
51
+ expect(smartAccountClient.account.address).toBe(
52
+ simpleSmartAccount.address
53
+ )
54
+ })
55
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "permissionless",
3
- "version": "0.1.35",
3
+ "version": "0.1.36",
4
4
  "author": "Pimlico",
5
5
  "homepage": "https://docs.pimlico.io/permissionless",
6
6
  "repository": "github:pimlicolabs/permissionless.js",
@@ -0,0 +1,57 @@
1
+ import { toHex } from "viem"
2
+ import { describe, expect, test } from "vitest"
3
+ import { deepHexlify } from "../utils"
4
+
5
+ describe("deepHexlify", () => {
6
+ test("should return undefined for function input", async () => {
7
+ const func = () => {}
8
+ expect(deepHexlify(func)).toBeUndefined()
9
+ })
10
+
11
+ test("should return null for null input", () => {
12
+ expect(deepHexlify(null)).toBeNull()
13
+ })
14
+
15
+ test("should return the same string for string input", () => {
16
+ const str = "test"
17
+ expect(deepHexlify(str)).toBe(str)
18
+ })
19
+
20
+ test("should return the same boolean for boolean input", () => {
21
+ const bool = true
22
+ expect(deepHexlify(bool)).toBe(bool)
23
+ })
24
+
25
+ test("should return hex string for bigint input", () => {
26
+ const bigint = BigInt(12345)
27
+ expect(deepHexlify(bigint)).toBe(toHex(bigint))
28
+ })
29
+
30
+ test("should return hex string for number input", () => {
31
+ const number = 12345
32
+ expect(deepHexlify(number)).toBe(toHex(number).replace(/^0x0/, "0x"))
33
+ })
34
+
35
+ test("should return array with hex values for array input", () => {
36
+ const array = [12345, BigInt(67890)]
37
+ expect(deepHexlify(array)).toEqual([
38
+ toHex(12345).replace(/^0x0/, "0x"),
39
+ toHex(BigInt(67890))
40
+ ])
41
+ })
42
+
43
+ test("should return object with hex values for object input", () => {
44
+ const obj = {
45
+ a: 12345,
46
+ b: BigInt(67890),
47
+ c: "string",
48
+ d: true
49
+ }
50
+ expect(deepHexlify(obj)).toEqual({
51
+ a: toHex(12345).replace(/^0x0/, "0x"),
52
+ b: toHex(BigInt(67890)),
53
+ c: "string",
54
+ d: true
55
+ })
56
+ })
57
+ })
@@ -0,0 +1,68 @@
1
+ import { describe, expect, test } from "vitest"
2
+ import { encode7579CallData } from "./encode7579CallData"
3
+
4
+ describe("encode7579CallData", () => {
5
+ test("single call", async () => {
6
+ const callData = encode7579CallData({
7
+ mode: {
8
+ type: "call"
9
+ },
10
+ callData: {
11
+ to: "0x1234567890123456789012345678901234567890",
12
+ value: BigInt(12345),
13
+ data: "0x1234567890123456789012345678901234567890"
14
+ }
15
+ })
16
+
17
+ expect(callData).toBe(
18
+ "0xe9ae5c53000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000048123456789012345678901234567890123456789000000000000000000000000000000000000000000000000000000000000030391234567890123456789012345678901234567890000000000000000000000000000000000000000000000000"
19
+ )
20
+ })
21
+
22
+ test("batch call", async () => {
23
+ const callData = encode7579CallData({
24
+ mode: {
25
+ type: "batchcall"
26
+ },
27
+ callData: [
28
+ {
29
+ to: "0x1234567890123456789012345678901234567890",
30
+ value: BigInt(12345),
31
+ data: "0x1234567890123456789012345678901234567890"
32
+ },
33
+ {
34
+ to: "0x1234567890123456789012345678901234567890",
35
+ value: BigInt(12345),
36
+ data: "0x1234567890123456789012345678901234567890"
37
+ }
38
+ ]
39
+ })
40
+
41
+ expect(callData).toBe(
42
+ "0xe9ae5c53ff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000001234567890123456789012345678901234567890000000000000000000000000000000000000000000000000000000000000303900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000014123456789012345678901234567890123456789000000000000000000000000000000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000003039000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000141234567890123456789012345678901234567890000000000000000000000000"
43
+ )
44
+ })
45
+
46
+ test("should throw error for batch call with different mode", async () => {
47
+ expect(() => {
48
+ encode7579CallData({
49
+ mode: {
50
+ type: "call"
51
+ },
52
+ // @ts-expect-error
53
+ callData: [
54
+ {
55
+ to: "0x1234567890123456789012345678901234567890",
56
+ value: BigInt(12345),
57
+ data: "0x1234567890123456789012345678901234567890"
58
+ },
59
+ {
60
+ to: "0x1234567890123456789012345678901234567890",
61
+ value: BigInt(12345),
62
+ data: "0x1234567890123456789012345678901234567890"
63
+ }
64
+ ]
65
+ })
66
+ }).toThrowError("batchcall calldata")
67
+ })
68
+ })
@@ -33,7 +33,7 @@ export function encode7579CallData<callType extends CallType>({
33
33
  }: EncodeCallDataParams<callType>): Hex {
34
34
  if (Array.isArray(callData) && mode?.type !== "batchcall") {
35
35
  throw new Error(
36
- `mode ${mode} does not supported for batchcall calldata`
36
+ `mode ${JSON.stringify(mode)} does not supported for batchcall calldata`
37
37
  )
38
38
  }
39
39
 
@@ -0,0 +1,31 @@
1
+ import { describe, expect, test } from "vitest"
2
+ import { getAddressFromInitCodeOrPaymasterAndData } from "./getAddressFromInitCodeOrPaymasterAndData"
3
+
4
+ describe("getAddressFromInitCodeOrPaymasterAndData", () => {
5
+ test("should return undefined for undefined data", () => {
6
+ expect(
7
+ // @ts-expect-error
8
+ getAddressFromInitCodeOrPaymasterAndData(undefined)
9
+ ).toBeUndefined()
10
+ })
11
+
12
+ test("should return undefined for empty string data", () => {
13
+ // @ts-expect-error
14
+ expect(getAddressFromInitCodeOrPaymasterAndData("")).toBeUndefined()
15
+ })
16
+
17
+ test("should return undefined for data shorter than 42 characters", () => {
18
+ const shortData = "0x123456789"
19
+ expect(
20
+ getAddressFromInitCodeOrPaymasterAndData(shortData)
21
+ ).toBeUndefined()
22
+ })
23
+
24
+ test("should return the correct address for data exactly 42 characters", () => {
25
+ const expectedAddress = "0x1234567890123456789012345678901234567890"
26
+ const exactData = `${expectedAddress}_mocked_address_for`
27
+ expect(getAddressFromInitCodeOrPaymasterAndData(exactData)).toBe(
28
+ expectedAddress
29
+ )
30
+ })
31
+ })
@@ -0,0 +1,52 @@
1
+ import { describe, expect, test } from "vitest"
2
+ import {
3
+ ENTRYPOINT_ADDRESS_V06,
4
+ ENTRYPOINT_ADDRESS_V07,
5
+ getEntryPointVersion,
6
+ isUserOperationVersion06,
7
+ isUserOperationVersion07
8
+ } from "./getEntryPointVersion"
9
+
10
+ describe("getEntryPointVersion", () => {
11
+ describe("getEntryPointVersion", () => {
12
+ test('should return "v0.6" for ENTRYPOINT_ADDRESS_V06', () => {
13
+ expect(getEntryPointVersion(ENTRYPOINT_ADDRESS_V06)).toBe("v0.6")
14
+ })
15
+
16
+ test('should return "v0.7" for ENTRYPOINT_ADDRESS_V07', () => {
17
+ expect(getEntryPointVersion(ENTRYPOINT_ADDRESS_V07)).toBe("v0.7")
18
+ })
19
+ })
20
+
21
+ describe("isUserOperationVersion06", () => {
22
+ test('should return true for ENTRYPOINT_ADDRESS_V06 and UserOperation<"v0.6">', () => {
23
+ const userOperation = {} as any // mock UserOperation<"v0.6">
24
+ expect(
25
+ isUserOperationVersion06(ENTRYPOINT_ADDRESS_V06, userOperation)
26
+ ).toBe(true)
27
+ })
28
+
29
+ test('should return false for ENTRYPOINT_ADDRESS_V07 and UserOperation<"v0.6">', () => {
30
+ const userOperation = {} as any // mock UserOperation<"v0.6">
31
+ expect(
32
+ isUserOperationVersion06(ENTRYPOINT_ADDRESS_V07, userOperation)
33
+ ).toBe(false)
34
+ })
35
+ })
36
+
37
+ describe("isUserOperationVersion07", () => {
38
+ test('should return false for ENTRYPOINT_ADDRESS_V06 and UserOperation<"v0.6">', () => {
39
+ const userOperation = {} as any // mock UserOperation<"v0.6">
40
+ expect(
41
+ isUserOperationVersion07(ENTRYPOINT_ADDRESS_V06, userOperation)
42
+ ).toBe(false)
43
+ })
44
+
45
+ test('should return true for ENTRYPOINT_ADDRESS_V07 and UserOperation<"v0.7">', () => {
46
+ const userOperation = {} as any // mock UserOperation<"v0.7">
47
+ expect(
48
+ isUserOperationVersion07(ENTRYPOINT_ADDRESS_V07, userOperation)
49
+ ).toBe(true)
50
+ })
51
+ })
52
+ })