@deserialize/multi-vm-wallet 1.2.293 → 1.3.0

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 (106) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/SMART_WALLET_GUIDE.md +746 -0
  3. package/SMART_WALLET_IMPLEMENTATION.md +460 -0
  4. package/dist/IChainWallet.d.ts +4 -3
  5. package/dist/IChainWallet.js +5 -0
  6. package/dist/IChainWallet.js.map +1 -1
  7. package/dist/constant.js +17 -4
  8. package/dist/constant.js.map +1 -1
  9. package/dist/evm/SMART_WALLET_EXAMPLES.d.ts +20 -0
  10. package/dist/evm/SMART_WALLET_EXAMPLES.js +451 -0
  11. package/dist/evm/SMART_WALLET_EXAMPLES.js.map +1 -0
  12. package/dist/evm/aa-service/index.d.ts +16 -0
  13. package/dist/evm/aa-service/index.js +69 -0
  14. package/dist/evm/aa-service/index.js.map +1 -0
  15. package/dist/evm/aa-service/lib/account-adapter.d.ts +26 -0
  16. package/dist/evm/aa-service/lib/account-adapter.js +53 -0
  17. package/dist/evm/aa-service/lib/account-adapter.js.map +1 -0
  18. package/dist/evm/aa-service/lib/kernel-account.d.ts +91 -0
  19. package/dist/evm/aa-service/lib/kernel-account.js +251 -0
  20. package/dist/evm/aa-service/lib/kernel-account.js.map +1 -0
  21. package/dist/evm/aa-service/lib/kernel-modules.d.ts +240 -0
  22. package/dist/evm/aa-service/lib/kernel-modules.js +409 -0
  23. package/dist/evm/aa-service/lib/kernel-modules.js.map +1 -0
  24. package/dist/evm/aa-service/lib/session-keys.d.ts +170 -0
  25. package/dist/evm/aa-service/lib/session-keys.js +297 -0
  26. package/dist/evm/aa-service/lib/session-keys.js.map +1 -0
  27. package/dist/evm/aa-service/lib/type.d.ts +167 -0
  28. package/dist/evm/aa-service/lib/type.js +43 -0
  29. package/dist/evm/aa-service/lib/type.js.map +1 -0
  30. package/dist/evm/aa-service/services/account-abstraction.d.ts +614 -0
  31. package/dist/evm/aa-service/services/account-abstraction.js +754 -0
  32. package/dist/evm/aa-service/services/account-abstraction.js.map +1 -0
  33. package/dist/evm/aa-service/services/bundler.d.ts +29 -0
  34. package/dist/evm/aa-service/services/bundler.js +168 -0
  35. package/dist/evm/aa-service/services/bundler.js.map +1 -0
  36. package/dist/evm/evm.d.ts +68 -3
  37. package/dist/evm/evm.js +223 -8
  38. package/dist/evm/evm.js.map +1 -1
  39. package/dist/evm/index.d.ts +1 -0
  40. package/dist/evm/index.js +3 -0
  41. package/dist/evm/index.js.map +1 -1
  42. package/dist/evm/smartWallet.d.ts +265 -0
  43. package/dist/evm/smartWallet.js +675 -0
  44. package/dist/evm/smartWallet.js.map +1 -0
  45. package/dist/evm/smartWallet.types.d.ts +10 -0
  46. package/dist/evm/smartWallet.types.js +16 -0
  47. package/dist/evm/smartWallet.types.js.map +1 -0
  48. package/dist/evm/transaction.utils.d.ts +10 -10
  49. package/dist/evm/transaction.utils.js +12 -8
  50. package/dist/evm/transaction.utils.js.map +1 -1
  51. package/dist/evm/transactionParsing.js +123 -27
  52. package/dist/evm/transactionParsing.js.map +1 -1
  53. package/dist/evm/utils.d.ts +12 -1
  54. package/dist/evm/utils.js +138 -2
  55. package/dist/evm/utils.js.map +1 -1
  56. package/dist/helpers/index.d.ts +4 -1
  57. package/dist/helpers/index.js +25 -0
  58. package/dist/helpers/index.js.map +1 -1
  59. package/dist/helpers/routeScan.d.ts +191 -0
  60. package/dist/helpers/routeScan.js +114 -0
  61. package/dist/helpers/routeScan.js.map +1 -0
  62. package/dist/index.d.ts +0 -2
  63. package/dist/index.js +0 -2
  64. package/dist/index.js.map +1 -1
  65. package/dist/svm/svm.d.ts +6 -4
  66. package/dist/svm/svm.js +33 -19
  67. package/dist/svm/svm.js.map +1 -1
  68. package/dist/svm/transactionSender.js +2 -2
  69. package/dist/svm/transactionSender.js.map +1 -1
  70. package/dist/svm/utils.d.ts +20 -4
  71. package/dist/svm/utils.js +232 -12
  72. package/dist/svm/utils.js.map +1 -1
  73. package/dist/test.d.ts +1 -6
  74. package/dist/test.js +47 -16
  75. package/dist/test.js.map +1 -1
  76. package/dist/types.d.ts +169 -2
  77. package/dist/types.js.map +1 -1
  78. package/dist/vm.js +9 -7
  79. package/dist/vm.js.map +1 -1
  80. package/package.json +2 -2
  81. package/tsconfig.json +4 -3
  82. package/utils/IChainWallet.ts +4 -3
  83. package/utils/constant.ts +18 -4
  84. package/utils/evm/SMART_WALLET_EXAMPLES.ts.bak +591 -0
  85. package/utils/evm/aa-service/index.ts +85 -0
  86. package/utils/evm/aa-service/lib/account-adapter.ts +60 -0
  87. package/utils/evm/aa-service/lib/kernel-account.ts +367 -0
  88. package/utils/evm/aa-service/lib/kernel-modules.ts +598 -0
  89. package/utils/evm/aa-service/lib/session-keys.ts +389 -0
  90. package/utils/evm/aa-service/lib/type.ts +236 -0
  91. package/utils/evm/aa-service/services/account-abstraction.ts +1015 -0
  92. package/utils/evm/aa-service/services/bundler.ts +217 -0
  93. package/utils/evm/evm.ts +281 -13
  94. package/utils/evm/index.ts +5 -1
  95. package/utils/evm/smartWallet.ts +797 -0
  96. package/utils/evm/smartWallet.types.ts +33 -0
  97. package/utils/evm/transaction.utils.ts +12 -10
  98. package/utils/evm/transactionParsing.ts +153 -63
  99. package/utils/evm/utils.ts +161 -2
  100. package/utils/helpers/index.ts +13 -1
  101. package/utils/helpers/routeScan.ts +397 -0
  102. package/utils/index.ts +0 -2
  103. package/utils/svm/svm.ts +61 -14
  104. package/utils/svm/utils.ts +317 -14
  105. package/utils/test.ts +54 -18
  106. package/utils/types.ts +223 -2
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Account Adapter
3
+ *
4
+ * Adapts ZeroDev's account objects to work with our service layer.
5
+ * Normalizes the interface to match KernelAccountInstance.
6
+ */
7
+
8
+ import { Chain, Hex } from 'viem';
9
+ import { entryPoint07Address } from 'viem/account-abstraction';
10
+ import { KernelAccountInstance } from './kernel-account';
11
+
12
+ /**
13
+ * Adapt a ZeroDev account to our KernelAccountInstance interface
14
+ *
15
+ * ZeroDev's createKernelAccount returns a different structure than what
16
+ * our service expects. This adapter normalizes it.
17
+ *
18
+ * @param account - The account from createKernelAccount
19
+ * @param chain - The chain the account is on
20
+ * @returns Normalized account that works with our service
21
+ */
22
+ export function adaptZeroDevAccount(
23
+ account: any,
24
+ chain: Chain
25
+ ): KernelAccountInstance {
26
+ return {
27
+ ...account,
28
+ chain,
29
+ entryPoint: account.entryPoint || {
30
+ address: entryPoint07Address,
31
+ version: '0.7'
32
+ }
33
+ } as KernelAccountInstance;
34
+ }
35
+
36
+ /**
37
+ * Adapt a session key account specifically
38
+ *
39
+ * Session key accounts need special handling to ensure all properties
40
+ * are properly set for transaction execution.
41
+ */
42
+ export function adaptSessionKeyAccount(
43
+ sessionKeyAccount: any,
44
+ masterAccount: KernelAccountInstance
45
+ ): KernelAccountInstance {
46
+ // Ensure entryPoint is properly defined
47
+ const entryPoint = sessionKeyAccount.entryPoint || masterAccount.entryPoint || {
48
+ address: entryPoint07Address,
49
+ version: '0.7'
50
+ };
51
+
52
+ return {
53
+ ...sessionKeyAccount,
54
+ chain: masterAccount.chain,
55
+ entryPoint: {
56
+ address: entryPoint.address || entryPoint07Address,
57
+ version: entryPoint.version || '0.7'
58
+ }
59
+ } as KernelAccountInstance;
60
+ }
@@ -0,0 +1,367 @@
1
+ /**
2
+ * Kernel Account Factory
3
+ *
4
+ * Modular factory for creating Kernel smart accounts with EIP-7702.
5
+ * Supports multiple bundlers, chains, and EntryPoint versions.
6
+ */
7
+
8
+ import { Chain, Hex, parseEther, PublicClient, SignAuthorizationReturnType, createPublicClient, http } from 'viem';
9
+ import { PrivateKeyAccount, privateKeyToAccount } from 'viem/accounts';
10
+ import { createKernelAccount } from '@zerodev/sdk';
11
+ import { KERNEL_V3_3, KernelVersionToAddressesMap } from '@zerodev/sdk/constants';
12
+ import { entryPoint07Address, entryPoint08Address } from 'viem/account-abstraction';
13
+ import { BundlerManager, createBundlerService } from '../services/bundler';
14
+ import { BatchTransactionConfig, EntryPointVersion, KernelAccountConfig, KernelAccountInstance, KernelVersion, SingleTransactionConfig, Call } from './type';
15
+
16
+ // Re-export types so other files can import from this module
17
+ export type {
18
+ Call,
19
+ KernelAccountInstance,
20
+ EntryPointVersion,
21
+ KernelVersion,
22
+ KernelAccountConfig,
23
+ BatchTransactionConfig,
24
+ SingleTransactionConfig
25
+ } from './type';
26
+
27
+
28
+
29
+ // ============================================
30
+ // EntryPoint Mapping
31
+ // ============================================
32
+
33
+ const ENTRYPOINT_MAP: Record<EntryPointVersion, Hex> = {
34
+ '0.6': entryPoint07Address, // Fallback to 0.7 for 0.6 requests
35
+ '0.7': entryPoint07Address
36
+ };
37
+
38
+ // ============================================
39
+ // Kernel Account Factory
40
+ // ============================================
41
+
42
+ export async function createKernel7702Account(
43
+ config: KernelAccountConfig
44
+ ): Promise<KernelAccountInstance> {
45
+ const {
46
+ chain,
47
+ owner,
48
+ bundlerManager,
49
+ entryPointVersion = '0.7',
50
+ kernelVersion = '0.3.3'
51
+ } = config;
52
+
53
+ // Create public client for standard RPC calls
54
+ // (Bundler clients don't support standard eth_* methods)
55
+ const publicClient = createPublicClient({
56
+ chain,
57
+ transport: http()
58
+ });
59
+
60
+ // Get EntryPoint address
61
+ const entryPointAddress = ENTRYPOINT_MAP[entryPointVersion];
62
+
63
+ if (!entryPointAddress) {
64
+ throw new Error(`Unsupported EntryPoint version: ${entryPointVersion}`);
65
+ }
66
+
67
+ // Create Kernel account with EIP-7702
68
+ // Use public client for account creation (needs eth_call, eth_getCode, etc.)
69
+ const kernelAccount = await createKernelAccount(
70
+ publicClient as any,
71
+ {
72
+ entryPoint: {
73
+ address: entryPointAddress,
74
+ version: entryPointVersion
75
+ },
76
+ kernelVersion: KERNEL_V3_3,
77
+ eip7702Account: owner as any
78
+ }
79
+ );
80
+
81
+ return {
82
+ account: kernelAccount,
83
+ address: kernelAccount.address,
84
+ owner,
85
+ chain,
86
+ entryPoint: {
87
+ address: entryPointAddress,
88
+ version: entryPointVersion
89
+ }
90
+ };
91
+ }
92
+
93
+ // ============================================
94
+ // EIP-7702 Authorization Helper
95
+ // ============================================
96
+
97
+ export async function createKernelAuthorization(
98
+ config: {
99
+ owner: PrivateKeyAccount;
100
+ chain: Chain;
101
+ bundlerManager: BundlerManager;
102
+ kernelVersion?: KernelVersion;
103
+ }
104
+ ): Promise<SignAuthorizationReturnType | undefined> {
105
+ const { owner, chain, bundlerManager, kernelVersion = '0.3.3' } = config;
106
+
107
+ const bundlerClient = bundlerManager.getClient(chain);
108
+
109
+ // Create public client for eth_getCode (bundler clients don't support it)
110
+ const publicClient = createPublicClient({
111
+ chain,
112
+ transport: http()
113
+ });
114
+
115
+ // Get Kernel implementation address
116
+ const delegateAddress = KernelVersionToAddressesMap[KERNEL_V3_3].accountImplementationAddress;
117
+
118
+ // Check if already delegated
119
+ const code = await publicClient.getCode({ address: owner.address });
120
+ const expectedCode = `0xef0100${delegateAddress.toLowerCase().substring(2)}`;
121
+
122
+ if (code === expectedCode) {
123
+ console.log('Already delegated to Kernel, no authorization needed');
124
+ return undefined;
125
+ }
126
+
127
+ // Create authorization
128
+ console.log('Creating EIP-7702 authorization for Kernel...');
129
+
130
+ // Get nonce for authorization
131
+ const nonce = await publicClient.getTransactionCount({
132
+ address: owner.address,
133
+ blockTag: 'pending'
134
+ });
135
+
136
+ // Sign authorization using the account's signAuthorization method
137
+ const authorization = await owner.signAuthorization({
138
+ contractAddress: delegateAddress,
139
+ chainId: chain.id,
140
+ nonce: nonce
141
+ });
142
+
143
+ return authorization;
144
+ }
145
+
146
+ // ============================================
147
+ // Transaction Helpers
148
+ // ============================================
149
+
150
+ /**
151
+ * Send batch transaction (RECOMMENDED for smart accounts)
152
+ *
153
+ * Sends multiple calls in a single UserOperation, paying gas only once.
154
+ * This is one of the main benefits of smart accounts over EOAs.
155
+ *
156
+ * @example
157
+ * // Send ETH to 3 recipients in one transaction
158
+ * await sendBatchTransaction({
159
+ * kernelAccount: account,
160
+ * bundlerManager,
161
+ * calls: [
162
+ * { to: '0xRecipient1', value: parseEther('0.01') },
163
+ * { to: '0xRecipient2', value: parseEther('0.02') },
164
+ * { to: '0xRecipient3', value: parseEther('0.03') }
165
+ * ]
166
+ * });
167
+ */
168
+ export async function sendBatchTransaction(config: BatchTransactionConfig): Promise<Hex> {
169
+ const {
170
+ kernelAccount,
171
+ bundlerManager,
172
+ authorization,
173
+ calls
174
+ } = config;
175
+
176
+ if (calls.length === 0) {
177
+ throw new Error('Batch transaction must have at least one call');
178
+ }
179
+
180
+ const bundlerClient = bundlerManager.getClient(kernelAccount.chain);
181
+
182
+ // Normalize calls to ensure value and data are set
183
+ const normalizedCalls = calls.map(call => ({
184
+ to: call.to,
185
+ value: call.value ?? 0n,
186
+ data: call.data ?? '0x' as Hex
187
+ }));
188
+
189
+ const userOpHash = await bundlerClient.sendUserOperation({
190
+ account: kernelAccount.account,
191
+ authorization,
192
+ calls: normalizedCalls
193
+ });
194
+
195
+ return userOpHash as Hex;
196
+ }
197
+
198
+ /**
199
+ * Send single transaction (convenience wrapper around sendBatchTransaction)
200
+ *
201
+ * For single operations, you can use this instead of sendBatchTransaction.
202
+ * Under the hood, it creates a batch with one call.
203
+ */
204
+ export async function sendKernelTransaction(config: SingleTransactionConfig): Promise<Hex> {
205
+ const {
206
+ kernelAccount,
207
+ bundlerManager,
208
+ authorization,
209
+ to,
210
+ value = 0n,
211
+ data = '0x'
212
+ } = config;
213
+
214
+ // Use batch transaction with single call
215
+ return sendBatchTransaction({
216
+ kernelAccount,
217
+ bundlerManager,
218
+ authorization,
219
+ calls: [{
220
+ to,
221
+ value,
222
+ data
223
+ }]
224
+ });
225
+ }
226
+
227
+ // ============================================
228
+ // Wait for Receipt Helper
229
+ // ============================================
230
+
231
+ export async function waitForKernelReceipt(config: {
232
+ userOpHash: Hex;
233
+ chain: Chain;
234
+ bundlerManager: BundlerManager;
235
+ }): Promise<any> {
236
+ const { userOpHash, chain, bundlerManager } = config;
237
+
238
+ const bundlerClient = bundlerManager.getClient(chain);
239
+
240
+ const receipt = await bundlerClient.waitForUserOperationReceipt({
241
+ hash: userOpHash
242
+ });
243
+
244
+ return receipt;
245
+ }
246
+
247
+ // ============================================
248
+ // Sponsored Transactions (EIP-7702)
249
+ // ============================================
250
+
251
+ /**
252
+ * Configuration for sponsored batch transaction
253
+ */
254
+ export interface SponsoredBatchTransactionConfig {
255
+ ownerAuthorization: SignAuthorizationReturnType;
256
+ calls: Call[];
257
+ feePayerPrivateKey: Hex;
258
+ bundlerUrl: string;
259
+ paymasterUrl?: string;
260
+ chain: Chain;
261
+ entryPointVersion?: EntryPointVersion;
262
+ }
263
+
264
+ /**
265
+ * Send sponsored batch transaction using EIP-7702
266
+ *
267
+ * Allows a feePayer wallet to pay gas fees for another wallet's transaction.
268
+ * The transaction executes from the owner's address, but gas is paid by the feePayer.
269
+ *
270
+ * @param config - Sponsored transaction configuration
271
+ * @returns UserOperation hash and transaction hash
272
+ *
273
+ * @example
274
+ * // Owner creates authorization
275
+ * const authorization = await createKernelAuthorization({
276
+ * owner: ownerAccount,
277
+ * chain,
278
+ * bundlerManager
279
+ * });
280
+ *
281
+ * // FeePayer sends transaction
282
+ * const result = await sendSponsoredBatchTransaction({
283
+ * ownerAuthorization: authorization,
284
+ * calls: [{ to: recipient, value: parseEther('0.1') }],
285
+ * feePayerPrivateKey: sponsorPrivateKey,
286
+ * bundlerUrl,
287
+ * chain
288
+ * });
289
+ */
290
+ export async function sendSponsoredBatchTransaction(
291
+ config: SponsoredBatchTransactionConfig
292
+ ): Promise<{ userOpHash: Hex; transactionHash?: string }> {
293
+ const {
294
+ ownerAuthorization,
295
+ calls,
296
+ feePayerPrivateKey,
297
+ bundlerUrl,
298
+ paymasterUrl,
299
+ chain,
300
+ entryPointVersion = '0.7'
301
+ } = config;
302
+
303
+ if (calls.length === 0) {
304
+ throw new Error('Sponsored transaction must have at least one call');
305
+ }
306
+
307
+ // Create feePayer account
308
+ const feePayerAccount = privateKeyToAccount(feePayerPrivateKey);
309
+
310
+ // Create bundler service for feePayer
311
+ const feePayerBundlerService = createBundlerService({
312
+ provider: "custom",
313
+ customUrl: bundlerUrl,
314
+ chain
315
+ });
316
+
317
+ // Get bundler client (uses feePayer account internally)
318
+ const bundlerClient = feePayerBundlerService.getClient(chain);
319
+
320
+ // Create kernel account for feePayer (needed for sendUserOperation)
321
+ const publicClient = createPublicClient({
322
+ chain,
323
+ transport: http(chain.rpcUrls.default.http[0])
324
+ });
325
+
326
+ const entryPointAddress = ENTRYPOINT_MAP[entryPointVersion];
327
+ if (!entryPointAddress) {
328
+ throw new Error(`Unsupported EntryPoint version: ${entryPointVersion}`);
329
+ }
330
+
331
+ const feePayerKernelAccount = await createKernelAccount(
332
+ publicClient as any,
333
+ {
334
+ entryPoint: {
335
+ address: entryPointAddress,
336
+ version: entryPointVersion
337
+ },
338
+ kernelVersion: KERNEL_V3_3,
339
+ eip7702Account: feePayerAccount as any
340
+ }
341
+ );
342
+
343
+ // Normalize calls
344
+ const normalizedCalls = calls.map(call => ({
345
+ to: call.to,
346
+ value: call.value ?? 0n,
347
+ data: call.data ?? '0x' as Hex
348
+ }));
349
+
350
+ // Send UserOperation with owner's authorization
351
+ // The transaction executes from owner's address, but feePayer pays gas
352
+ const userOpHash = await bundlerClient.sendUserOperation({
353
+ account: feePayerKernelAccount,
354
+ authorization: ownerAuthorization,
355
+ calls: normalizedCalls
356
+ });
357
+
358
+ // Wait for receipt
359
+ const receipt = await bundlerClient.waitForUserOperationReceipt({
360
+ hash: userOpHash
361
+ });
362
+
363
+ return {
364
+ userOpHash: userOpHash as Hex,
365
+ transactionHash: receipt?.receipt?.transactionHash
366
+ };
367
+ }