@zerodev/sdk 5.4.9-alpha.0 → 5.4.10

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 (59) hide show
  1. package/_cjs/accounts/kernel/abi/kernel_v_3_0_0/KernelModuleAbi.js +38 -1
  2. package/_cjs/accounts/kernel/abi/kernel_v_3_0_0/KernelModuleAbi.js.map +1 -1
  3. package/_cjs/accounts/kernel/createKernelAccount.js +25 -38
  4. package/_cjs/accounts/kernel/createKernelAccount.js.map +1 -1
  5. package/_cjs/accounts/kernel/utils/plugins/ep0_7/getPluginInstallCallData.js +18 -0
  6. package/_cjs/accounts/kernel/utils/plugins/ep0_7/getPluginInstallCallData.js.map +1 -0
  7. package/_cjs/accounts/utils/toKernelPluginManager.js +1 -0
  8. package/_cjs/accounts/utils/toKernelPluginManager.js.map +1 -1
  9. package/_cjs/actions/public/index.js +3 -1
  10. package/_cjs/actions/public/index.js.map +1 -1
  11. package/_cjs/actions/public/isPluginInstalled.js +23 -0
  12. package/_cjs/actions/public/isPluginInstalled.js.map +1 -0
  13. package/_cjs/constants.js +9 -2
  14. package/_cjs/constants.js.map +1 -1
  15. package/_cjs/types/index.js.map +1 -1
  16. package/_cjs/types/kernel.js.map +1 -1
  17. package/_esm/accounts/kernel/abi/kernel_v_3_0_0/KernelModuleAbi.js +37 -0
  18. package/_esm/accounts/kernel/abi/kernel_v_3_0_0/KernelModuleAbi.js.map +1 -1
  19. package/_esm/accounts/kernel/createKernelAccount.js +35 -44
  20. package/_esm/accounts/kernel/createKernelAccount.js.map +1 -1
  21. package/_esm/accounts/kernel/utils/plugins/ep0_7/getPluginInstallCallData.js +14 -0
  22. package/_esm/accounts/kernel/utils/plugins/ep0_7/getPluginInstallCallData.js.map +1 -0
  23. package/_esm/accounts/utils/toKernelPluginManager.js +1 -0
  24. package/_esm/accounts/utils/toKernelPluginManager.js.map +1 -1
  25. package/_esm/actions/public/index.js +1 -0
  26. package/_esm/actions/public/index.js.map +1 -1
  27. package/_esm/actions/public/isPluginInstalled.js +44 -0
  28. package/_esm/actions/public/isPluginInstalled.js.map +1 -0
  29. package/_esm/constants.js +8 -1
  30. package/_esm/constants.js.map +1 -1
  31. package/_esm/types/index.js.map +1 -1
  32. package/_esm/types/kernel.js.map +1 -1
  33. package/_types/accounts/kernel/abi/kernel_v_3_0_0/KernelModuleAbi.d.ts +41 -0
  34. package/_types/accounts/kernel/abi/kernel_v_3_0_0/KernelModuleAbi.d.ts.map +1 -1
  35. package/_types/accounts/kernel/createKernelAccount.d.ts +3 -5
  36. package/_types/accounts/kernel/createKernelAccount.d.ts.map +1 -1
  37. package/_types/accounts/kernel/utils/plugins/ep0_7/getPluginInstallCallData.d.ts +5 -0
  38. package/_types/accounts/kernel/utils/plugins/ep0_7/getPluginInstallCallData.d.ts.map +1 -0
  39. package/_types/accounts/utils/toKernelPluginManager.d.ts.map +1 -1
  40. package/_types/actions/public/index.d.ts +1 -0
  41. package/_types/actions/public/index.d.ts.map +1 -1
  42. package/_types/actions/public/isPluginInstalled.d.ts +37 -0
  43. package/_types/actions/public/isPluginInstalled.d.ts.map +1 -0
  44. package/_types/constants.d.ts +8 -1
  45. package/_types/constants.d.ts.map +1 -1
  46. package/_types/types/index.d.ts +1 -1
  47. package/_types/types/index.d.ts.map +1 -1
  48. package/_types/types/kernel.d.ts +8 -1
  49. package/_types/types/kernel.d.ts.map +1 -1
  50. package/accounts/kernel/abi/kernel_v_3_0_0/KernelModuleAbi.ts +39 -0
  51. package/accounts/kernel/createKernelAccount.ts +62 -58
  52. package/accounts/kernel/utils/plugins/ep0_7/getPluginInstallCallData.ts +19 -0
  53. package/accounts/utils/toKernelPluginManager.ts +1 -0
  54. package/actions/public/index.ts +1 -0
  55. package/actions/public/isPluginInstalled.ts +62 -0
  56. package/constants.ts +9 -3
  57. package/package.json +1 -1
  58. package/types/index.ts +2 -1
  59. package/types/kernel.ts +10 -1
@@ -6,15 +6,12 @@ import {
6
6
  type Hex,
7
7
  type SignableMessage,
8
8
  type TypedDataDefinition,
9
- concat,
10
9
  concatHex,
11
10
  createNonceManager,
12
- createWalletClient,
13
11
  encodeFunctionData,
14
12
  getTypesForEIP712Domain,
15
13
  hashMessage,
16
14
  hashTypedData,
17
- http,
18
15
  toHex,
19
16
  validateTypedData,
20
17
  zeroAddress
@@ -29,11 +26,12 @@ import {
29
26
  entryPoint07Address,
30
27
  toSmartAccount
31
28
  } from "viem/account-abstraction"
32
- import { getChainId, getCode, writeContract } from "viem/actions"
29
+ import { getChainId } from "viem/actions"
33
30
  import { getAction } from "viem/utils"
34
31
  import {
35
32
  getAccountNonce,
36
- getSenderAddress
33
+ getSenderAddress,
34
+ isPluginInstalled
37
35
  } from "../../actions/public/index.js"
38
36
  import {
39
37
  KernelVersionToAddressesMap,
@@ -45,7 +43,8 @@ import type {
45
43
  GetEntryPointAbi,
46
44
  GetKernelVersion,
47
45
  KernelPluginManager,
48
- KernelPluginManagerParams
46
+ KernelPluginManagerParams,
47
+ PluginMigrationData
49
48
  } from "../../types/kernel.js"
50
49
  import { KERNEL_FEATURES, hasKernelFeature } from "../../utils.js"
51
50
  import { validateKernelVersionWithEntryPoint } from "../../utils.js"
@@ -54,10 +53,7 @@ import {
54
53
  toKernelPluginManager
55
54
  } from "../utils/toKernelPluginManager.js"
56
55
  import { KernelInitAbi } from "./abi/KernelAccountAbi.js"
57
- import {
58
- KernelV3AccountAbi,
59
- KernelV3InitAbi
60
- } from "./abi/kernel_v_3_0_0/KernelAccountAbi.js"
56
+ import { KernelV3InitAbi } from "./abi/kernel_v_3_0_0/KernelAccountAbi.js"
61
57
  import { KernelV3FactoryAbi } from "./abi/kernel_v_3_0_0/KernelFactoryAbi.js"
62
58
  import { KernelFactoryStakerAbi } from "./abi/kernel_v_3_0_0/KernelFactoryStakerAbi.js"
63
59
  import { KernelV3_1AccountAbi } from "./abi/kernel_v_3_1/KernelAccountAbi.js"
@@ -67,11 +63,7 @@ import { encodeCallData as encodeCallDataEpV07 } from "./utils/account/ep0_7/enc
67
63
  import { encodeDeployCallData as encodeDeployCallDataV07 } from "./utils/account/ep0_7/encodeDeployCallData.js"
68
64
  import { accountMetadata } from "./utils/common/accountMetadata.js"
69
65
  import { eip712WrapHash } from "./utils/common/eip712WrapHash.js"
70
- import {
71
- privateKeyToAccount,
72
- type SignAuthorizationReturnType
73
- } from "viem/accounts"
74
- import { odysseyTestnet } from "viem/chains"
66
+ import { getPluginInstallCallData } from "./utils/plugins/ep0_7/getPluginInstallCallData.js"
75
67
 
76
68
  type SignMessageParameters = {
77
69
  message: SignableMessage
@@ -102,7 +94,6 @@ export type KernelSmartAccountImplementation<
102
94
  bytecode
103
95
  }: EncodeDeployDataParameters) => Promise<Hex>
104
96
  signMessage: (parameters: SignMessageParameters) => Promise<Hex>
105
- eip7702Auth?: SignAuthorizationReturnType
106
97
  }
107
98
  >
108
99
 
@@ -129,7 +120,7 @@ export type CreateKernelAccountParameters<
129
120
  kernelVersion: GetKernelVersion<entryPointVersion>
130
121
  initConfig?: KernelVerion extends "0.3.1" ? Hex[] : never
131
122
  useMetaFactory?: boolean
132
- eip7702Auth?: SignAuthorizationReturnType
123
+ pluginMigrations?: PluginMigrationData[]
133
124
  }
134
125
 
135
126
  /**
@@ -342,6 +333,11 @@ const getDefaultAddresses = <entryPointVersion extends EntryPointVersion>(
342
333
  }
343
334
  }
344
335
 
336
+ type PluginInstallationCache = {
337
+ pendingPlugins: PluginMigrationData[]
338
+ allInstalled: boolean
339
+ }
340
+
345
341
  /**
346
342
  * Build a kernel smart account from a private key, that use the ECDSA signer behind the scene
347
343
  * @param client
@@ -369,7 +365,7 @@ export async function createKernelAccount<
369
365
  kernelVersion,
370
366
  initConfig,
371
367
  useMetaFactory = true,
372
- eip7702Auth
368
+ pluginMigrations
373
369
  }: CreateKernelAccountParameters<entryPointVersion, KernelVersion>
374
370
  ): Promise<CreateKernelAccountReturnType<entryPointVersion>> {
375
371
  const { accountImplementationAddress, factoryAddress, metaFactoryAddress } =
@@ -463,50 +459,39 @@ export async function createKernelAccount<
463
459
  version: entryPoint?.version ?? "0.7"
464
460
  } as const
465
461
 
466
- if (eip7702Auth && client.chain && client.chain.id === odysseyTestnet.id) {
467
- let code = await getCode(client, { address: accountAddress })
468
- const isEip7702Authorized =
469
- code?.length && code.length > 0 && code.startsWith("0xef")
470
- console.log("Code before:", code)
471
- console.log("Is Eip7702 Authorized:", isEip7702Authorized)
472
- if (!isEip7702Authorized) {
473
- const sponsorWalletClient = createWalletClient({
474
- account: privateKeyToAccount(
475
- // NOTE: Don't worry about this private key, it's just for testing
476
- "0x688b84097239bc2bca41079d02fae599964a5844bc9e64f524206ad53a927bb9"
477
- ),
478
- chain: client.chain,
479
- transport: http()
480
- })
481
- console.log("Authorizing eip7702 account...")
482
- const txHash = await writeContract(sponsorWalletClient, {
483
- address: accountAddress,
484
- abi: KernelV3AccountAbi,
485
- functionName: "initialize",
486
- args: [
487
- concat([
488
- "0x01",
489
- "0x845ADb2C711129d4f3966735eD98a9F09fC4cE57"
490
- ]),
491
- zeroAddress,
492
- accountAddress,
493
- "0x"
494
- ],
495
- authorizationList: [eip7702Auth]
496
- })
497
- console.log(
498
- `Authorized eip7702 account: https://explorer-odyssey.t.conduit.xyz/tx/${txHash}`
499
- )
500
- code = await getCode(client, { address: accountAddress })
501
- while (code?.length === undefined || code.length === 0) {
502
- code = await getCode(client, { address: accountAddress })
503
- }
504
- console.log("Code after:", code)
462
+ // Cache for plugin installation status
463
+ const pluginCache: PluginInstallationCache = {
464
+ pendingPlugins: pluginMigrations || [],
465
+ allInstalled: false
466
+ }
467
+
468
+ const checkPluginInstallationStatus = async () => {
469
+ // Skip if no plugins or all are installed
470
+ if (!pluginCache.pendingPlugins.length || pluginCache.allInstalled) {
471
+ pluginCache.allInstalled = true
472
+ return
505
473
  }
474
+
475
+ // Check all pending plugins in parallel
476
+ const installationResults = await Promise.all(
477
+ pluginCache.pendingPlugins.map((plugin) =>
478
+ isPluginInstalled(client, {
479
+ address: accountAddress,
480
+ plugin
481
+ })
482
+ )
483
+ )
484
+
485
+ // Filter out installed plugins
486
+ pluginCache.pendingPlugins = pluginCache.pendingPlugins.filter(
487
+ (_, index) => !installationResults[index]
488
+ )
489
+ pluginCache.allInstalled = pluginCache.pendingPlugins.length === 0
506
490
  }
507
491
 
492
+ await checkPluginInstallationStatus()
493
+
508
494
  return toSmartAccount<KernelSmartAccountImplementation<entryPointVersion>>({
509
- eip7702Auth,
510
495
  kernelVersion,
511
496
  kernelPluginManager,
512
497
  factoryAddress: (await getFactoryArgs()).factory,
@@ -544,6 +529,25 @@ export async function createKernelAccount<
544
529
  return encodeDeployCallDataV07(_tx)
545
530
  },
546
531
  async encodeCalls(calls, callType) {
532
+ // Check plugin status only if we have pending plugins
533
+ await checkPluginInstallationStatus()
534
+
535
+ // Add plugin installation calls if needed
536
+ if (
537
+ pluginCache.pendingPlugins.length > 0 &&
538
+ entryPoint.version === "0.7" &&
539
+ kernelPluginManager.activeValidatorMode === "sudo"
540
+ ) {
541
+ const pluginInstallCalls = pluginCache.pendingPlugins.map(
542
+ (plugin) => getPluginInstallCallData(accountAddress, plugin)
543
+ )
544
+ return encodeCallDataEpV07(
545
+ [...calls, ...pluginInstallCalls],
546
+ callType,
547
+ plugins.hook ? true : undefined
548
+ )
549
+ }
550
+
547
551
  if (
548
552
  calls.length === 1 &&
549
553
  (!callType || callType === "call") &&
@@ -0,0 +1,19 @@
1
+ import { type Address, encodeFunctionData } from "viem"
2
+ import type { PluginMigrationData } from "../../../../../types/kernel.js"
3
+ import { KernelModuleInstallAbi } from "../../../abi/kernel_v_3_0_0/KernelModuleAbi.js"
4
+ import type { CallArgs } from "../../types.js"
5
+
6
+ export const getPluginInstallCallData = (
7
+ accountAddress: Address,
8
+ plugin: PluginMigrationData
9
+ ): CallArgs => {
10
+ const data = encodeFunctionData({
11
+ abi: KernelModuleInstallAbi,
12
+ functionName: "installModule",
13
+ args: [plugin.type, plugin.address, plugin.data]
14
+ })
15
+ return {
16
+ to: accountAddress,
17
+ data
18
+ }
19
+ }
@@ -264,6 +264,7 @@ export async function toKernelPluginManager<
264
264
  return {
265
265
  sudoValidator: sudo,
266
266
  regularValidator: regular,
267
+ activeValidatorMode: sudo && !regular ? "sudo" : "regular",
267
268
  ...activeValidator,
268
269
  hook,
269
270
  getIdentifier,
@@ -9,3 +9,4 @@ export {
9
9
  } from "./getSenderAddress.js"
10
10
  export { isSmartAccountDeployed } from "./isSmartAccountDeployed.js"
11
11
  export { getKernelImplementationAddress } from "./getKernelImplementationAddress.js"
12
+ export { isPluginInstalled } from "./isPluginInstalled.js"
@@ -0,0 +1,62 @@
1
+ import type { Address, Client, Hex } from "viem"
2
+ import { readContract } from "viem/actions"
3
+ import { getAction } from "viem/utils"
4
+ import { KernelModuleIsModuleInstalledAbi } from "../../accounts/kernel/abi/kernel_v_3_0_0/KernelModuleAbi.js"
5
+ import type { PLUGIN_TYPE } from "../../constants.js"
6
+
7
+ export type IsPluginInstalledParams = {
8
+ address: Address
9
+ plugin: {
10
+ type: (typeof PLUGIN_TYPE)[keyof typeof PLUGIN_TYPE]
11
+ address: Address
12
+ data?: Hex
13
+ }
14
+ }
15
+
16
+ /**
17
+ * Returns whether a plugin is installed on the account.
18
+ *
19
+ * @param client - Client to use
20
+ * @param args - {@link IsPluginInstalledParams} address and plugin details
21
+ * @returns boolean indicating if plugin is installed
22
+ *
23
+ * @example
24
+ * import { createPublicClient } from "viem"
25
+ * import { isPluginInstalled } from "@zerodev/sdk"
26
+ *
27
+ * const client = createPublicClient({
28
+ * chain: mainnet,
29
+ * transport: http()
30
+ * })
31
+ *
32
+ * const isInstalled = await isPluginInstalled(client, {
33
+ * address: accountAddress,
34
+ * plugin: {
35
+ * type: PLUGIN_TYPE.VALIDATOR,
36
+ * address: validatorAddress,
37
+ * data: "0x"
38
+ * }
39
+ * })
40
+ */
41
+ export const isPluginInstalled = async (
42
+ client: Client,
43
+ args: IsPluginInstalledParams
44
+ ): Promise<boolean> => {
45
+ const { address, plugin } = args
46
+ const { type, address: pluginAddress, data = "0x" } = plugin
47
+
48
+ try {
49
+ return await getAction(
50
+ client,
51
+ readContract,
52
+ "readContract"
53
+ )({
54
+ address,
55
+ abi: KernelModuleIsModuleInstalledAbi,
56
+ functionName: "isModuleInstalled",
57
+ args: [BigInt(type), pluginAddress, data]
58
+ })
59
+ } catch (error) {
60
+ return false
61
+ }
62
+ }
package/constants.ts CHANGED
@@ -120,6 +120,15 @@ export enum EXEC_TYPE {
120
120
  TRY_EXEC = "0x01"
121
121
  }
122
122
 
123
+ export const PLUGIN_TYPE = {
124
+ VALIDATOR: 1,
125
+ EXECUTOR: 2,
126
+ FALLBACK: 3,
127
+ HOOK: 4,
128
+ POLICY: 5,
129
+ SIGNER: 6
130
+ }
131
+
123
132
  // Safe's library for create and create2: https://github.com/safe-global/safe-contracts/blob/0acdd35a203299585438f53885df630f9d486a86/contracts/libraries/CreateCall.sol
124
133
  // Address was found here: https://github.com/safe-global/safe-deployments/blob/926ec6bbe2ebcac3aa2c2c6c0aff74aa590cbc6a/src/assets/v1.4.1/create_call.json
125
134
  export const safeCreateCallAddress =
@@ -147,6 +156,3 @@ export const getEntryPoint = <TEntryPointVersion extends EntryPointVersion>(
147
156
  version: entryPointVersion
148
157
  }
149
158
  }
150
-
151
- export const KERNEL_7702_DELEGATION_ADDRESS =
152
- "0x94F097E1ebEB4ecA3AAE54cabb08905B239A7D27"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerodev/sdk",
3
- "version": "5.4.9-alpha.0",
3
+ "version": "5.4.10",
4
4
  "author": "ZeroDev",
5
5
  "main": "./_cjs/index.js",
6
6
  "module": "./_esm/index.js",
package/types/index.ts CHANGED
@@ -14,7 +14,8 @@ export type {
14
14
  KERNEL_VERSION_TYPE,
15
15
  GetKernelVersion,
16
16
  GetEntryPointAbi,
17
- EntryPointType
17
+ EntryPointType,
18
+ PluginMigrationData
18
19
  } from "./kernel.js"
19
20
 
20
21
  export { ValidatorMode } from "./kernel.js"
package/types/kernel.ts CHANGED
@@ -5,7 +5,7 @@ import type {
5
5
  entryPoint06Abi,
6
6
  entryPoint07Abi
7
7
  } from "viem/account-abstraction"
8
- import type { VALIDATOR_TYPE } from "../constants.js"
8
+ import type { PLUGIN_TYPE, VALIDATOR_TYPE } from "../constants.js"
9
9
  export type ZeroDevPaymasterRpcSchema<
10
10
  entryPointVersion extends EntryPointVersion
11
11
  > = [
@@ -154,10 +154,13 @@ export type ValidatorInitData = {
154
154
  initConfig?: Hex[]
155
155
  }
156
156
 
157
+ export type ActiveValidatorMode = "sudo" | "regular"
158
+
157
159
  export type KernelPluginManager<entryPointVersion extends EntryPointVersion> =
158
160
  KernelValidator & {
159
161
  sudoValidator?: KernelValidator
160
162
  regularValidator?: KernelValidator
163
+ activeValidatorMode: ActiveValidatorMode
161
164
  hook?: KernelValidatorHook
162
165
  getPluginEnableSignature(accountAddress: Address): Promise<Hex>
163
166
  getValidatorInitData(): Promise<ValidatorInitData>
@@ -221,6 +224,12 @@ export enum ValidatorMode {
221
224
  enable = "0x00000002"
222
225
  }
223
226
 
227
+ export type PluginMigrationData = {
228
+ type: (typeof PLUGIN_TYPE)[keyof typeof PLUGIN_TYPE]
229
+ address: Address
230
+ data: Hex
231
+ }
232
+
224
233
  export type CallType = "call" | "delegatecall"
225
234
 
226
235
  export type KernelEncodeCallDataArgs = {