@zerodev/permissions 5.2.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 (171) hide show
  1. package/_cjs/constants.js +18 -0
  2. package/_cjs/constants.js.map +1 -0
  3. package/_cjs/deserializePermissionAccount.js +99 -0
  4. package/_cjs/deserializePermissionAccount.js.map +1 -0
  5. package/_cjs/index.js +12 -0
  6. package/_cjs/index.js.map +1 -0
  7. package/_cjs/package.json +1 -0
  8. package/_cjs/policies/callPolicyUtils.js +87 -0
  9. package/_cjs/policies/callPolicyUtils.js.map +1 -0
  10. package/_cjs/policies/index.js +21 -0
  11. package/_cjs/policies/index.js.map +1 -0
  12. package/_cjs/policies/toCallPolicy.js +42 -0
  13. package/_cjs/policies/toCallPolicy.js.map +1 -0
  14. package/_cjs/policies/toGasPolicy.js +30 -0
  15. package/_cjs/policies/toGasPolicy.js.map +1 -0
  16. package/_cjs/policies/toRateLimitPolicy.js +30 -0
  17. package/_cjs/policies/toRateLimitPolicy.js.map +1 -0
  18. package/_cjs/policies/toSignatureCallerPolicy.js +24 -0
  19. package/_cjs/policies/toSignatureCallerPolicy.js.map +1 -0
  20. package/_cjs/policies/toSudoPolicy.js +22 -0
  21. package/_cjs/policies/toSudoPolicy.js.map +1 -0
  22. package/_cjs/policies/toTimestampPolicy.js +27 -0
  23. package/_cjs/policies/toTimestampPolicy.js.map +1 -0
  24. package/_cjs/policies/types.js +19 -0
  25. package/_cjs/policies/types.js.map +1 -0
  26. package/_cjs/policies/utils/toPolicyId.js +11 -0
  27. package/_cjs/policies/utils/toPolicyId.js.map +1 -0
  28. package/_cjs/serializePermissionAccount.js +27 -0
  29. package/_cjs/serializePermissionAccount.js.map +1 -0
  30. package/_cjs/signers/index.js +14 -0
  31. package/_cjs/signers/index.js.map +1 -0
  32. package/_cjs/signers/toECDSASigner.js +39 -0
  33. package/_cjs/signers/toECDSASigner.js.map +1 -0
  34. package/_cjs/signers/toEmptyECDSASigner.js +30 -0
  35. package/_cjs/signers/toEmptyECDSASigner.js.map +1 -0
  36. package/_cjs/signers/toWebAuthnPubKey.js +98 -0
  37. package/_cjs/signers/toWebAuthnPubKey.js.map +1 -0
  38. package/_cjs/signers/toWebAuthnSigner.js +154 -0
  39. package/_cjs/signers/toWebAuthnSigner.js.map +1 -0
  40. package/_cjs/signers/utils/toSignerId.js +9 -0
  41. package/_cjs/signers/utils/toSignerId.js.map +1 -0
  42. package/_cjs/signers/webAuthnUtils.js +45 -0
  43. package/_cjs/signers/webAuthnUtils.js.map +1 -0
  44. package/_cjs/toPermissionValidator.js +98 -0
  45. package/_cjs/toPermissionValidator.js.map +1 -0
  46. package/_cjs/types.js +3 -0
  47. package/_cjs/types.js.map +1 -0
  48. package/_cjs/utils.js +37 -0
  49. package/_cjs/utils.js.map +1 -0
  50. package/_esm/constants.js +15 -0
  51. package/_esm/constants.js.map +1 -0
  52. package/_esm/deserializePermissionAccount.js +94 -0
  53. package/_esm/deserializePermissionAccount.js.map +1 -0
  54. package/_esm/index.js +5 -0
  55. package/_esm/index.js.map +1 -0
  56. package/_esm/package.json +1 -0
  57. package/_esm/policies/callPolicyUtils.js +82 -0
  58. package/_esm/policies/callPolicyUtils.js.map +1 -0
  59. package/_esm/policies/index.js +9 -0
  60. package/_esm/policies/index.js.map +1 -0
  61. package/_esm/policies/toCallPolicy.js +38 -0
  62. package/_esm/policies/toCallPolicy.js.map +1 -0
  63. package/_esm/policies/toGasPolicy.js +26 -0
  64. package/_esm/policies/toGasPolicy.js.map +1 -0
  65. package/_esm/policies/toRateLimitPolicy.js +26 -0
  66. package/_esm/policies/toRateLimitPolicy.js.map +1 -0
  67. package/_esm/policies/toSignatureCallerPolicy.js +20 -0
  68. package/_esm/policies/toSignatureCallerPolicy.js.map +1 -0
  69. package/_esm/policies/toSudoPolicy.js +18 -0
  70. package/_esm/policies/toSudoPolicy.js.map +1 -0
  71. package/_esm/policies/toTimestampPolicy.js +23 -0
  72. package/_esm/policies/toTimestampPolicy.js.map +1 -0
  73. package/_esm/policies/types.js +17 -0
  74. package/_esm/policies/types.js.map +1 -0
  75. package/_esm/policies/utils/toPolicyId.js +7 -0
  76. package/_esm/policies/utils/toPolicyId.js.map +1 -0
  77. package/_esm/serializePermissionAccount.js +23 -0
  78. package/_esm/serializePermissionAccount.js.map +1 -0
  79. package/_esm/signers/index.js +6 -0
  80. package/_esm/signers/index.js.map +1 -0
  81. package/_esm/signers/toECDSASigner.js +36 -0
  82. package/_esm/signers/toECDSASigner.js.map +1 -0
  83. package/_esm/signers/toEmptyECDSASigner.js +27 -0
  84. package/_esm/signers/toEmptyECDSASigner.js.map +1 -0
  85. package/_esm/signers/toWebAuthnPubKey.js +108 -0
  86. package/_esm/signers/toWebAuthnPubKey.js.map +1 -0
  87. package/_esm/signers/toWebAuthnSigner.js +164 -0
  88. package/_esm/signers/toWebAuthnSigner.js.map +1 -0
  89. package/_esm/signers/utils/toSignerId.js +5 -0
  90. package/_esm/signers/utils/toSignerId.js.map +1 -0
  91. package/_esm/signers/webAuthnUtils.js +41 -0
  92. package/_esm/signers/webAuthnUtils.js.map +1 -0
  93. package/_esm/toPermissionValidator.js +94 -0
  94. package/_esm/toPermissionValidator.js.map +1 -0
  95. package/_esm/types.js +3 -0
  96. package/_esm/types.js.map +1 -0
  97. package/_esm/utils.js +32 -0
  98. package/_esm/utils.js.map +1 -0
  99. package/_types/constants.d.ts +14 -0
  100. package/_types/constants.d.ts.map +1 -0
  101. package/_types/deserializePermissionAccount.d.ts +13 -0
  102. package/_types/deserializePermissionAccount.d.ts.map +1 -0
  103. package/_types/index.d.ts +6 -0
  104. package/_types/index.d.ts.map +1 -0
  105. package/_types/policies/callPolicyUtils.d.ts +5 -0
  106. package/_types/policies/callPolicyUtils.d.ts.map +1 -0
  107. package/_types/policies/index.d.ts +9 -0
  108. package/_types/policies/index.d.ts.map +1 -0
  109. package/_types/policies/toCallPolicy.d.ts +8 -0
  110. package/_types/policies/toCallPolicy.d.ts.map +1 -0
  111. package/_types/policies/toGasPolicy.d.ts +9 -0
  112. package/_types/policies/toGasPolicy.d.ts.map +1 -0
  113. package/_types/policies/toRateLimitPolicy.d.ts +8 -0
  114. package/_types/policies/toRateLimitPolicy.d.ts.map +1 -0
  115. package/_types/policies/toSignatureCallerPolicy.d.ts +7 -0
  116. package/_types/policies/toSignatureCallerPolicy.d.ts.map +1 -0
  117. package/_types/policies/toSudoPolicy.d.ts +4 -0
  118. package/_types/policies/toSudoPolicy.d.ts.map +1 -0
  119. package/_types/policies/toTimestampPolicy.d.ts +7 -0
  120. package/_types/policies/toTimestampPolicy.d.ts.map +1 -0
  121. package/_types/policies/types.d.ts +56 -0
  122. package/_types/policies/types.d.ts.map +1 -0
  123. package/_types/policies/utils/toPolicyId.d.ts +4 -0
  124. package/_types/policies/utils/toPolicyId.d.ts.map +1 -0
  125. package/_types/serializePermissionAccount.d.ts +5 -0
  126. package/_types/serializePermissionAccount.d.ts.map +1 -0
  127. package/_types/signers/index.d.ts +6 -0
  128. package/_types/signers/index.d.ts.map +1 -0
  129. package/_types/signers/toECDSASigner.d.ts +8 -0
  130. package/_types/signers/toECDSASigner.d.ts.map +1 -0
  131. package/_types/signers/toEmptyECDSASigner.d.ts +4 -0
  132. package/_types/signers/toEmptyECDSASigner.d.ts.map +1 -0
  133. package/_types/signers/toWebAuthnPubKey.d.ts +11 -0
  134. package/_types/signers/toWebAuthnPubKey.d.ts.map +1 -0
  135. package/_types/signers/toWebAuthnSigner.d.ts +16 -0
  136. package/_types/signers/toWebAuthnSigner.d.ts.map +1 -0
  137. package/_types/signers/utils/toSignerId.d.ts +4 -0
  138. package/_types/signers/utils/toSignerId.d.ts.map +1 -0
  139. package/_types/signers/webAuthnUtils.d.ts +13 -0
  140. package/_types/signers/webAuthnUtils.d.ts.map +1 -0
  141. package/_types/toPermissionValidator.d.ts +5 -0
  142. package/_types/toPermissionValidator.d.ts.map +1 -0
  143. package/_types/types.d.ts +61 -0
  144. package/_types/types.d.ts.map +1 -0
  145. package/_types/utils.d.ts +8 -0
  146. package/_types/utils.d.ts.map +1 -0
  147. package/constants.ts +19 -0
  148. package/deserializePermissionAccount.ts +130 -0
  149. package/index.ts +5 -0
  150. package/package.json +63 -0
  151. package/policies/callPolicyUtils.ts +122 -0
  152. package/policies/index.ts +17 -0
  153. package/policies/toCallPolicy.ts +65 -0
  154. package/policies/toGasPolicy.ts +42 -0
  155. package/policies/toRateLimitPolicy.ts +41 -0
  156. package/policies/toSignatureCallerPolicy.ts +32 -0
  157. package/policies/toSudoPolicy.ts +24 -0
  158. package/policies/toTimestampPolicy.ts +37 -0
  159. package/policies/types.ts +118 -0
  160. package/policies/utils/toPolicyId.ts +13 -0
  161. package/serializePermissionAccount.ts +38 -0
  162. package/signers/index.ts +11 -0
  163. package/signers/toECDSASigner.ts +61 -0
  164. package/signers/toEmptyECDSASigner.ts +34 -0
  165. package/signers/toWebAuthnPubKey.ts +153 -0
  166. package/signers/toWebAuthnSigner.ts +246 -0
  167. package/signers/utils/toSignerId.ts +9 -0
  168. package/signers/webAuthnUtils.ts +54 -0
  169. package/toPermissionValidator.ts +151 -0
  170. package/types.ts +75 -0
  171. package/utils.ts +42 -0
@@ -0,0 +1,42 @@
1
+ import { type Address, concatHex, encodeAbiParameters, zeroAddress } from "viem"
2
+ import { PolicyFlags } from "../constants.js"
3
+ import { GAS_POLICY_CONTRACT } from "../constants.js"
4
+ import type { Policy, PolicyParams } from "../types.js"
5
+
6
+ export type GasPolicyParams = PolicyParams & {
7
+ allowed?: bigint
8
+ enforcePaymaster?: boolean
9
+ allowedPaymaster?: Address
10
+ }
11
+
12
+ export function toGasPolicy({
13
+ policyAddress = GAS_POLICY_CONTRACT,
14
+ policyFlag = PolicyFlags.FOR_ALL_VALIDATION,
15
+ allowed = 0n,
16
+ enforcePaymaster = false,
17
+ allowedPaymaster = zeroAddress
18
+ }: GasPolicyParams): Policy {
19
+ return {
20
+ getPolicyData: () => {
21
+ return encodeAbiParameters(
22
+ [
23
+ { name: "allowed", type: "uint128" },
24
+ { name: "enforcePaymaster", type: "bool" },
25
+ { name: "allowedPaymaster", type: "address" }
26
+ ],
27
+ [allowed, enforcePaymaster, allowedPaymaster]
28
+ )
29
+ },
30
+ getPolicyInfoInBytes: () => {
31
+ return concatHex([policyFlag, policyAddress])
32
+ },
33
+ policyParams: {
34
+ type: "gas",
35
+ policyAddress,
36
+ policyFlag,
37
+ allowed,
38
+ enforcePaymaster,
39
+ allowedPaymaster
40
+ } as GasPolicyParams & { type: "gas" }
41
+ }
42
+ }
@@ -0,0 +1,41 @@
1
+ import { concatHex } from "viem"
2
+ import { PolicyFlags } from "../constants.js"
3
+ import { RATE_LIMIT_POLICY_CONTRACT } from "../constants.js"
4
+ import type { Policy, PolicyParams } from "../types.js"
5
+
6
+ export type RateLimitPolicyParams = PolicyParams & {
7
+ interval?: number
8
+ count: number
9
+ startAt?: number
10
+ }
11
+
12
+ export function toRateLimitPolicy({
13
+ policyAddress = RATE_LIMIT_POLICY_CONTRACT,
14
+ policyFlag = PolicyFlags.FOR_ALL_VALIDATION,
15
+ interval = 0,
16
+ count,
17
+ startAt = 0
18
+ }: RateLimitPolicyParams): Policy {
19
+ return {
20
+ getPolicyData: () => {
21
+ const intervalHex = interval.toString(16).padStart(12, "0")
22
+ const countHex = count.toString(16).padStart(12, "0")
23
+ const startAtHex = startAt.toString(16).padStart(12, "0")
24
+
25
+ const data = intervalHex + countHex + startAtHex
26
+
27
+ return `0x${data}`
28
+ },
29
+ getPolicyInfoInBytes: () => {
30
+ return concatHex([policyFlag, policyAddress])
31
+ },
32
+ policyParams: {
33
+ type: "rate-limit",
34
+ policyAddress,
35
+ policyFlag,
36
+ interval,
37
+ count,
38
+ startAt
39
+ } as RateLimitPolicyParams & { type: "rate-limit" }
40
+ }
41
+ }
@@ -0,0 +1,32 @@
1
+ import { type Address, concatHex, encodeAbiParameters } from "viem"
2
+ import { PolicyFlags } from "../constants.js"
3
+ import { SIGNATURE_POLICY_CONTRACT } from "../constants.js"
4
+ import type { Policy, PolicyParams } from "../types.js"
5
+
6
+ export type SignatureCallerPolicyParams = PolicyParams & {
7
+ allowedCallers: Address[]
8
+ }
9
+
10
+ export function toSignatureCallerPolicy({
11
+ policyAddress = SIGNATURE_POLICY_CONTRACT,
12
+ policyFlag = PolicyFlags.FOR_ALL_VALIDATION,
13
+ allowedCallers
14
+ }: SignatureCallerPolicyParams): Policy {
15
+ return {
16
+ getPolicyData: () => {
17
+ return encodeAbiParameters(
18
+ [{ name: "allowedCallers", type: "address[]" }],
19
+ [allowedCallers]
20
+ )
21
+ },
22
+ getPolicyInfoInBytes: () => {
23
+ return concatHex([policyFlag, policyAddress])
24
+ },
25
+ policyParams: {
26
+ type: "signature-caller",
27
+ policyAddress,
28
+ policyFlag,
29
+ allowedCallers
30
+ } as SignatureCallerPolicyParams & { type: "signature-caller" }
31
+ }
32
+ }
@@ -0,0 +1,24 @@
1
+ import { concatHex } from "viem"
2
+ import { PolicyFlags, SUDO_POLICY_CONTRACT } from "../constants.js"
3
+ import type { Policy, PolicyParams } from "../types.js"
4
+
5
+ export type SudoPolicyParams = PolicyParams
6
+
7
+ export function toSudoPolicy({
8
+ policyAddress = SUDO_POLICY_CONTRACT,
9
+ policyFlag = PolicyFlags.FOR_ALL_VALIDATION
10
+ }: SudoPolicyParams): Policy {
11
+ return {
12
+ getPolicyData: () => {
13
+ return "0x"
14
+ },
15
+ getPolicyInfoInBytes: () => {
16
+ return concatHex([policyFlag, policyAddress])
17
+ },
18
+ policyParams: {
19
+ type: "sudo",
20
+ policyAddress,
21
+ policyFlag
22
+ } as SudoPolicyParams & { type: "sudo" }
23
+ }
24
+ }
@@ -0,0 +1,37 @@
1
+ import { concatHex, encodeAbiParameters } from "viem"
2
+ import { PolicyFlags, TIMESTAMP_POLICY_CONTRACT } from "../constants.js"
3
+ import type { Policy, PolicyParams } from "../types.js"
4
+
5
+ export type TimestampPolicyParams = PolicyParams & {
6
+ validAfter?: number
7
+ validUntil?: number
8
+ }
9
+
10
+ export function toTimestampPolicy({
11
+ policyAddress = TIMESTAMP_POLICY_CONTRACT,
12
+ policyFlag = PolicyFlags.FOR_ALL_VALIDATION,
13
+ validAfter = 0,
14
+ validUntil = 0
15
+ }: TimestampPolicyParams): Policy {
16
+ return {
17
+ getPolicyData: () => {
18
+ return encodeAbiParameters(
19
+ [
20
+ { name: "validAfter", type: "uint48" },
21
+ { name: "validUntil", type: "uint48" }
22
+ ],
23
+ [validAfter, validUntil]
24
+ )
25
+ },
26
+ getPolicyInfoInBytes: () => {
27
+ return concatHex([policyFlag, policyAddress])
28
+ },
29
+ policyParams: {
30
+ type: "timestamp",
31
+ policyAddress,
32
+ policyFlag,
33
+ validAfter,
34
+ validUntil
35
+ } as TimestampPolicyParams & { type: "timestamp" }
36
+ }
37
+ }
@@ -0,0 +1,118 @@
1
+ import { type ExtractAbiFunction, type ExtractAbiFunctionNames } from "abitype"
2
+ import type {
3
+ Abi,
4
+ AbiFunction,
5
+ AbiParameter,
6
+ AbiParameterKind,
7
+ AbiParameterToPrimitiveType,
8
+ AbiStateMutability,
9
+ Address,
10
+ Hex,
11
+ Narrow
12
+ } from "viem"
13
+
14
+ export enum CallType {
15
+ CALL = "0x00",
16
+ BATCH_CALL = "0x01",
17
+ DELEGATE_CALL = "0xff"
18
+ }
19
+
20
+ export enum ParamCondition {
21
+ EQUAL = 0,
22
+ GREATER_THAN = 1,
23
+ LESS_THAN = 2,
24
+ GREATER_THAN_OR_EQUAL = 3,
25
+ LESS_THAN_OR_EQUAL = 4,
26
+ NOT_EQUAL = 5
27
+ }
28
+
29
+ export interface ParamRule {
30
+ condition: ParamCondition
31
+ offset: number
32
+ param: Hex
33
+ }
34
+
35
+ export type PermissionCore = {
36
+ callType?: CallType
37
+ target: Address
38
+ selector?: Hex
39
+ valueLimit?: bigint
40
+ rules?: ParamRule[]
41
+ }
42
+
43
+ export type InferFunctionName<
44
+ TAbi extends Abi | readonly unknown[] = Abi,
45
+ TFunctionName extends string | undefined = string,
46
+ TAbiStateMutability extends AbiStateMutability = AbiStateMutability
47
+ > = TAbi extends Abi
48
+ ? ExtractAbiFunctionNames<
49
+ TAbi,
50
+ TAbiStateMutability
51
+ > extends infer AbiFunctionNames
52
+ ?
53
+ | AbiFunctionNames
54
+ | (TFunctionName extends AbiFunctionNames ? TFunctionName : never)
55
+ | (Abi extends TAbi ? string : never)
56
+ : never
57
+ : TFunctionName
58
+
59
+ export type GetFunctionArgs<
60
+ TAbi extends Abi | readonly unknown[],
61
+ TFunctionName extends string,
62
+ TAbiFunction extends AbiFunction = TAbi extends Abi
63
+ ? ExtractAbiFunction<TAbi, TFunctionName>
64
+ : AbiFunction,
65
+ TArgs = CombinedArgs<TAbiFunction["inputs"]>,
66
+ FailedToParseArgs =
67
+ | ([TArgs] extends [never] ? true : false)
68
+ | (readonly unknown[] extends TArgs ? true : false)
69
+ > = true extends FailedToParseArgs
70
+ ? {
71
+ args?: readonly unknown[]
72
+ }
73
+ : TArgs extends readonly []
74
+ ? { args?: never }
75
+ : {
76
+ args?: TArgs
77
+ }
78
+
79
+ export type Permission<
80
+ TAbi extends Abi | readonly unknown[],
81
+ TFunctionName extends string | undefined = string,
82
+ _FunctionName = TAbi extends Abi
83
+ ? InferFunctionName<TAbi, TFunctionName>
84
+ : never
85
+ > = PermissionCore & {
86
+ functionName?: _FunctionName
87
+ } & (TFunctionName extends string
88
+ ? { abi?: Narrow<TAbi> } & GetFunctionArgs<TAbi, TFunctionName>
89
+ : _FunctionName extends string
90
+ ? { abi?: [Narrow<TAbi[number]>] } & GetFunctionArgs<
91
+ TAbi,
92
+ _FunctionName
93
+ >
94
+ : never)
95
+
96
+ export type CombinedArgs<
97
+ TAbiParameters extends readonly AbiParameter[],
98
+ TAbiParameterKind extends AbiParameterKind = AbiParameterKind
99
+ > = {
100
+ [K in keyof TAbiParameters]: {
101
+ condition: ParamCondition
102
+ value: AbiParameterToPrimitiveType<TAbiParameters[K], TAbiParameterKind>
103
+ } | null
104
+ }
105
+
106
+ export type GeneratePermissionFromArgsParameters<
107
+ TAbi extends Abi | readonly unknown[],
108
+ TFunctionName extends string | undefined = string,
109
+ _FunctionName = TAbi extends Abi
110
+ ? InferFunctionName<TAbi, TFunctionName>
111
+ : never
112
+ > = {
113
+ functionName?: _FunctionName
114
+ } & (TFunctionName extends string
115
+ ? { abi: Narrow<TAbi> } & GetFunctionArgs<TAbi, TFunctionName>
116
+ : _FunctionName extends string
117
+ ? { abi: [Narrow<TAbi[number]>] } & GetFunctionArgs<TAbi, _FunctionName>
118
+ : never)
@@ -0,0 +1,13 @@
1
+ import { type Hex, concat, encodeAbiParameters } from "viem"
2
+ import type { Policy } from "../../types.js"
3
+
4
+ export const toPolicyId = (policies: Policy[]): Hex => {
5
+ return encodeAbiParameters(
6
+ [{ name: "policiesData", type: "bytes[]" }],
7
+ [
8
+ policies.map((policy) =>
9
+ concat([policy.getPolicyInfoInBytes(), policy.getPolicyData()])
10
+ )
11
+ ]
12
+ )
13
+ }
@@ -0,0 +1,38 @@
1
+ import type { KernelSmartAccount } from "@zerodev/sdk"
2
+ import type { EntryPoint } from "permissionless/types"
3
+ import type { Hex } from "viem"
4
+ import {
5
+ isPermissionValidatorPlugin,
6
+ serializePermissionAccountParams
7
+ } from "./utils.js"
8
+
9
+ export const serializePermissionAccount = async <entryPoint extends EntryPoint>(
10
+ account: KernelSmartAccount<entryPoint>,
11
+ privateKey?: Hex
12
+ ): Promise<string> => {
13
+ if (!isPermissionValidatorPlugin(account.kernelPluginManager))
14
+ throw new Error("Account plugin is not a permission validator")
15
+ const permissionParams =
16
+ account.kernelPluginManager.getPluginSerializationParams()
17
+ const action = account.kernelPluginManager.getAction()
18
+ const validityData = account.kernelPluginManager.getValidityData()
19
+ const enableSignature =
20
+ await account.kernelPluginManager.getPluginEnableSignature(
21
+ account.address
22
+ )
23
+ const accountParams = {
24
+ initCode: await account.generateInitCode(),
25
+ accountAddress: account.address
26
+ }
27
+
28
+ const paramsToBeSerialized = {
29
+ permissionParams,
30
+ action,
31
+ validityData,
32
+ accountParams,
33
+ enableSignature,
34
+ privateKey
35
+ }
36
+
37
+ return serializePermissionAccountParams(paramsToBeSerialized)
38
+ }
@@ -0,0 +1,11 @@
1
+ export {
2
+ toECDSASigner,
3
+ type ECDSAModularSignerParams
4
+ } from "./toECDSASigner.js"
5
+ export {
6
+ toWebAuthnSigner,
7
+ type WebAuthnModularSignerParams
8
+ } from "./toWebAuthnSigner.js"
9
+ export { WebAuthnMode } from "./toWebAuthnPubKey.js"
10
+ export { toSignerId } from "./utils/toSignerId.js"
11
+ export { toEmptyECDSASigner } from "./toEmptyECDSASigner.js"
@@ -0,0 +1,61 @@
1
+ import { constants, fixSignedData } from "@zerodev/sdk"
2
+ import type { TypedData } from "abitype"
3
+ import {
4
+ SignTransactionNotSupportedBySmartAccount,
5
+ type SmartAccountSigner
6
+ } from "permissionless/accounts"
7
+ import { type Address, type LocalAccount, type TypedDataDefinition } from "viem"
8
+ import { toAccount } from "viem/accounts"
9
+ import { ECDSA_SIGNER_CONTRACT } from "../constants.js"
10
+ import type { ModularSigner, ModularSignerParams } from "../types.js"
11
+
12
+ export type ECDSAModularSignerParams<
13
+ TSource extends string = "custom",
14
+ TAddress extends Address = Address
15
+ > = ModularSignerParams & {
16
+ signer: SmartAccountSigner<TSource, TAddress>
17
+ }
18
+
19
+ export function toECDSASigner<
20
+ TSource extends string = "custom",
21
+ TAddress extends Address = Address
22
+ >({
23
+ signer,
24
+ signerContractAddress = ECDSA_SIGNER_CONTRACT
25
+ }: ECDSAModularSignerParams<TSource, TAddress>): ModularSigner {
26
+ const viemSigner: LocalAccount = {
27
+ ...signer,
28
+ signTransaction: (_, __) => {
29
+ throw new SignTransactionNotSupportedBySmartAccount()
30
+ }
31
+ } as LocalAccount
32
+ const account = toAccount({
33
+ address: viemSigner.address,
34
+ async signMessage({ message }) {
35
+ return fixSignedData(await viemSigner.signMessage({ message }))
36
+ },
37
+ async signTransaction(_, __) {
38
+ throw new SignTransactionNotSupportedBySmartAccount()
39
+ },
40
+ async signTypedData<
41
+ const TTypedData extends TypedData | Record<string, unknown>,
42
+ TPrimaryType extends
43
+ | keyof TTypedData
44
+ | "EIP712Domain" = keyof TTypedData
45
+ >(typedData: TypedDataDefinition<TTypedData, TPrimaryType>) {
46
+ return fixSignedData(
47
+ await viemSigner.signTypedData<TTypedData, TPrimaryType>({
48
+ ...typedData
49
+ })
50
+ )
51
+ }
52
+ })
53
+ return {
54
+ account,
55
+ signerContractAddress,
56
+ getSignerData: () => {
57
+ return viemSigner.address
58
+ },
59
+ getDummySignature: () => constants.DUMMY_ECDSA_SIG
60
+ }
61
+ }
@@ -0,0 +1,34 @@
1
+ import { constants } from "@zerodev/sdk"
2
+ import type { TypedData } from "abitype"
3
+ import { type Address, type TypedDataDefinition } from "viem"
4
+ import { toAccount } from "viem/accounts"
5
+ import { ECDSA_SIGNER_CONTRACT } from "../constants.js"
6
+ import type { ModularSigner } from "../types.js"
7
+
8
+ export function toEmptyECDSASigner(address: Address): ModularSigner {
9
+ const account = toAccount({
10
+ address,
11
+ async signMessage() {
12
+ throw new Error("Method not supported")
13
+ },
14
+ async signTransaction(_, __) {
15
+ throw new Error("Method not supported")
16
+ },
17
+ async signTypedData<
18
+ const TTypedData extends TypedData | Record<string, unknown>,
19
+ TPrimaryType extends
20
+ | keyof TTypedData
21
+ | "EIP712Domain" = keyof TTypedData
22
+ >(_typedData: TypedDataDefinition<TTypedData, TPrimaryType>) {
23
+ throw new Error("Method not supported")
24
+ }
25
+ })
26
+ return {
27
+ account,
28
+ signerContractAddress: ECDSA_SIGNER_CONTRACT,
29
+ getSignerData: () => {
30
+ return address
31
+ },
32
+ getDummySignature: () => constants.DUMMY_ECDSA_SIG
33
+ }
34
+ }
@@ -0,0 +1,153 @@
1
+ import { Buffer } from "buffer"
2
+ import { type Hex, keccak256 } from "viem"
3
+ import { type WebAuthnKey } from "./toWebAuthnSigner.js"
4
+ import { b64ToBytes, uint8ArrayToHexString } from "./webAuthnUtils.js"
5
+
6
+ export enum WebAuthnMode {
7
+ Register = "register",
8
+ Login = "login"
9
+ }
10
+
11
+ export const toWebAuthnPubKey = async ({
12
+ passkeyName,
13
+ passkeyServerUrl,
14
+ mode = WebAuthnMode.Login
15
+ }: {
16
+ passkeyName: string
17
+ passkeyServerUrl: string
18
+ mode: WebAuthnMode
19
+ }): Promise<WebAuthnKey> => {
20
+ let pubKey: string | undefined
21
+ let authenticatorIdHash: Hex
22
+ if (mode === WebAuthnMode.Login) {
23
+ // Get login options
24
+ const loginOptionsResponse = await fetch(
25
+ `${passkeyServerUrl}/login/options`,
26
+ {
27
+ method: "POST",
28
+ headers: { "Content-Type": "application/json" },
29
+ credentials: "include"
30
+ }
31
+ )
32
+ const loginOptions = await loginOptionsResponse.json()
33
+
34
+ // Start authentication (login)
35
+ const { startAuthentication } = await import("@simplewebauthn/browser")
36
+ const loginCred = await startAuthentication(loginOptions)
37
+
38
+ // get authenticatorIdHash
39
+ authenticatorIdHash = keccak256(
40
+ uint8ArrayToHexString(b64ToBytes(loginCred.id))
41
+ )
42
+
43
+ // Verify authentication
44
+ const loginVerifyResponse = await fetch(
45
+ `${passkeyServerUrl}/login/verify`,
46
+ {
47
+ method: "POST",
48
+ headers: { "Content-Type": "application/json" },
49
+ body: JSON.stringify({ cred: loginCred }),
50
+ credentials: "include"
51
+ }
52
+ )
53
+
54
+ const loginVerifyResult = await loginVerifyResponse.json()
55
+
56
+ if (window.sessionStorage === undefined) {
57
+ throw new Error("sessionStorage is not available")
58
+ }
59
+ sessionStorage.setItem("userId", loginVerifyResult.userId)
60
+
61
+ if (!loginVerifyResult.verification.verified) {
62
+ throw new Error("Login not verified")
63
+ }
64
+ // Import the key
65
+ pubKey = loginVerifyResult.pubkey // Uint8Array pubkey
66
+ } else {
67
+ if (!passkeyName) {
68
+ throw new Error("No passkey name provided")
69
+ }
70
+ // Get registration options
71
+ const registerOptionsResponse = await fetch(
72
+ `${passkeyServerUrl}/register/options`,
73
+ {
74
+ method: "POST",
75
+ headers: {
76
+ "Content-Type": "application/json"
77
+ },
78
+ body: JSON.stringify({ username: passkeyName }),
79
+ credentials: "include"
80
+ }
81
+ )
82
+ const registerOptions = await registerOptionsResponse.json()
83
+
84
+ // save userId to sessionStorage
85
+ if (window.sessionStorage === undefined) {
86
+ throw new Error("sessionStorage is not available")
87
+ }
88
+ sessionStorage.setItem("userId", registerOptions.userId)
89
+
90
+ // Start registration
91
+ const { startRegistration } = await import("@simplewebauthn/browser")
92
+ const registerCred = await startRegistration(registerOptions.options)
93
+
94
+ // get authenticatorIdHash
95
+ authenticatorIdHash = keccak256(
96
+ uint8ArrayToHexString(b64ToBytes(registerCred.id))
97
+ )
98
+
99
+ // Verify registration
100
+ const registerVerifyResponse = await fetch(
101
+ `${passkeyServerUrl}/register/verify`,
102
+ {
103
+ method: "POST",
104
+ headers: {
105
+ "Content-Type": "application/json"
106
+ },
107
+ body: JSON.stringify({
108
+ userId: registerOptions.userId,
109
+ username: passkeyName,
110
+ cred: registerCred
111
+ }),
112
+ credentials: "include"
113
+ }
114
+ )
115
+
116
+ const registerVerifyResult = await registerVerifyResponse.json()
117
+ if (!registerVerifyResult.verified) {
118
+ throw new Error("Registration not verified")
119
+ }
120
+
121
+ // Import the key
122
+ pubKey = registerCred.response.publicKey
123
+ }
124
+ if (!pubKey) {
125
+ throw new Error("No public key returned from registration credential")
126
+ }
127
+
128
+ const spkiDer = Buffer.from(pubKey, "base64")
129
+ const key = await crypto.subtle.importKey(
130
+ "spki",
131
+ spkiDer,
132
+ {
133
+ name: "ECDSA",
134
+ namedCurve: "P-256"
135
+ },
136
+ true,
137
+ ["verify"]
138
+ )
139
+
140
+ // Export the key to the raw format
141
+ const rawKey = await crypto.subtle.exportKey("raw", key)
142
+ const rawKeyBuffer = Buffer.from(rawKey)
143
+
144
+ // The first byte is 0x04 (uncompressed), followed by x and y coordinates (32 bytes each for P-256)
145
+ const pubKeyX = rawKeyBuffer.subarray(1, 33).toString("hex")
146
+ const pubKeyY = rawKeyBuffer.subarray(33).toString("hex")
147
+
148
+ return {
149
+ pubX: BigInt(`0x${pubKeyX}`),
150
+ pubY: BigInt(`0x${pubKeyY}`),
151
+ authenticatorIdHash
152
+ }
153
+ }