permissionless 0.1.41 → 0.1.42
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 +6 -0
- package/_cjs/actions/erc7579/installModule.js +3 -3
- package/_cjs/actions/erc7579/installModule.js.map +1 -1
- package/_cjs/actions/erc7579/installModules.js +65 -0
- package/_cjs/actions/erc7579/installModules.js.map +1 -0
- package/_cjs/actions/erc7579/uninstallModule.js +3 -3
- package/_cjs/actions/erc7579/uninstallModule.js.map +1 -1
- package/_cjs/actions/erc7579/uninstallModules.js +65 -0
- package/_cjs/actions/erc7579/uninstallModules.js.map +1 -0
- package/_cjs/actions/smartAccount/deployContract.js +2 -2
- package/_cjs/actions/smartAccount/deployContract.js.map +1 -1
- package/_cjs/actions/smartAccount/sendTransaction.js +2 -2
- package/_cjs/actions/smartAccount/sendTransaction.js.map +1 -1
- package/_cjs/actions/smartAccount/sendTransactions.js +2 -2
- package/_cjs/actions/smartAccount/sendTransactions.js.map +1 -1
- package/_esm/actions/erc7579/installModule.js +3 -3
- package/_esm/actions/erc7579/installModule.js.map +1 -1
- package/_esm/actions/erc7579/installModules.js +61 -0
- package/_esm/actions/erc7579/installModules.js.map +1 -0
- package/_esm/actions/erc7579/uninstallModule.js +3 -3
- package/_esm/actions/erc7579/uninstallModule.js.map +1 -1
- package/_esm/actions/erc7579/uninstallModules.js +61 -0
- package/_esm/actions/erc7579/uninstallModules.js.map +1 -0
- package/_esm/actions/smartAccount/deployContract.js +2 -2
- package/_esm/actions/smartAccount/deployContract.js.map +1 -1
- package/_esm/actions/smartAccount/sendTransaction.js +2 -2
- package/_esm/actions/smartAccount/sendTransaction.js.map +1 -1
- package/_esm/actions/smartAccount/sendTransactions.js +2 -2
- package/_esm/actions/smartAccount/sendTransactions.js.map +1 -1
- package/_types/actions/erc7579/installModules.d.ts +18 -0
- package/_types/actions/erc7579/installModules.d.ts.map +1 -0
- package/_types/actions/erc7579/uninstallModules.d.ts +20 -0
- package/_types/actions/erc7579/uninstallModules.d.ts.map +1 -0
- package/actions/erc7579/installModule.ts +3 -3
- package/actions/erc7579/installModules.test.ts +244 -0
- package/actions/erc7579/installModules.ts +115 -0
- package/actions/erc7579/uninstallModule.ts +3 -3
- package/actions/erc7579/uninstallModules.test.ts +168 -0
- package/actions/erc7579/uninstallModules.ts +120 -0
- package/actions/smartAccount/deployContract.ts +2 -2
- package/actions/smartAccount/sendTransaction.ts +2 -2
- package/actions/smartAccount/sendTransactions.ts +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import {
|
|
2
|
+
http,
|
|
3
|
+
type Chain,
|
|
4
|
+
type Transport,
|
|
5
|
+
encodeAbiParameters,
|
|
6
|
+
encodePacked,
|
|
7
|
+
isHash,
|
|
8
|
+
zeroAddress
|
|
9
|
+
} from "viem"
|
|
10
|
+
import { generatePrivateKey } from "viem/accounts"
|
|
11
|
+
import { describe, expect } from "vitest"
|
|
12
|
+
import { testWithRpc } from "../../../permissionless-test/src/testWithRpc"
|
|
13
|
+
import {
|
|
14
|
+
getCoreSmartAccounts,
|
|
15
|
+
getPimlicoPaymasterClient
|
|
16
|
+
} from "../../../permissionless-test/src/utils"
|
|
17
|
+
import type { SmartAccount } from "../../accounts"
|
|
18
|
+
import { createBundlerClient } from "../../clients/createBundlerClient"
|
|
19
|
+
import type { SmartAccountClient } from "../../clients/createSmartAccountClient"
|
|
20
|
+
import type { ENTRYPOINT_ADDRESS_V07_TYPE } from "../../types/entrypoint"
|
|
21
|
+
import { ENTRYPOINT_ADDRESS_V07 } from "../../utils"
|
|
22
|
+
import { erc7579Actions } from "../erc7579"
|
|
23
|
+
import { installModules } from "./installModules"
|
|
24
|
+
|
|
25
|
+
describe.each(getCoreSmartAccounts())(
|
|
26
|
+
"installmodules $name",
|
|
27
|
+
({ getErc7579SmartAccountClient, name }) => {
|
|
28
|
+
testWithRpc.skipIf(!getErc7579SmartAccountClient)(
|
|
29
|
+
"installModules",
|
|
30
|
+
async ({ rpc }) => {
|
|
31
|
+
const { anvilRpc, altoRpc, paymasterRpc } = rpc
|
|
32
|
+
|
|
33
|
+
if (!getErc7579SmartAccountClient) {
|
|
34
|
+
throw new Error("getErc7579SmartAccountClient not defined")
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const privateKey = generatePrivateKey()
|
|
38
|
+
|
|
39
|
+
const smartClientWithoutExtend: SmartAccountClient<
|
|
40
|
+
ENTRYPOINT_ADDRESS_V07_TYPE,
|
|
41
|
+
Transport,
|
|
42
|
+
Chain,
|
|
43
|
+
SmartAccount<ENTRYPOINT_ADDRESS_V07_TYPE>
|
|
44
|
+
> = await getErc7579SmartAccountClient({
|
|
45
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07,
|
|
46
|
+
privateKey: privateKey,
|
|
47
|
+
altoRpc: altoRpc,
|
|
48
|
+
anvilRpc: anvilRpc,
|
|
49
|
+
paymasterClient: getPimlicoPaymasterClient({
|
|
50
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07,
|
|
51
|
+
paymasterRpc
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const smartClient = smartClientWithoutExtend.extend(
|
|
56
|
+
erc7579Actions({
|
|
57
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07
|
|
58
|
+
})
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
const moduleData = encodePacked(
|
|
62
|
+
["address"],
|
|
63
|
+
[smartClient.account.address]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
const opHash = await installModules(smartClient as any, {
|
|
67
|
+
account: smartClient.account as any,
|
|
68
|
+
modules: [
|
|
69
|
+
{
|
|
70
|
+
type: "executor",
|
|
71
|
+
address:
|
|
72
|
+
"0xc98B026383885F41d9a995f85FC480E9bb8bB891",
|
|
73
|
+
context:
|
|
74
|
+
name === "Kernel 7579"
|
|
75
|
+
? encodePacked(
|
|
76
|
+
["address", "bytes"],
|
|
77
|
+
[
|
|
78
|
+
zeroAddress,
|
|
79
|
+
encodeAbiParameters(
|
|
80
|
+
[
|
|
81
|
+
{ type: "bytes" },
|
|
82
|
+
{ type: "bytes" }
|
|
83
|
+
],
|
|
84
|
+
[moduleData, "0x"]
|
|
85
|
+
)
|
|
86
|
+
]
|
|
87
|
+
)
|
|
88
|
+
: moduleData
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const bundlerClientV07 = createBundlerClient({
|
|
94
|
+
transport: http(altoRpc),
|
|
95
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
expect(isHash(opHash)).toBe(true)
|
|
99
|
+
|
|
100
|
+
const userOperationReceipt =
|
|
101
|
+
await bundlerClientV07.waitForUserOperationReceipt({
|
|
102
|
+
hash: opHash,
|
|
103
|
+
timeout: 100000
|
|
104
|
+
})
|
|
105
|
+
expect(userOperationReceipt).not.toBeNull()
|
|
106
|
+
expect(userOperationReceipt?.userOpHash).toBe(opHash)
|
|
107
|
+
expect(
|
|
108
|
+
userOperationReceipt?.receipt.transactionHash
|
|
109
|
+
).toBeTruthy()
|
|
110
|
+
|
|
111
|
+
const receipt = await bundlerClientV07.getUserOperationReceipt({
|
|
112
|
+
hash: opHash
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
expect(receipt?.receipt.transactionHash).toBe(
|
|
116
|
+
userOperationReceipt?.receipt.transactionHash
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
const isModuleInstalled = await smartClient.isModuleInstalled({
|
|
120
|
+
type: "executor",
|
|
121
|
+
address: "0xc98B026383885F41d9a995f85FC480E9bb8bB891",
|
|
122
|
+
context: "0x"
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
expect(isModuleInstalled).toBe(true)
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
testWithRpc.skipIf(!getErc7579SmartAccountClient)(
|
|
129
|
+
"installModule",
|
|
130
|
+
async ({ rpc }) => {
|
|
131
|
+
const { anvilRpc, altoRpc, paymasterRpc } = rpc
|
|
132
|
+
|
|
133
|
+
if (!getErc7579SmartAccountClient) {
|
|
134
|
+
throw new Error("getErc7579SmartAccountClient not defined")
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const privateKey = generatePrivateKey()
|
|
138
|
+
|
|
139
|
+
const smartClientWithoutExtend: SmartAccountClient<
|
|
140
|
+
ENTRYPOINT_ADDRESS_V07_TYPE,
|
|
141
|
+
Transport,
|
|
142
|
+
Chain,
|
|
143
|
+
SmartAccount<ENTRYPOINT_ADDRESS_V07_TYPE>
|
|
144
|
+
> = await getErc7579SmartAccountClient({
|
|
145
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07,
|
|
146
|
+
privateKey: privateKey,
|
|
147
|
+
altoRpc: altoRpc,
|
|
148
|
+
anvilRpc: anvilRpc,
|
|
149
|
+
paymasterClient: getPimlicoPaymasterClient({
|
|
150
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07,
|
|
151
|
+
paymasterRpc
|
|
152
|
+
})
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
const smartClient = smartClientWithoutExtend.extend(
|
|
156
|
+
erc7579Actions({
|
|
157
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07
|
|
158
|
+
})
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
await smartClient.sendTransactions({
|
|
162
|
+
transactions: [
|
|
163
|
+
{
|
|
164
|
+
to: smartClient.account.address,
|
|
165
|
+
value: 0n,
|
|
166
|
+
data: "0x"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
to: smartClient.account.address,
|
|
170
|
+
value: 0n,
|
|
171
|
+
data: "0x"
|
|
172
|
+
}
|
|
173
|
+
]
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
const moduleData = encodePacked(
|
|
177
|
+
["address"],
|
|
178
|
+
[smartClient.account.address]
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
const opHash = await installModules(smartClient as any, {
|
|
182
|
+
account: smartClient.account as any,
|
|
183
|
+
modules: [
|
|
184
|
+
{
|
|
185
|
+
type: "executor",
|
|
186
|
+
address:
|
|
187
|
+
"0xc98B026383885F41d9a995f85FC480E9bb8bB891",
|
|
188
|
+
context:
|
|
189
|
+
name === "Kernel 7579"
|
|
190
|
+
? encodePacked(
|
|
191
|
+
["address", "bytes"],
|
|
192
|
+
[
|
|
193
|
+
zeroAddress,
|
|
194
|
+
encodeAbiParameters(
|
|
195
|
+
[
|
|
196
|
+
{ type: "bytes" },
|
|
197
|
+
{ type: "bytes" }
|
|
198
|
+
],
|
|
199
|
+
[moduleData, "0x"]
|
|
200
|
+
)
|
|
201
|
+
]
|
|
202
|
+
)
|
|
203
|
+
: moduleData
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
const bundlerClientV07 = createBundlerClient({
|
|
209
|
+
transport: http(altoRpc),
|
|
210
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
expect(isHash(opHash)).toBe(true)
|
|
214
|
+
|
|
215
|
+
const userOperationReceipt =
|
|
216
|
+
await bundlerClientV07.waitForUserOperationReceipt({
|
|
217
|
+
hash: opHash,
|
|
218
|
+
timeout: 100000
|
|
219
|
+
})
|
|
220
|
+
expect(userOperationReceipt).not.toBeNull()
|
|
221
|
+
expect(userOperationReceipt?.userOpHash).toBe(opHash)
|
|
222
|
+
expect(
|
|
223
|
+
userOperationReceipt?.receipt.transactionHash
|
|
224
|
+
).toBeTruthy()
|
|
225
|
+
|
|
226
|
+
const receipt = await bundlerClientV07.getUserOperationReceipt({
|
|
227
|
+
hash: opHash
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
expect(receipt?.receipt.transactionHash).toBe(
|
|
231
|
+
userOperationReceipt?.receipt.transactionHash
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
const isModuleInstalled = await smartClient.isModuleInstalled({
|
|
235
|
+
type: "executor",
|
|
236
|
+
address: "0xc98B026383885F41d9a995f85FC480E9bb8bB891",
|
|
237
|
+
context: "0x"
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
expect(isModuleInstalled).toBe(true)
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Address,
|
|
3
|
+
type Chain,
|
|
4
|
+
type Client,
|
|
5
|
+
type Hex,
|
|
6
|
+
type Transport,
|
|
7
|
+
encodeFunctionData,
|
|
8
|
+
getAddress
|
|
9
|
+
} from "viem"
|
|
10
|
+
import { getAction } from "viem/utils"
|
|
11
|
+
import type { SmartAccount } from "../../accounts/types"
|
|
12
|
+
import type { GetAccountParameter, Prettify } from "../../types/"
|
|
13
|
+
import type { EntryPoint } from "../../types/entrypoint"
|
|
14
|
+
import { parseAccount } from "../../utils/"
|
|
15
|
+
import { AccountOrClientNotFoundError } from "../../utils/signUserOperationHashWithECDSA"
|
|
16
|
+
import type { Middleware } from "../smartAccount/prepareUserOperationRequest"
|
|
17
|
+
import { sendUserOperation } from "../smartAccount/sendUserOperation"
|
|
18
|
+
import { type ModuleType, parseModuleTypeId } from "./supportsModule"
|
|
19
|
+
|
|
20
|
+
export type InstallModulesParameters<
|
|
21
|
+
TEntryPoint extends EntryPoint,
|
|
22
|
+
TSmartAccount extends SmartAccount<TEntryPoint> | undefined
|
|
23
|
+
> = GetAccountParameter<TEntryPoint, TSmartAccount> &
|
|
24
|
+
Middleware<TEntryPoint> & {
|
|
25
|
+
modules: {
|
|
26
|
+
type: ModuleType
|
|
27
|
+
address: Address
|
|
28
|
+
context: Hex
|
|
29
|
+
}[]
|
|
30
|
+
maxFeePerGas?: bigint
|
|
31
|
+
maxPriorityFeePerGas?: bigint
|
|
32
|
+
nonce?: bigint
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function installModules<
|
|
36
|
+
TEntryPoint extends EntryPoint,
|
|
37
|
+
TSmartAccount extends SmartAccount<TEntryPoint> | undefined,
|
|
38
|
+
TTransport extends Transport = Transport,
|
|
39
|
+
TChain extends Chain | undefined = Chain | undefined
|
|
40
|
+
>(
|
|
41
|
+
client: Client<TTransport, TChain, TSmartAccount>,
|
|
42
|
+
parameters: Prettify<InstallModulesParameters<TEntryPoint, TSmartAccount>>
|
|
43
|
+
): Promise<Hex> {
|
|
44
|
+
const {
|
|
45
|
+
account: account_ = client.account,
|
|
46
|
+
maxFeePerGas,
|
|
47
|
+
maxPriorityFeePerGas,
|
|
48
|
+
nonce,
|
|
49
|
+
middleware,
|
|
50
|
+
modules
|
|
51
|
+
} = parameters
|
|
52
|
+
|
|
53
|
+
if (!account_) {
|
|
54
|
+
throw new AccountOrClientNotFoundError({
|
|
55
|
+
docsPath: "/docs/actions/wallet/sendTransaction"
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const account = parseAccount(account_) as SmartAccount<TEntryPoint>
|
|
60
|
+
|
|
61
|
+
const installModulesCallData = await account.encodeCallData(
|
|
62
|
+
await Promise.all(
|
|
63
|
+
modules.map(({ type, address, context }) => ({
|
|
64
|
+
to: account.address,
|
|
65
|
+
value: BigInt(0),
|
|
66
|
+
data: encodeFunctionData({
|
|
67
|
+
abi: [
|
|
68
|
+
{
|
|
69
|
+
name: "installModule",
|
|
70
|
+
type: "function",
|
|
71
|
+
stateMutability: "nonpayable",
|
|
72
|
+
inputs: [
|
|
73
|
+
{
|
|
74
|
+
type: "uint256",
|
|
75
|
+
name: "moduleTypeId"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
type: "address",
|
|
79
|
+
name: "module"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
type: "bytes",
|
|
83
|
+
name: "initData"
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
outputs: []
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
functionName: "installModule",
|
|
90
|
+
args: [
|
|
91
|
+
parseModuleTypeId(type),
|
|
92
|
+
getAddress(address),
|
|
93
|
+
context
|
|
94
|
+
]
|
|
95
|
+
})
|
|
96
|
+
}))
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return getAction(
|
|
101
|
+
client,
|
|
102
|
+
sendUserOperation<TEntryPoint>,
|
|
103
|
+
"sendUserOperation"
|
|
104
|
+
)({
|
|
105
|
+
userOperation: {
|
|
106
|
+
sender: account.address,
|
|
107
|
+
maxFeePerGas: maxFeePerGas,
|
|
108
|
+
maxPriorityFeePerGas: maxPriorityFeePerGas,
|
|
109
|
+
callData: installModulesCallData,
|
|
110
|
+
nonce: nonce
|
|
111
|
+
},
|
|
112
|
+
account: account,
|
|
113
|
+
middleware
|
|
114
|
+
})
|
|
115
|
+
}
|
|
@@ -102,10 +102,10 @@ export async function uninstallModule<
|
|
|
102
102
|
)({
|
|
103
103
|
userOperation: {
|
|
104
104
|
sender: account.address,
|
|
105
|
-
maxFeePerGas: maxFeePerGas
|
|
106
|
-
maxPriorityFeePerGas: maxPriorityFeePerGas
|
|
105
|
+
maxFeePerGas: maxFeePerGas,
|
|
106
|
+
maxPriorityFeePerGas: maxPriorityFeePerGas,
|
|
107
107
|
callData: uninstallModuleCallData,
|
|
108
|
-
nonce: nonce
|
|
108
|
+
nonce: nonce
|
|
109
109
|
},
|
|
110
110
|
account: account,
|
|
111
111
|
middleware
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import {
|
|
2
|
+
http,
|
|
3
|
+
type Chain,
|
|
4
|
+
type Transport,
|
|
5
|
+
encodeAbiParameters,
|
|
6
|
+
encodePacked,
|
|
7
|
+
isHash,
|
|
8
|
+
zeroAddress
|
|
9
|
+
} from "viem"
|
|
10
|
+
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
|
|
11
|
+
import { describe, expect } from "vitest"
|
|
12
|
+
import { testWithRpc } from "../../../permissionless-test/src/testWithRpc"
|
|
13
|
+
import {
|
|
14
|
+
getCoreSmartAccounts,
|
|
15
|
+
getPimlicoPaymasterClient,
|
|
16
|
+
getPublicClient
|
|
17
|
+
} from "../../../permissionless-test/src/utils"
|
|
18
|
+
import type { SmartAccount } from "../../accounts"
|
|
19
|
+
import { createBundlerClient } from "../../clients/createBundlerClient"
|
|
20
|
+
import type { SmartAccountClient } from "../../clients/createSmartAccountClient"
|
|
21
|
+
import type { ENTRYPOINT_ADDRESS_V07_TYPE } from "../../types"
|
|
22
|
+
import { ENTRYPOINT_ADDRESS_V07 } from "../../utils"
|
|
23
|
+
import { erc7579Actions } from "../erc7579"
|
|
24
|
+
import { uninstallModules } from "./uninstallModules"
|
|
25
|
+
|
|
26
|
+
describe.each(getCoreSmartAccounts())(
|
|
27
|
+
"uninstallModules $name",
|
|
28
|
+
({ getErc7579SmartAccountClient, name }) => {
|
|
29
|
+
testWithRpc.skipIf(!getErc7579SmartAccountClient)(
|
|
30
|
+
"uninstallModules",
|
|
31
|
+
async ({ rpc }) => {
|
|
32
|
+
const { anvilRpc, altoRpc, paymasterRpc } = rpc
|
|
33
|
+
|
|
34
|
+
if (!getErc7579SmartAccountClient) {
|
|
35
|
+
throw new Error("getErc7579SmartAccountClient not defined")
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const privateKey = generatePrivateKey()
|
|
39
|
+
|
|
40
|
+
const eoaAccount = privateKeyToAccount(privateKey)
|
|
41
|
+
|
|
42
|
+
const smartClientWithoutExtend: SmartAccountClient<
|
|
43
|
+
ENTRYPOINT_ADDRESS_V07_TYPE,
|
|
44
|
+
Transport,
|
|
45
|
+
Chain,
|
|
46
|
+
SmartAccount<ENTRYPOINT_ADDRESS_V07_TYPE>
|
|
47
|
+
> = await getErc7579SmartAccountClient({
|
|
48
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07,
|
|
49
|
+
privateKey: privateKey,
|
|
50
|
+
altoRpc: altoRpc,
|
|
51
|
+
anvilRpc: anvilRpc,
|
|
52
|
+
paymasterClient: getPimlicoPaymasterClient({
|
|
53
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07,
|
|
54
|
+
paymasterRpc
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const smartClient = smartClientWithoutExtend.extend(
|
|
59
|
+
erc7579Actions({
|
|
60
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07
|
|
61
|
+
})
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
const moduleData = encodePacked(
|
|
65
|
+
["address"],
|
|
66
|
+
[smartClient.account.address]
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
const bundlerClientV07 = createBundlerClient({
|
|
70
|
+
transport: http(altoRpc),
|
|
71
|
+
entryPoint: ENTRYPOINT_ADDRESS_V07
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
const publicClient = getPublicClient(anvilRpc)
|
|
75
|
+
|
|
76
|
+
const opHash = await smartClient.installModule({
|
|
77
|
+
type: "executor",
|
|
78
|
+
address: "0xc98B026383885F41d9a995f85FC480E9bb8bB891",
|
|
79
|
+
context:
|
|
80
|
+
name === "Kernel 7579"
|
|
81
|
+
? encodePacked(
|
|
82
|
+
["address", "bytes"],
|
|
83
|
+
[
|
|
84
|
+
zeroAddress,
|
|
85
|
+
encodeAbiParameters(
|
|
86
|
+
[
|
|
87
|
+
{ type: "bytes" },
|
|
88
|
+
{ type: "bytes" }
|
|
89
|
+
],
|
|
90
|
+
[moduleData, "0x"]
|
|
91
|
+
)
|
|
92
|
+
]
|
|
93
|
+
)
|
|
94
|
+
: moduleData
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
const userOperationReceipt =
|
|
98
|
+
await bundlerClientV07.waitForUserOperationReceipt({
|
|
99
|
+
hash: opHash,
|
|
100
|
+
timeout: 100000
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
await publicClient.waitForTransactionReceipt({
|
|
104
|
+
hash: userOperationReceipt.receipt.transactionHash
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
const uninstallModulesUserOpHash = await uninstallModules(
|
|
108
|
+
smartClient as any,
|
|
109
|
+
{
|
|
110
|
+
account: smartClient.account as any,
|
|
111
|
+
modules: [
|
|
112
|
+
{
|
|
113
|
+
type: "executor",
|
|
114
|
+
address:
|
|
115
|
+
"0xc98B026383885F41d9a995f85FC480E9bb8bB891",
|
|
116
|
+
context:
|
|
117
|
+
name === "Kernel 7579"
|
|
118
|
+
? "0x"
|
|
119
|
+
: encodeAbiParameters(
|
|
120
|
+
[
|
|
121
|
+
{
|
|
122
|
+
name: "prev",
|
|
123
|
+
type: "address"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: "moduleInitData",
|
|
127
|
+
type: "bytes"
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
[
|
|
131
|
+
"0x0000000000000000000000000000000000000001",
|
|
132
|
+
"0x"
|
|
133
|
+
]
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
expect(isHash(uninstallModulesUserOpHash)).toBe(true)
|
|
141
|
+
|
|
142
|
+
const userOperationReceiptUninstallModules =
|
|
143
|
+
await bundlerClientV07.waitForUserOperationReceipt({
|
|
144
|
+
hash: uninstallModulesUserOpHash,
|
|
145
|
+
timeout: 100000
|
|
146
|
+
})
|
|
147
|
+
expect(userOperationReceiptUninstallModules).not.toBeNull()
|
|
148
|
+
expect(userOperationReceiptUninstallModules?.userOpHash).toBe(
|
|
149
|
+
uninstallModulesUserOpHash
|
|
150
|
+
)
|
|
151
|
+
expect(
|
|
152
|
+
userOperationReceiptUninstallModules?.receipt
|
|
153
|
+
.transactionHash
|
|
154
|
+
).toBeTruthy()
|
|
155
|
+
|
|
156
|
+
const receiptUninstallModules =
|
|
157
|
+
await bundlerClientV07.getUserOperationReceipt({
|
|
158
|
+
hash: uninstallModulesUserOpHash
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
expect(receiptUninstallModules?.receipt.transactionHash).toBe(
|
|
162
|
+
userOperationReceiptUninstallModules?.receipt
|
|
163
|
+
.transactionHash
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Address,
|
|
3
|
+
type Chain,
|
|
4
|
+
type Client,
|
|
5
|
+
type Hex,
|
|
6
|
+
type Transport,
|
|
7
|
+
encodeFunctionData,
|
|
8
|
+
getAddress
|
|
9
|
+
} from "viem"
|
|
10
|
+
import { getAction } from "viem/utils"
|
|
11
|
+
import type { SmartAccount } from "../../accounts/types"
|
|
12
|
+
import type { GetAccountParameter, Prettify } from "../../types/"
|
|
13
|
+
import type { EntryPoint } from "../../types/entrypoint"
|
|
14
|
+
import { parseAccount } from "../../utils/"
|
|
15
|
+
import { AccountOrClientNotFoundError } from "../../utils/signUserOperationHashWithECDSA"
|
|
16
|
+
import type { Middleware } from "../smartAccount/prepareUserOperationRequest"
|
|
17
|
+
import { sendUserOperation } from "../smartAccount/sendUserOperation"
|
|
18
|
+
import { type ModuleType, parseModuleTypeId } from "./supportsModule"
|
|
19
|
+
|
|
20
|
+
export type UninstallModulesParameters<
|
|
21
|
+
TEntryPoint extends EntryPoint,
|
|
22
|
+
TSmartAccount extends SmartAccount<TEntryPoint> | undefined =
|
|
23
|
+
| SmartAccount<TEntryPoint>
|
|
24
|
+
| undefined
|
|
25
|
+
> = GetAccountParameter<TEntryPoint, TSmartAccount> & {
|
|
26
|
+
modules: [
|
|
27
|
+
{
|
|
28
|
+
type: ModuleType
|
|
29
|
+
address: Address
|
|
30
|
+
context: Hex
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
maxFeePerGas?: bigint
|
|
34
|
+
maxPriorityFeePerGas?: bigint
|
|
35
|
+
nonce?: bigint
|
|
36
|
+
} & Middleware<TEntryPoint>
|
|
37
|
+
|
|
38
|
+
export async function uninstallModules<
|
|
39
|
+
TEntryPoint extends EntryPoint,
|
|
40
|
+
TSmartAccount extends SmartAccount<TEntryPoint> | undefined =
|
|
41
|
+
| SmartAccount<TEntryPoint>
|
|
42
|
+
| undefined,
|
|
43
|
+
TTransport extends Transport = Transport,
|
|
44
|
+
TChain extends Chain | undefined = Chain | undefined
|
|
45
|
+
>(
|
|
46
|
+
client: Client<TTransport, TChain, TSmartAccount>,
|
|
47
|
+
parameters: Prettify<UninstallModulesParameters<TEntryPoint, TSmartAccount>>
|
|
48
|
+
): Promise<Hex> {
|
|
49
|
+
const {
|
|
50
|
+
account: account_ = client.account,
|
|
51
|
+
maxFeePerGas,
|
|
52
|
+
maxPriorityFeePerGas,
|
|
53
|
+
nonce,
|
|
54
|
+
middleware,
|
|
55
|
+
modules
|
|
56
|
+
} = parameters
|
|
57
|
+
|
|
58
|
+
if (!account_) {
|
|
59
|
+
throw new AccountOrClientNotFoundError({
|
|
60
|
+
docsPath: "/docs/actions/wallet/sendTransaction"
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const account = parseAccount(account_) as SmartAccount<TEntryPoint>
|
|
65
|
+
|
|
66
|
+
const uninstallModulesCallData = await account.encodeCallData(
|
|
67
|
+
await Promise.all(
|
|
68
|
+
modules.map(({ type, address, context }) => ({
|
|
69
|
+
to: account.address,
|
|
70
|
+
value: BigInt(0),
|
|
71
|
+
data: encodeFunctionData({
|
|
72
|
+
abi: [
|
|
73
|
+
{
|
|
74
|
+
name: "uninstallModule",
|
|
75
|
+
type: "function",
|
|
76
|
+
stateMutability: "nonpayable",
|
|
77
|
+
inputs: [
|
|
78
|
+
{
|
|
79
|
+
type: "uint256",
|
|
80
|
+
name: "moduleTypeId"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
type: "address",
|
|
84
|
+
name: "module"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
type: "bytes",
|
|
88
|
+
name: "deInitData"
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
outputs: []
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
functionName: "uninstallModule",
|
|
95
|
+
args: [
|
|
96
|
+
parseModuleTypeId(type),
|
|
97
|
+
getAddress(address),
|
|
98
|
+
context
|
|
99
|
+
]
|
|
100
|
+
})
|
|
101
|
+
}))
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
return getAction(
|
|
106
|
+
client,
|
|
107
|
+
sendUserOperation<TEntryPoint>,
|
|
108
|
+
"sendUserOperation"
|
|
109
|
+
)({
|
|
110
|
+
userOperation: {
|
|
111
|
+
sender: account.address,
|
|
112
|
+
maxFeePerGas: maxFeePerGas,
|
|
113
|
+
maxPriorityFeePerGas: maxPriorityFeePerGas,
|
|
114
|
+
callData: uninstallModulesCallData,
|
|
115
|
+
nonce: nonce
|
|
116
|
+
},
|
|
117
|
+
account: account,
|
|
118
|
+
middleware
|
|
119
|
+
})
|
|
120
|
+
}
|
|
@@ -91,8 +91,8 @@ export async function deployContract<
|
|
|
91
91
|
)({
|
|
92
92
|
userOperation: {
|
|
93
93
|
sender: account.address,
|
|
94
|
-
maxFeePerGas: request.maxFeePerGas
|
|
95
|
-
maxPriorityFeePerGas: request.maxPriorityFeePerGas
|
|
94
|
+
maxFeePerGas: request.maxFeePerGas,
|
|
95
|
+
maxPriorityFeePerGas: request.maxPriorityFeePerGas,
|
|
96
96
|
callData: await account.encodeDeployCallData({
|
|
97
97
|
abi,
|
|
98
98
|
bytecode,
|
|
@@ -124,8 +124,8 @@ export async function sendTransaction<
|
|
|
124
124
|
)({
|
|
125
125
|
userOperation: {
|
|
126
126
|
sender: account.address,
|
|
127
|
-
maxFeePerGas: maxFeePerGas
|
|
128
|
-
maxPriorityFeePerGas: maxPriorityFeePerGas
|
|
127
|
+
maxFeePerGas: maxFeePerGas,
|
|
128
|
+
maxPriorityFeePerGas: maxPriorityFeePerGas,
|
|
129
129
|
callData: callData,
|
|
130
130
|
nonce: nonce ? BigInt(nonce) : undefined
|
|
131
131
|
},
|