@zerodev/permissions 5.6.2 → 5.6.4

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 (52) hide show
  1. package/_cjs/constants.js +2 -1
  2. package/_cjs/constants.js.map +1 -1
  3. package/_cjs/policies/callPolicyUtils.js +27 -0
  4. package/_cjs/policies/callPolicyUtils.js.map +1 -1
  5. package/_cjs/policies/toCallPolicy.js +18 -16
  6. package/_cjs/policies/toCallPolicy.js.map +1 -1
  7. package/_cjs/policies/types.js +1 -0
  8. package/_cjs/policies/types.js.map +1 -1
  9. package/_cjs/serializeMultiChainPermissionAccounts.js +31 -13
  10. package/_cjs/serializeMultiChainPermissionAccounts.js.map +1 -1
  11. package/_cjs/serializePermissionAccount.js +5 -4
  12. package/_cjs/serializePermissionAccount.js.map +1 -1
  13. package/_cjs/toInitConfig.js +3 -3
  14. package/_cjs/toInitConfig.js.map +1 -1
  15. package/_esm/constants.js +5 -0
  16. package/_esm/constants.js.map +1 -1
  17. package/_esm/policies/callPolicyUtils.js +29 -1
  18. package/_esm/policies/callPolicyUtils.js.map +1 -1
  19. package/_esm/policies/toCallPolicy.js +21 -19
  20. package/_esm/policies/toCallPolicy.js.map +1 -1
  21. package/_esm/policies/types.js +1 -0
  22. package/_esm/policies/types.js.map +1 -1
  23. package/_esm/serializeMultiChainPermissionAccounts.js +33 -14
  24. package/_esm/serializeMultiChainPermissionAccounts.js.map +1 -1
  25. package/_esm/serializePermissionAccount.js +6 -4
  26. package/_esm/serializePermissionAccount.js.map +1 -1
  27. package/_esm/toInitConfig.js +3 -3
  28. package/_esm/toInitConfig.js.map +1 -1
  29. package/_types/constants.d.ts +5 -0
  30. package/_types/constants.d.ts.map +1 -1
  31. package/_types/policies/callPolicyUtils.d.ts.map +1 -1
  32. package/_types/policies/toCallPolicy.d.ts +7 -6
  33. package/_types/policies/toCallPolicy.d.ts.map +1 -1
  34. package/_types/policies/types.d.ts +21 -2
  35. package/_types/policies/types.d.ts.map +1 -1
  36. package/_types/serializeMultiChainPermissionAccounts.d.ts +3 -0
  37. package/_types/serializeMultiChainPermissionAccounts.d.ts.map +1 -1
  38. package/_types/serializePermissionAccount.d.ts +1 -1
  39. package/_types/serializePermissionAccount.d.ts.map +1 -1
  40. package/_types/toInitConfig.d.ts +1 -1
  41. package/_types/toInitConfig.d.ts.map +1 -1
  42. package/_types/types.d.ts +2 -2
  43. package/_types/types.d.ts.map +1 -1
  44. package/constants.ts +7 -0
  45. package/package.json +1 -1
  46. package/policies/callPolicyUtils.ts +39 -0
  47. package/policies/toCallPolicy.ts +22 -17
  48. package/policies/types.ts +51 -2
  49. package/serializeMultiChainPermissionAccounts.ts +42 -21
  50. package/serializePermissionAccount.ts +9 -4
  51. package/toInitConfig.ts +5 -3
  52. package/types.ts +2 -2
package/policies/types.ts CHANGED
@@ -7,8 +7,10 @@ import type {
7
7
  AbiParameterToPrimitiveType,
8
8
  AbiStateMutability,
9
9
  Address,
10
+ ContractFunctionName,
10
11
  Hex,
11
- Narrow
12
+ Narrow,
13
+ Prettify
12
14
  } from "viem"
13
15
 
14
16
  export enum CallType {
@@ -24,7 +26,8 @@ export enum ParamCondition {
24
26
  GREATER_THAN_OR_EQUAL = 3,
25
27
  LESS_THAN_OR_EQUAL = 4,
26
28
  NOT_EQUAL = 5,
27
- ONE_OF = 6
29
+ ONE_OF = 6,
30
+ SLICE_EQUAL = 7
28
31
  }
29
32
 
30
33
  export interface ParamRule {
@@ -113,6 +116,12 @@ type ConditionValue<
113
116
  condition: ParamCondition.ONE_OF
114
117
  value: AbiParameterToPrimitiveType<TAbiParameter, TAbiParameterKind>[]
115
118
  }
119
+ | {
120
+ condition: ParamCondition.SLICE_EQUAL
121
+ value: AbiParameterToPrimitiveType<TAbiParameter, TAbiParameterKind>
122
+ start: number
123
+ length: number
124
+ }
116
125
  | {
117
126
  condition: Exclude<ParamCondition, ParamCondition.ONE_OF>
118
127
  value: AbiParameterToPrimitiveType<TAbiParameter, TAbiParameterKind>
@@ -149,3 +158,43 @@ export type GeneratePermissionFromArgsParameters<
149
158
  : _FunctionName extends string
150
159
  ? { abi: [Narrow<TAbi[number]>] } & GetFunctionArgs<TAbi, _FunctionName>
151
160
  : never)
161
+
162
+ // infer permission parameters from `unknown` - similar to GetMulticallContractParameters
163
+ export type GetPermissionParameters<permission> = permission extends {
164
+ abi: infer abi extends Abi
165
+ } // 1. Check if `abi` is const-asserted or defined inline
166
+ ? // 1a. Check if `functionName` is valid for `abi`
167
+ permission extends {
168
+ functionName: infer functionName extends ContractFunctionName<abi>
169
+ }
170
+ ? // Use PermissionWithABI which supports CombinedArgs
171
+ PermissionWithABI<abi, functionName>
172
+ : // 1b. `functionName` is invalid, check if `abi` is declared as `Abi`
173
+ Abi extends abi
174
+ ? PermissionWithABI<abi, string> // `abi` declared as `Abi`, unable to infer types further
175
+ : // `abi` is const-asserted or defined inline, infer types for `functionName` and `args`
176
+ PermissionWithABI<abi, string>
177
+ : permission extends { target: Address } // manual permission
178
+ ? PermissionManual
179
+ : never // invalid permission
180
+
181
+ // Process permissions array - similar to MulticallContracts
182
+ export type InferPermissions<
183
+ permissions extends readonly unknown[],
184
+ result extends readonly unknown[] = []
185
+ > = permissions extends readonly [] // no permissions, return empty
186
+ ? readonly []
187
+ : permissions extends readonly [infer permission] // one permission left before returning `result`
188
+ ? readonly [...result, Prettify<GetPermissionParameters<permission>>]
189
+ : permissions extends readonly [infer permission, ...infer rest] // grab first permission and recurse through `rest`
190
+ ? InferPermissions<
191
+ [...rest],
192
+ [...result, Prettify<GetPermissionParameters<permission>>]
193
+ >
194
+ : readonly unknown[] extends permissions
195
+ ? permissions
196
+ : // If `permissions` is *some* array but we couldn't assign `unknown[]` to it, then it must hold some known/homogenous type!
197
+ permissions extends readonly (infer permission)[]
198
+ ? readonly Prettify<GetPermissionParameters<permission>>[]
199
+ : // Fallback
200
+ readonly Permission<Abi, string>[]
@@ -19,6 +19,8 @@ import {
19
19
  export type MultiChainPermissionAccountsParams = {
20
20
  account: SmartAccount<KernelSmartAccountImplementation>
21
21
  privateKey?: Hex
22
+ permissionPlugin?: PermissionPlugin
23
+ isExternalPermissionPlugin?: boolean
22
24
  }
23
25
 
24
26
  export const serializeMultiChainPermissionAccounts = async (
@@ -26,13 +28,21 @@ export const serializeMultiChainPermissionAccounts = async (
26
28
  ): Promise<string[]> => {
27
29
  if (params.length === 0) return []
28
30
 
31
+ let isPreInstalled = false
29
32
  const permissionParamsPerAccounts = params.map((param) => {
30
- if (!isPermissionValidatorPlugin(param.account.kernelPluginManager)) {
33
+ if (
34
+ isPermissionValidatorPlugin(param.account.kernelPluginManager) &&
35
+ !param.isExternalPermissionPlugin
36
+ ) {
37
+ return (
38
+ param.account.kernelPluginManager as PermissionPlugin
39
+ ).getPluginSerializationParams()
40
+ } else if (param.permissionPlugin) {
41
+ isPreInstalled = !param.isExternalPermissionPlugin
42
+ return param.permissionPlugin.getPluginSerializationParams()
43
+ } else {
31
44
  throw new Error("Account plugin is not a permission validator")
32
45
  }
33
- return (
34
- param.account.kernelPluginManager as PermissionPlugin
35
- ).getPluginSerializationParams()
36
46
  })
37
47
 
38
48
  const actions = params.map((param) =>
@@ -43,23 +53,30 @@ export const serializeMultiChainPermissionAccounts = async (
43
53
  param.account.kernelPluginManager.getValidityData()
44
54
  )
45
55
 
46
- const pluginEnableTypedDatas = await Promise.all(
47
- params.map(async (param) => {
48
- return param.account.kernelPluginManager.getPluginsEnableTypedData(
49
- param.account.address
50
- )
51
- })
52
- )
53
-
54
- // build merkle tree for enable signatures
55
- const leaves = pluginEnableTypedDatas.map((typedData) => {
56
- return hashTypedData(typedData)
57
- })
56
+ let leaves: Hex[] = []
57
+ let merkleTree: MerkleTree = new MerkleTree(leaves)
58
+
59
+ if (!isPreInstalled) {
60
+ const pluginEnableTypedDatas = await Promise.all(
61
+ params.map(async (param) => {
62
+ return param.account.kernelPluginManager.getPluginsEnableTypedData(
63
+ param.account.address,
64
+ param.isExternalPermissionPlugin
65
+ ? param.permissionPlugin
66
+ : undefined // override permission plugin if externalPlugin
67
+ )
68
+ })
69
+ )
58
70
 
59
- const merkleTree = new MerkleTree(leaves, keccak256, {
60
- sortPairs: true
61
- })
71
+ // build merkle tree for enable signatures
72
+ leaves = pluginEnableTypedDatas.map((typedData) => {
73
+ return hashTypedData(typedData)
74
+ })
62
75
 
76
+ merkleTree = new MerkleTree(leaves, keccak256, {
77
+ sortPairs: true
78
+ })
79
+ }
63
80
  const merkleRoot = merkleTree.getHexRoot() as Hex
64
81
 
65
82
  const toEthSignedMessageHash = hashMessage({ raw: merkleRoot })
@@ -67,7 +84,8 @@ export const serializeMultiChainPermissionAccounts = async (
67
84
  let signature: Hex = "0x"
68
85
  if (
69
86
  params[0].account.kernelPluginManager.sudoValidator?.source ===
70
- "MultiChainECDSAValidator"
87
+ "MultiChainECDSAValidator" &&
88
+ !isPreInstalled
71
89
  ) {
72
90
  signature =
73
91
  await params[0].account.kernelPluginManager.sudoValidator?.signMessage(
@@ -80,7 +98,8 @@ export const serializeMultiChainPermissionAccounts = async (
80
98
  }
81
99
  if (
82
100
  params[0].account.kernelPluginManager.sudoValidator?.source ===
83
- "MultiChainWebAuthnValidator"
101
+ "MultiChainWebAuthnValidator" &&
102
+ !isPreInstalled
84
103
  ) {
85
104
  const encodedSignature =
86
105
  await params[0].account.kernelPluginManager.sudoValidator?.signMessage(
@@ -96,6 +115,8 @@ export const serializeMultiChainPermissionAccounts = async (
96
115
  // get enable signatures for multi-chain validator
97
116
  const enableSignatures = await Promise.all(
98
117
  params.map(async (param, index) => {
118
+ if (isPreInstalled) return undefined
119
+
99
120
  if (!param.account.kernelPluginManager.sudoValidator) {
100
121
  throw new Error(
101
122
  "No sudo validator found, check if sudo validator is multi-chain validator"
@@ -13,7 +13,8 @@ export const serializePermissionAccount = async (
13
13
  privateKey?: Hex,
14
14
  enableSignature?: Hex,
15
15
  eip7702Auth?: SignAuthorizationReturnType,
16
- permissionPlugin?: PermissionPlugin
16
+ permissionPlugin?: PermissionPlugin,
17
+ isExternalPermissionPlugin?: boolean
17
18
  ): Promise<string> => {
18
19
  let permissionParams: PermissionData
19
20
  let isPreInstalled = false
@@ -21,13 +22,16 @@ export const serializePermissionAccount = async (
21
22
  const validityData = account.kernelPluginManager.getValidityData()
22
23
 
23
24
  // Check if permission plugin is in kernelPluginManager
24
- if (isPermissionValidatorPlugin(account.kernelPluginManager)) {
25
+ if (
26
+ isPermissionValidatorPlugin(account.kernelPluginManager) &&
27
+ !isExternalPermissionPlugin
28
+ ) {
25
29
  permissionParams =
26
30
  account.kernelPluginManager.getPluginSerializationParams()
27
31
  } else if (permissionPlugin) {
28
32
  // Permission plugin provided externally (initConfig case)
29
33
  permissionParams = permissionPlugin.getPluginSerializationParams()
30
- isPreInstalled = true
34
+ isPreInstalled = !isExternalPermissionPlugin
31
35
  } else {
32
36
  throw new Error("No permission validator found in account or provided")
33
37
  }
@@ -36,7 +40,8 @@ export const serializePermissionAccount = async (
36
40
  ? undefined
37
41
  : (enableSignature ??
38
42
  (await account.kernelPluginManager.getPluginEnableSignature(
39
- account.address
43
+ account.address,
44
+ isExternalPermissionPlugin ? permissionPlugin : undefined // override permission plugin if externalPlugin
40
45
  )))
41
46
  const _eip7702Auth = account.authorization
42
47
  ? (eip7702Auth ?? (await account?.eip7702Authorization?.()))
package/toInitConfig.ts CHANGED
@@ -15,7 +15,9 @@ import {
15
15
  import type { PermissionPlugin } from "./types.js"
16
16
 
17
17
  export async function toInitConfig(
18
- permissionPlugin: PermissionPlugin
18
+ permissionPlugin: PermissionPlugin,
19
+ hook: Hex = zeroAddress,
20
+ hookData: Hex = "0x"
19
21
  ): Promise<Hex[]> {
20
22
  const permissionInstallFunctionData = encodeFunctionData({
21
23
  abi: KernelV3_3AccountAbi,
@@ -30,9 +32,9 @@ export async function toInitConfig(
30
32
  { size: 21, dir: "right" }
31
33
  )
32
34
  ],
33
- [{ nonce: 1, hook: zeroAddress }],
35
+ [{ nonce: 1, hook }],
34
36
  [await permissionPlugin.getEnableData()],
35
- ["0x"]
37
+ [hookData]
36
38
  ]
37
39
  })
38
40
  const grantAccessFunctionData = encodeFunctionData({
package/types.ts CHANGED
@@ -5,7 +5,7 @@ import type {
5
5
  GetKernelVersion,
6
6
  PluginValidityData
7
7
  } from "@zerodev/sdk/types"
8
- import type { Abi, Address, Hex, LocalAccount } from "viem"
8
+ import type { Address, Hex, LocalAccount } from "viem"
9
9
  import type { EntryPointVersion } from "viem/account-abstraction"
10
10
  import type { SignAuthorizationReturnType } from "viem/accounts"
11
11
  import type { PolicyFlags } from "./constants.js"
@@ -42,7 +42,7 @@ export type Policy = {
42
42
  getPolicyInfoInBytes: () => Hex
43
43
  // return params directly to serialize/deserialize Policy
44
44
  policyParams:
45
- | (CallPolicyParams<Abi | readonly unknown[], string> & {
45
+ | (CallPolicyParams & {
46
46
  type: "call"
47
47
  })
48
48
  | (GasPolicyParams & { type: "gas" })