@account-kit/smart-contracts 4.23.0 → 4.24.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 (49) hide show
  1. package/dist/esm/src/ma-v2/account/common/modularAccountV2Base.d.ts +1 -0
  2. package/dist/esm/src/ma-v2/account/common/modularAccountV2Base.js +38 -11
  3. package/dist/esm/src/ma-v2/account/common/modularAccountV2Base.js.map +1 -1
  4. package/dist/esm/src/ma-v2/account/modularAccountV2.d.ts +1 -0
  5. package/dist/esm/src/ma-v2/account/modularAccountV2.js +2 -1
  6. package/dist/esm/src/ma-v2/account/modularAccountV2.js.map +1 -1
  7. package/dist/esm/src/ma-v2/account/nativeSMASigner.d.ts +2 -2
  8. package/dist/esm/src/ma-v2/account/nativeSMASigner.js +11 -8
  9. package/dist/esm/src/ma-v2/account/nativeSMASigner.js.map +1 -1
  10. package/dist/esm/src/ma-v2/actions/deferralActions.d.ts +9 -7
  11. package/dist/esm/src/ma-v2/actions/deferralActions.js +21 -35
  12. package/dist/esm/src/ma-v2/actions/deferralActions.js.map +1 -1
  13. package/dist/esm/src/ma-v2/index.d.ts +4 -0
  14. package/dist/esm/src/ma-v2/index.js +2 -0
  15. package/dist/esm/src/ma-v2/index.js.map +1 -1
  16. package/dist/esm/src/ma-v2/modules/single-signer-validation/signer.d.ts +2 -1
  17. package/dist/esm/src/ma-v2/modules/single-signer-validation/signer.js +10 -6
  18. package/dist/esm/src/ma-v2/modules/single-signer-validation/signer.js.map +1 -1
  19. package/dist/esm/src/ma-v2/permissionBuilder.d.ts +115 -0
  20. package/dist/esm/src/ma-v2/permissionBuilder.js +485 -0
  21. package/dist/esm/src/ma-v2/permissionBuilder.js.map +1 -0
  22. package/dist/esm/src/ma-v2/utils.d.ts +37 -0
  23. package/dist/esm/src/ma-v2/utils.js +7 -1
  24. package/dist/esm/src/ma-v2/utils.js.map +1 -1
  25. package/dist/types/src/ma-v2/account/common/modularAccountV2Base.d.ts +1 -0
  26. package/dist/types/src/ma-v2/account/common/modularAccountV2Base.d.ts.map +1 -1
  27. package/dist/types/src/ma-v2/account/modularAccountV2.d.ts +1 -0
  28. package/dist/types/src/ma-v2/account/modularAccountV2.d.ts.map +1 -1
  29. package/dist/types/src/ma-v2/account/nativeSMASigner.d.ts +2 -2
  30. package/dist/types/src/ma-v2/account/nativeSMASigner.d.ts.map +1 -1
  31. package/dist/types/src/ma-v2/actions/deferralActions.d.ts +9 -7
  32. package/dist/types/src/ma-v2/actions/deferralActions.d.ts.map +1 -1
  33. package/dist/types/src/ma-v2/index.d.ts +4 -0
  34. package/dist/types/src/ma-v2/index.d.ts.map +1 -1
  35. package/dist/types/src/ma-v2/modules/single-signer-validation/signer.d.ts +2 -1
  36. package/dist/types/src/ma-v2/modules/single-signer-validation/signer.d.ts.map +1 -1
  37. package/dist/types/src/ma-v2/permissionBuilder.d.ts +116 -0
  38. package/dist/types/src/ma-v2/permissionBuilder.d.ts.map +1 -0
  39. package/dist/types/src/ma-v2/utils.d.ts +37 -0
  40. package/dist/types/src/ma-v2/utils.d.ts.map +1 -1
  41. package/package.json +6 -5
  42. package/src/ma-v2/account/common/modularAccountV2Base.ts +52 -10
  43. package/src/ma-v2/account/modularAccountV2.ts +3 -0
  44. package/src/ma-v2/account/nativeSMASigner.ts +20 -14
  45. package/src/ma-v2/actions/deferralActions.ts +38 -51
  46. package/src/ma-v2/index.ts +4 -0
  47. package/src/ma-v2/modules/single-signer-validation/signer.ts +19 -13
  48. package/src/ma-v2/permissionBuilder.ts +724 -0
  49. package/src/ma-v2/utils.ts +10 -0
@@ -23,22 +23,26 @@ import { packUOSignature, pack1271Signature } from "../../utils.js";
23
23
  * @param {Chain} chain Chain object for the signer
24
24
  * @param {Address} accountAddress address of the smart account using this signer
25
25
  * @param {number} entityId the entity id of the signing validation
26
+ * @param {Hex} deferredActionData optional deferred action data to prepend to the uo signatures
26
27
  * @returns {object} an object with methods for signing operations and managing signatures
27
28
  */
28
- export const singleSignerMessageSigner = (signer, chain, accountAddress, entityId) => {
29
+ export const singleSignerMessageSigner = (signer, chain, accountAddress, entityId, deferredActionData) => {
29
30
  return {
30
31
  getDummySignature: () => {
31
- const dummyEcdsaSignature = "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c";
32
- return packUOSignature({
32
+ const sig = packUOSignature({
33
33
  // orderedHookData: [],
34
- validationSignature: dummyEcdsaSignature,
34
+ validationSignature: "0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c",
35
35
  });
36
+ return deferredActionData ? concatHex([deferredActionData, sig]) : sig;
36
37
  },
37
- signUserOperationHash: (uoHash) => {
38
- return signer.signMessage({ raw: uoHash }).then((signature) => packUOSignature({
38
+ signUserOperationHash: async (uoHash) => {
39
+ const sig = await signer
40
+ .signMessage({ raw: uoHash })
41
+ .then((signature) => packUOSignature({
39
42
  // orderedHookData: [],
40
43
  validationSignature: signature,
41
44
  }));
45
+ return deferredActionData ? concatHex([deferredActionData, sig]) : sig;
42
46
  },
43
47
  // we apply the expected 1271 packing here since the account contract will expect it
44
48
  async signMessage({ message }) {
@@ -1 +1 @@
1
- {"version":3,"file":"signer.js","sourceRoot":"","sources":["../../../../../../src/ma-v2/modules/single-signer-validation/signer.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SmartAccountSigner } from \"@aa-sdk/core\";\nimport {\n hashMessage,\n hashTypedData,\n concatHex,\n type Hex,\n type SignableMessage,\n type TypedData,\n type TypedDataDefinition,\n type Chain,\n type Address,\n concat,\n} from \"viem\";\nimport {\n getDefaultSingleSignerValidationModuleAddress,\n SignatureType,\n} from \"../utils.js\";\n\nimport { packUOSignature, pack1271Signature } from \"../../utils.js\";\n/**\n * Creates an object with methods for generating a dummy signature, signing user operation hashes, signing messages, and signing typed data.\n *\n * @example \n \n * ```ts\n * import { singleSignerMessageSigner } from \"@account-kit/smart-contracts\";\n * import { LocalAccountSigner } from \"@aa-sdk/core\";\n *\n * const MNEMONIC = \"...\":\n * \n * const account = createModularAccountV2({ config });\n *\n * const signer = LocalAccountSigner.mnemonicToAccountSigner(MNEMONIC);\n *\n * const messageSigner = singleSignerMessageSigner(signer, chain, account.address, account.signerEntity.entityId);\n * ```\n *\n * @param {SmartAccountSigner} signer Signer to use for signing operations\n * @param {Chain} chain Chain object for the signer\n * @param {Address} accountAddress address of the smart account using this signer\n * @param {number} entityId the entity id of the signing validation\n * @returns {object} an object with methods for signing operations and managing signatures\n */\nexport const singleSignerMessageSigner = (\n signer: SmartAccountSigner,\n chain: Chain,\n accountAddress: Address,\n entityId: number\n) => {\n return {\n getDummySignature: (): Hex => {\n const dummyEcdsaSignature =\n \"0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c\";\n\n return packUOSignature({\n // orderedHookData: [],\n validationSignature: dummyEcdsaSignature,\n });\n },\n\n signUserOperationHash: (uoHash: Hex): Promise<Hex> => {\n return signer.signMessage({ raw: uoHash }).then((signature: Hex) =>\n packUOSignature({\n // orderedHookData: [],\n validationSignature: signature,\n })\n );\n },\n\n // we apply the expected 1271 packing here since the account contract will expect it\n async signMessage({ message }: { message: SignableMessage }): Promise<Hex> {\n const hash = await hashMessage(message);\n\n return pack1271Signature({\n validationSignature: await signer.signTypedData({\n domain: {\n chainId: Number(chain.id),\n verifyingContract:\n getDefaultSingleSignerValidationModuleAddress(chain),\n salt: concatHex([`0x${\"00\".repeat(12)}`, accountAddress]),\n },\n types: {\n ReplaySafeHash: [{ name: \"hash\", type: \"bytes32\" }],\n },\n message: {\n hash,\n },\n primaryType: \"ReplaySafeHash\",\n }),\n entityId,\n });\n },\n\n // TODO: maybe move \"sign deferred actions\" to a separate function?\n // we don't apply the expected 1271 packing since deferred sigs use typed data sigs and don't expect the 1271 packing\n signTypedData: async <\n const typedData extends TypedData | Record<string, unknown>,\n primaryType extends keyof typedData | \"EIP712Domain\" = keyof typedData\n >(\n typedDataDefinition: TypedDataDefinition<typedData, primaryType>\n ): Promise<Hex> => {\n // the accounts domain already gives replay protection across accounts for deferred actions, so we don't need to apply another wrapping\n const isDeferredAction =\n typedDataDefinition?.primaryType === \"DeferredAction\" &&\n typedDataDefinition?.domain?.verifyingContract === accountAddress;\n\n const validationSignature = await signer.signTypedData({\n domain: {\n chainId: Number(chain.id),\n verifyingContract:\n getDefaultSingleSignerValidationModuleAddress(chain),\n salt: concatHex([`0x${\"00\".repeat(12)}`, accountAddress]),\n },\n types: {\n ReplaySafeHash: [{ name: \"hash\", type: \"bytes32\" }],\n },\n message: {\n hash: hashTypedData(typedDataDefinition),\n },\n primaryType: \"ReplaySafeHash\",\n });\n\n // TODO: Handle non-EOA signer case\n return isDeferredAction\n ? concat([SignatureType.EOA, validationSignature])\n : pack1271Signature({\n validationSignature,\n entityId,\n });\n },\n };\n};\n"]}
1
+ {"version":3,"file":"signer.js","sourceRoot":"","sources":["../../../../../../src/ma-v2/modules/single-signer-validation/signer.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,aAAa,EACb,SAAS,EAOT,MAAM,GACP,MAAM,MAAM,CAAC;AACd,OAAO,EACL,6CAA6C,EAC7C,aAAa,GACd,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACpE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,MAA0B,EAC1B,KAAY,EACZ,cAAuB,EACvB,QAAgB,EAChB,kBAAwB,EACxB,EAAE;IACF,OAAO;QACL,iBAAiB,EAAE,GAAQ,EAAE;YAC3B,MAAM,GAAG,GAAG,eAAe,CAAC;gBAC1B,uBAAuB;gBACvB,mBAAmB,EACjB,sIAAsI;aACzI,CAAC,CAAC;YAEH,OAAO,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACzE,CAAC;QAED,qBAAqB,EAAE,KAAK,EAAE,MAAW,EAAgB,EAAE;YACzD,MAAM,GAAG,GAAG,MAAM,MAAM;iBACrB,WAAW,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;iBAC5B,IAAI,CAAC,CAAC,SAAc,EAAE,EAAE,CACvB,eAAe,CAAC;gBACd,uBAAuB;gBACvB,mBAAmB,EAAE,SAAS;aAC/B,CAAC,CACH,CAAC;YAEJ,OAAO,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACzE,CAAC;QAED,oFAAoF;QACpF,KAAK,CAAC,WAAW,CAAC,EAAE,OAAO,EAAgC;YACzD,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;YAExC,OAAO,iBAAiB,CAAC;gBACvB,mBAAmB,EAAE,MAAM,MAAM,CAAC,aAAa,CAAC;oBAC9C,MAAM,EAAE;wBACN,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;wBACzB,iBAAiB,EACf,6CAA6C,CAAC,KAAK,CAAC;wBACtD,IAAI,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;qBAC1D;oBACD,KAAK,EAAE;wBACL,cAAc,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;qBACpD;oBACD,OAAO,EAAE;wBACP,IAAI;qBACL;oBACD,WAAW,EAAE,gBAAgB;iBAC9B,CAAC;gBACF,QAAQ;aACT,CAAC,CAAC;QACL,CAAC;QAED,mEAAmE;QACnE,qHAAqH;QACrH,aAAa,EAAE,KAAK,EAIlB,mBAAgE,EAClD,EAAE;YAChB,uIAAuI;YACvI,MAAM,gBAAgB,GACpB,mBAAmB,EAAE,WAAW,KAAK,gBAAgB;gBACrD,mBAAmB,EAAE,MAAM,EAAE,iBAAiB,KAAK,cAAc,CAAC;YAEpE,MAAM,mBAAmB,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC;gBACrD,MAAM,EAAE;oBACN,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,iBAAiB,EACf,6CAA6C,CAAC,KAAK,CAAC;oBACtD,IAAI,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;iBAC1D;gBACD,KAAK,EAAE;oBACL,cAAc,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;iBACpD;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,aAAa,CAAC,mBAAmB,CAAC;iBACzC;gBACD,WAAW,EAAE,gBAAgB;aAC9B,CAAC,CAAC;YAEH,mCAAmC;YACnC,OAAO,gBAAgB;gBACrB,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;gBAClD,CAAC,CAAC,iBAAiB,CAAC;oBAChB,mBAAmB;oBACnB,QAAQ;iBACT,CAAC,CAAC;QACT,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import type { SmartAccountSigner } from \"@aa-sdk/core\";\nimport {\n hashMessage,\n hashTypedData,\n concatHex,\n type Hex,\n type SignableMessage,\n type TypedData,\n type TypedDataDefinition,\n type Chain,\n type Address,\n concat,\n} from \"viem\";\nimport {\n getDefaultSingleSignerValidationModuleAddress,\n SignatureType,\n} from \"../utils.js\";\n\nimport { packUOSignature, pack1271Signature } from \"../../utils.js\";\n/**\n * Creates an object with methods for generating a dummy signature, signing user operation hashes, signing messages, and signing typed data.\n *\n * @example \n \n * ```ts\n * import { singleSignerMessageSigner } from \"@account-kit/smart-contracts\";\n * import { LocalAccountSigner } from \"@aa-sdk/core\";\n *\n * const MNEMONIC = \"...\":\n * \n * const account = createModularAccountV2({ config });\n *\n * const signer = LocalAccountSigner.mnemonicToAccountSigner(MNEMONIC);\n *\n * const messageSigner = singleSignerMessageSigner(signer, chain, account.address, account.signerEntity.entityId);\n * ```\n *\n * @param {SmartAccountSigner} signer Signer to use for signing operations\n * @param {Chain} chain Chain object for the signer\n * @param {Address} accountAddress address of the smart account using this signer\n * @param {number} entityId the entity id of the signing validation\n * @param {Hex} deferredActionData optional deferred action data to prepend to the uo signatures\n * @returns {object} an object with methods for signing operations and managing signatures\n */\nexport const singleSignerMessageSigner = (\n signer: SmartAccountSigner,\n chain: Chain,\n accountAddress: Address,\n entityId: number,\n deferredActionData?: Hex\n) => {\n return {\n getDummySignature: (): Hex => {\n const sig = packUOSignature({\n // orderedHookData: [],\n validationSignature:\n \"0xfffffffffffffffffffffffffffffff0000000000000000000000000000000007aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c\",\n });\n\n return deferredActionData ? concatHex([deferredActionData, sig]) : sig;\n },\n\n signUserOperationHash: async (uoHash: Hex): Promise<Hex> => {\n const sig = await signer\n .signMessage({ raw: uoHash })\n .then((signature: Hex) =>\n packUOSignature({\n // orderedHookData: [],\n validationSignature: signature,\n })\n );\n\n return deferredActionData ? concatHex([deferredActionData, sig]) : sig;\n },\n\n // we apply the expected 1271 packing here since the account contract will expect it\n async signMessage({ message }: { message: SignableMessage }): Promise<Hex> {\n const hash = await hashMessage(message);\n\n return pack1271Signature({\n validationSignature: await signer.signTypedData({\n domain: {\n chainId: Number(chain.id),\n verifyingContract:\n getDefaultSingleSignerValidationModuleAddress(chain),\n salt: concatHex([`0x${\"00\".repeat(12)}`, accountAddress]),\n },\n types: {\n ReplaySafeHash: [{ name: \"hash\", type: \"bytes32\" }],\n },\n message: {\n hash,\n },\n primaryType: \"ReplaySafeHash\",\n }),\n entityId,\n });\n },\n\n // TODO: maybe move \"sign deferred actions\" to a separate function?\n // we don't apply the expected 1271 packing since deferred sigs use typed data sigs and don't expect the 1271 packing\n signTypedData: async <\n const typedData extends TypedData | Record<string, unknown>,\n primaryType extends keyof typedData | \"EIP712Domain\" = keyof typedData\n >(\n typedDataDefinition: TypedDataDefinition<typedData, primaryType>\n ): Promise<Hex> => {\n // the accounts domain already gives replay protection across accounts for deferred actions, so we don't need to apply another wrapping\n const isDeferredAction =\n typedDataDefinition?.primaryType === \"DeferredAction\" &&\n typedDataDefinition?.domain?.verifyingContract === accountAddress;\n\n const validationSignature = await signer.signTypedData({\n domain: {\n chainId: Number(chain.id),\n verifyingContract:\n getDefaultSingleSignerValidationModuleAddress(chain),\n salt: concatHex([`0x${\"00\".repeat(12)}`, accountAddress]),\n },\n types: {\n ReplaySafeHash: [{ name: \"hash\", type: \"bytes32\" }],\n },\n message: {\n hash: hashTypedData(typedDataDefinition),\n },\n primaryType: \"ReplaySafeHash\",\n });\n\n // TODO: Handle non-EOA signer case\n return isDeferredAction\n ? concat([SignatureType.EOA, validationSignature])\n : pack1271Signature({\n validationSignature,\n entityId,\n });\n },\n };\n};\n"]}
@@ -0,0 +1,115 @@
1
+ import { type Address, type Hex } from "viem";
2
+ import { type HookConfig } from "./actions/common/types.js";
3
+ import { type InstallValidationParams } from "./actions/install-validation/installValidation.js";
4
+ import type { ModularAccountV2Client } from "./client/client.js";
5
+ import { type DeferredActionTypedData } from "./actions/deferralActions.js";
6
+ export declare enum PermissionType {
7
+ NATIVE_TOKEN_TRANSFER = "native-token-transfer",
8
+ ERC20_TOKEN_TRANSFER = "erc20-token-transfer",
9
+ GAS_LIMIT = "gas-limit",
10
+ CONTRACT_ACCESS = "contract-access",
11
+ ACCOUNT_FUNCTIONS = "account-functions",
12
+ FUNCTIONS_ON_ALL_CONTRACTS = "functions-on-all-contracts",
13
+ FUNCTIONS_ON_CONTRACT = "functions-on-contract",
14
+ ROOT = "root"
15
+ }
16
+ type OneOf<T extends {}[]> = T[number];
17
+ type Key = {
18
+ publicKey: Hex;
19
+ type: "secp256k1" | "contract";
20
+ };
21
+ export type Permission = OneOf<[
22
+ {
23
+ type: PermissionType.NATIVE_TOKEN_TRANSFER;
24
+ data: {
25
+ allowance: Hex;
26
+ };
27
+ },
28
+ {
29
+ type: PermissionType.ERC20_TOKEN_TRANSFER;
30
+ data: {
31
+ address: Address;
32
+ allowance: Hex;
33
+ };
34
+ },
35
+ {
36
+ type: PermissionType.GAS_LIMIT;
37
+ data: {
38
+ limit: Hex;
39
+ };
40
+ },
41
+ {
42
+ type: PermissionType.CONTRACT_ACCESS;
43
+ data: {
44
+ address: Address;
45
+ };
46
+ },
47
+ {
48
+ type: PermissionType.ACCOUNT_FUNCTIONS;
49
+ data: {
50
+ functions: Hex[];
51
+ };
52
+ },
53
+ {
54
+ type: PermissionType.FUNCTIONS_ON_ALL_CONTRACTS;
55
+ data: {
56
+ functions: Hex[];
57
+ };
58
+ },
59
+ {
60
+ type: PermissionType.FUNCTIONS_ON_CONTRACT;
61
+ data: {
62
+ address: Address;
63
+ functions: Hex[];
64
+ };
65
+ },
66
+ {
67
+ type: PermissionType.ROOT;
68
+ data?: never;
69
+ }
70
+ ]>;
71
+ type Hook = {
72
+ hookConfig: HookConfig;
73
+ initData: Hex;
74
+ };
75
+ export declare class PermissionBuilder {
76
+ private client;
77
+ private validationConfig;
78
+ private selectors;
79
+ private installData;
80
+ private permissions;
81
+ private hooks;
82
+ private nonce;
83
+ private hasAssociatedExecHooks;
84
+ constructor(client: ModularAccountV2Client);
85
+ configure({ key, entityId, nonce, selectors, hooks, }: {
86
+ key: Key;
87
+ entityId: number;
88
+ nonce: bigint;
89
+ selectors?: Hex[];
90
+ hooks?: Hook[];
91
+ }): this;
92
+ addSelector({ selector }: {
93
+ selector: Hex;
94
+ }): this;
95
+ addPermission({ permission }: {
96
+ permission: Permission;
97
+ }): this;
98
+ addPermissions({ permissions }: {
99
+ permissions: Permission[];
100
+ }): this;
101
+ compileDeferred({ deadline, }: {
102
+ deadline: number;
103
+ uoValidationEntityId: number;
104
+ uoIsGlobalValidation: boolean;
105
+ }): Promise<{
106
+ typedData: DeferredActionTypedData;
107
+ fullPreSignatureDeferredActionDigest: Hex;
108
+ }>;
109
+ compileRaw(): Promise<Hex>;
110
+ compileInstallArgs(): Promise<InstallValidationParams>;
111
+ private validateConfiguration;
112
+ private translatePermissions;
113
+ private addHooks;
114
+ }
115
+ export {};
@@ -0,0 +1,485 @@
1
+ import { toHex, zeroAddress } from "viem";
2
+ import { HookType, } from "./actions/common/types.js";
3
+ import { installValidationActions, } from "./actions/install-validation/installValidation.js";
4
+ import { deferralActions, } from "./actions/deferralActions.js";
5
+ import { NativeTokenLimitModule } from "./modules/native-token-limit-module/module.js";
6
+ import { getDefaultAllowlistModuleAddress, getDefaultNativeTokenLimitModuleAddress, getDefaultSingleSignerValidationModuleAddress, getDefaultTimeRangeModuleAddress, } from "./modules/utils.js";
7
+ import { SingleSignerValidationModule } from "./modules/single-signer-validation/module.js";
8
+ import { AllowlistModule } from "./modules/allowlist-module/module.js";
9
+ import { TimeRangeModule } from "./modules/time-range-module/module.js";
10
+ // We use this to offset the ERC20 spend limit entityId
11
+ const HALF_UINT32 = 2147483647;
12
+ const ERC20_APPROVE_SELECTOR = "0x095ea7b3";
13
+ const ERC20_TRANSFER_SELECTOR = "0xa9059cbb";
14
+ const ACCOUNT_EXECUTE_SELECTOR = "0xb61d27f6";
15
+ const ACCOUNT_EXECUTEBATCH_SELECTOR = "0x34fcd5be";
16
+ export var PermissionType;
17
+ (function (PermissionType) {
18
+ PermissionType["NATIVE_TOKEN_TRANSFER"] = "native-token-transfer";
19
+ PermissionType["ERC20_TOKEN_TRANSFER"] = "erc20-token-transfer";
20
+ // ERC721_TOKEN_TRANSFER = "erc721-token-transfer", //Unimplemented
21
+ // ERC1155_TOKEN_TRANSFER = "erc1155-token-transfer", //Unimplemented
22
+ PermissionType["GAS_LIMIT"] = "gas-limit";
23
+ // CALL_LIMIT = "call-limit", //Unimplemented
24
+ // RATE_LIMIT = "rate-limit", //Unimplemented
25
+ PermissionType["CONTRACT_ACCESS"] = "contract-access";
26
+ PermissionType["ACCOUNT_FUNCTIONS"] = "account-functions";
27
+ PermissionType["FUNCTIONS_ON_ALL_CONTRACTS"] = "functions-on-all-contracts";
28
+ PermissionType["FUNCTIONS_ON_CONTRACT"] = "functions-on-contract";
29
+ PermissionType["ROOT"] = "root";
30
+ })(PermissionType || (PermissionType = {}));
31
+ var HookIdentifier;
32
+ (function (HookIdentifier) {
33
+ HookIdentifier[HookIdentifier["NATIVE_TOKEN_TRANSFER"] = 0] = "NATIVE_TOKEN_TRANSFER";
34
+ HookIdentifier[HookIdentifier["ERC20_TOKEN_TRANSFER"] = 1] = "ERC20_TOKEN_TRANSFER";
35
+ HookIdentifier[HookIdentifier["GAS_LIMIT"] = 2] = "GAS_LIMIT";
36
+ HookIdentifier[HookIdentifier["PREVAL_ALLOWLIST"] = 3] = "PREVAL_ALLOWLIST";
37
+ })(HookIdentifier || (HookIdentifier = {}));
38
+ export class PermissionBuilder {
39
+ constructor(client) {
40
+ Object.defineProperty(this, "client", {
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true,
44
+ value: void 0
45
+ });
46
+ Object.defineProperty(this, "validationConfig", {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: {
51
+ moduleAddress: zeroAddress,
52
+ entityId: 0, // uint32
53
+ isGlobal: false,
54
+ isSignatureValidation: false,
55
+ isUserOpValidation: false,
56
+ }
57
+ });
58
+ Object.defineProperty(this, "selectors", {
59
+ enumerable: true,
60
+ configurable: true,
61
+ writable: true,
62
+ value: []
63
+ });
64
+ Object.defineProperty(this, "installData", {
65
+ enumerable: true,
66
+ configurable: true,
67
+ writable: true,
68
+ value: "0x"
69
+ });
70
+ Object.defineProperty(this, "permissions", {
71
+ enumerable: true,
72
+ configurable: true,
73
+ writable: true,
74
+ value: []
75
+ });
76
+ Object.defineProperty(this, "hooks", {
77
+ enumerable: true,
78
+ configurable: true,
79
+ writable: true,
80
+ value: []
81
+ });
82
+ Object.defineProperty(this, "nonce", {
83
+ enumerable: true,
84
+ configurable: true,
85
+ writable: true,
86
+ value: 0n
87
+ });
88
+ Object.defineProperty(this, "hasAssociatedExecHooks", {
89
+ enumerable: true,
90
+ configurable: true,
91
+ writable: true,
92
+ value: false
93
+ });
94
+ this.client = client;
95
+ }
96
+ // Configures the builder
97
+ configure({ key, entityId, nonce, selectors, hooks, }) {
98
+ this.validationConfig = {
99
+ moduleAddress: getDefaultSingleSignerValidationModuleAddress(this.client.chain),
100
+ entityId,
101
+ isUserOpValidation: true,
102
+ isGlobal: false,
103
+ isSignatureValidation: false,
104
+ };
105
+ this.installData = SingleSignerValidationModule.encodeOnInstallData({
106
+ entityId: entityId,
107
+ signer: key.publicKey,
108
+ });
109
+ if (selectors)
110
+ this.selectors = selectors;
111
+ if (hooks)
112
+ this.hooks = hooks;
113
+ this.nonce = nonce;
114
+ return this;
115
+ }
116
+ addSelector({ selector }) {
117
+ this.selectors.push(selector);
118
+ return this;
119
+ }
120
+ addPermission({ permission }) {
121
+ // Check 1: If we're adding root, we can't have any other permissions
122
+ if (permission.type === PermissionType.ROOT) {
123
+ if (this.permissions.length !== 0) {
124
+ throw new Error("PERMISSION: ROOT: Cannot add ROOT permission with other permissions");
125
+ }
126
+ this.permissions.push(permission);
127
+ // Set isGlobal to true
128
+ this.validationConfig.isGlobal = true;
129
+ return this;
130
+ }
131
+ // Check 2: If the permission is NOT ROOT (guaranteed), ensure there is no ROOT permission set
132
+ // Will resolve to undefined if ROOT is not found
133
+ // NOTE: Technically this could be replaced by checking permissions[0] since it should not be possible
134
+ // to have >1 permission with root among them
135
+ if (this.permissions.find((p) => p.type === PermissionType.ROOT)) {
136
+ throw new Error(`PERMISSION: ${permission.type} => Cannot add permissions with ROOT enabled`);
137
+ }
138
+ // Check 3: If the permission is either CONTRACT_ACCESS or FUNCTIONS_ON_CONTRACT, ensure it doesn't collide with another like it.
139
+ if (permission.type === PermissionType.CONTRACT_ACCESS ||
140
+ permission.type === PermissionType.FUNCTIONS_ON_CONTRACT) {
141
+ // Check 3.1: address must not be the account address, or the user should use the ACCOUNT_FUNCTIONS permission
142
+ if (permission.data.address === this.client.account.address) {
143
+ throw new Error(`PERMISSION: ${permission.type} => Account address as target, use ACCOUNT_FUNCTIONS for account address`);
144
+ }
145
+ // Check 3.2: there must not be an existing permission with this address as a target
146
+ const targetAddress = permission.data.address;
147
+ const existingPermissionWithSameAddress = this.permissions.find((p) => (p.type === PermissionType.CONTRACT_ACCESS &&
148
+ "address" in p.data &&
149
+ p.data.address === targetAddress) ||
150
+ (p.type === PermissionType.FUNCTIONS_ON_CONTRACT &&
151
+ "address" in p.data &&
152
+ p.data.address === targetAddress));
153
+ if (existingPermissionWithSameAddress) {
154
+ throw new Error(`PERMISSION: ${permission.type} => Address ${targetAddress} already has a permission. Cannot add multiple CONTRACT_ACCESS or FUNCTIONS_ON_CONTRACT permissions for the same target address.`);
155
+ }
156
+ }
157
+ // Check 4: If the permission is ACCOUNT_FUNCTIONS, add selectors
158
+ if (permission.type === PermissionType.ACCOUNT_FUNCTIONS) {
159
+ this.selectors = [...this.selectors, ...permission.data.functions];
160
+ return this;
161
+ }
162
+ this.permissions.push(permission);
163
+ return this;
164
+ }
165
+ addPermissions({ permissions }) {
166
+ // We could validate each permission here, but for simplicity we'll just add them
167
+ // A better approach would be to call addPermission for each one
168
+ permissions.forEach((permission) => {
169
+ this.addPermission({ permission });
170
+ });
171
+ return this;
172
+ }
173
+ // Use for building deferred action typed data to sign
174
+ async compileDeferred({ deadline, }) {
175
+ // Need to remove this because compileRaw may add selectors
176
+ // this.validateConfiguration();
177
+ // Add time range module hook via expiry
178
+ if (deadline !== 0) {
179
+ if (deadline < Date.now() / 1000) {
180
+ throw new Error(`PERMISSION: compileDeferred(): Deadline ${deadline} cannot be before now (${Date.now() / 1000})`);
181
+ }
182
+ this.hooks.push(TimeRangeModule.buildHook({
183
+ entityId: this.validationConfig.entityId, // will be timerange entityId
184
+ validUntil: deadline,
185
+ validAfter: 0,
186
+ }, getDefaultTimeRangeModuleAddress(this.client.chain)));
187
+ }
188
+ const installValidationCall = await this.compileRaw();
189
+ const { typedData } = await deferralActions(this.client).createDeferredActionTypedDataObject({
190
+ callData: installValidationCall,
191
+ deadline: deadline,
192
+ nonce: this.nonce,
193
+ });
194
+ const preSignatureDigest = deferralActions(this.client).buildPreSignatureDeferredActionDigest({ typedData });
195
+ // Encode additional information to build the full pre-signature digest
196
+ const fullPreSignatureDeferredActionDigest = `0x00${this.hasAssociatedExecHooks ? "01" : "00"}${toHex(this.nonce, {
197
+ size: 32,
198
+ }).slice(2)}${preSignatureDigest.slice(2)}`;
199
+ return {
200
+ typedData,
201
+ fullPreSignatureDeferredActionDigest,
202
+ };
203
+ }
204
+ // Use for direct `installValidation()` low-level calls (maybe useless)
205
+ async compileRaw() {
206
+ // Translate all permissions into raw hooks if >0
207
+ if (this.permissions.length > 0) {
208
+ const rawHooks = this.translatePermissions(this.validationConfig.entityId);
209
+ // Add the translated permissions as hooks
210
+ this.addHooks(rawHooks);
211
+ }
212
+ this.validateConfiguration();
213
+ return await installValidationActions(this.client).encodeInstallValidation({
214
+ validationConfig: this.validationConfig,
215
+ selectors: this.selectors,
216
+ installData: this.installData,
217
+ hooks: this.hooks,
218
+ account: this.client.account,
219
+ });
220
+ }
221
+ // Use for compiling args to installValidation
222
+ async compileInstallArgs() {
223
+ this.validateConfiguration();
224
+ return {
225
+ validationConfig: this.validationConfig,
226
+ selectors: this.selectors,
227
+ installData: this.installData,
228
+ hooks: this.hooks,
229
+ account: this.client.account,
230
+ };
231
+ }
232
+ validateConfiguration() {
233
+ if (this.validationConfig.isGlobal === false &&
234
+ this.selectors.length === 0) {
235
+ throw new Error("Validation config unset, use permissionBuilder.configure(...)");
236
+ }
237
+ }
238
+ // Used to translate consolidated permissions into raw unencoded hooks
239
+ // Note entityId will be a member object later
240
+ translatePermissions(entityId) {
241
+ const rawHooks = {
242
+ [HookIdentifier.NATIVE_TOKEN_TRANSFER]: undefined,
243
+ [HookIdentifier.ERC20_TOKEN_TRANSFER]: undefined,
244
+ [HookIdentifier.GAS_LIMIT]: undefined,
245
+ [HookIdentifier.PREVAL_ALLOWLIST]: undefined,
246
+ };
247
+ this.permissions.forEach((permission) => {
248
+ switch (permission.type) {
249
+ case PermissionType.NATIVE_TOKEN_TRANSFER:
250
+ // Should never be added twice, check is on addPermission(s) too
251
+ if (rawHooks[HookIdentifier.NATIVE_TOKEN_TRANSFER] !== undefined) {
252
+ throw new Error("PERMISSION: NATIVE_TOKEN_TRANSFER => Must have at most ONE native token transfer permission");
253
+ }
254
+ rawHooks[HookIdentifier.NATIVE_TOKEN_TRANSFER] = {
255
+ hookConfig: {
256
+ address: getDefaultNativeTokenLimitModuleAddress(this.client.chain),
257
+ entityId,
258
+ hookType: HookType.EXECUTION,
259
+ hasPreHooks: true,
260
+ hasPostHooks: false,
261
+ },
262
+ initData: {
263
+ entityId,
264
+ spendLimit: BigInt(permission.data.allowance),
265
+ },
266
+ };
267
+ this.hasAssociatedExecHooks = true;
268
+ break;
269
+ case PermissionType.ERC20_TOKEN_TRANSFER:
270
+ if (permission.data.address === zeroAddress) {
271
+ throw new Error("PERMISSION: ERC20_TOKEN_TRANSFER => Zero address provided");
272
+ }
273
+ rawHooks[HookIdentifier.ERC20_TOKEN_TRANSFER] = {
274
+ hookConfig: {
275
+ address: getDefaultAllowlistModuleAddress(this.client.chain),
276
+ entityId: entityId + HALF_UINT32,
277
+ hookType: HookType.EXECUTION,
278
+ hasPreHooks: true,
279
+ hasPostHooks: false,
280
+ },
281
+ initData: {
282
+ entityId: entityId + HALF_UINT32,
283
+ inputs: [
284
+ // Add previous inputs if they exist
285
+ ...(rawHooks[HookIdentifier.ERC20_TOKEN_TRANSFER]?.initData
286
+ .inputs || []),
287
+ {
288
+ target: permission.data.address,
289
+ hasSelectorAllowlist: false,
290
+ hasERC20SpendLimit: true,
291
+ erc20SpendLimit: BigInt(permission.data.allowance),
292
+ selectors: [],
293
+ },
294
+ ],
295
+ },
296
+ };
297
+ this.hasAssociatedExecHooks = true;
298
+ // Also allow `approve` and `transfer` for the erc20
299
+ rawHooks[HookIdentifier.PREVAL_ALLOWLIST] = {
300
+ hookConfig: {
301
+ address: getDefaultAllowlistModuleAddress(this.client.chain),
302
+ entityId,
303
+ hookType: HookType.VALIDATION,
304
+ hasPreHooks: true,
305
+ hasPostHooks: false,
306
+ },
307
+ initData: {
308
+ entityId,
309
+ inputs: [
310
+ // Add previous inputs if they exist
311
+ ...(rawHooks[HookIdentifier.PREVAL_ALLOWLIST]?.initData
312
+ .inputs || []),
313
+ {
314
+ target: permission.data.address,
315
+ hasSelectorAllowlist: true,
316
+ hasERC20SpendLimit: false,
317
+ erc20SpendLimit: 0n,
318
+ selectors: [ERC20_APPROVE_SELECTOR, ERC20_TRANSFER_SELECTOR], // approve, transfer
319
+ },
320
+ ],
321
+ },
322
+ };
323
+ break;
324
+ case PermissionType.GAS_LIMIT:
325
+ // Should only ever be added once, check is also on addPermission(s)
326
+ if (rawHooks[HookIdentifier.GAS_LIMIT] !== undefined) {
327
+ throw new Error("PERMISSION: GAS_LIMIT => Must have at most ONE gas limit permission");
328
+ }
329
+ rawHooks[HookIdentifier.GAS_LIMIT] = {
330
+ hookConfig: {
331
+ address: getDefaultNativeTokenLimitModuleAddress(this.client.chain),
332
+ entityId,
333
+ hookType: HookType.VALIDATION,
334
+ hasPreHooks: true,
335
+ hasPostHooks: false,
336
+ },
337
+ initData: {
338
+ entityId,
339
+ spendLimit: BigInt(permission.data.limit),
340
+ },
341
+ };
342
+ break;
343
+ case PermissionType.CONTRACT_ACCESS:
344
+ if (permission.data.address === zeroAddress) {
345
+ throw new Error("PERMISSION: CONTRACT_ACCESS => Zero address provided");
346
+ }
347
+ rawHooks[HookIdentifier.PREVAL_ALLOWLIST] = {
348
+ hookConfig: {
349
+ address: getDefaultAllowlistModuleAddress(this.client.chain),
350
+ entityId,
351
+ hookType: HookType.VALIDATION,
352
+ hasPreHooks: true,
353
+ hasPostHooks: false,
354
+ },
355
+ initData: {
356
+ entityId,
357
+ inputs: [
358
+ // Add previous inputs if they exist
359
+ ...(rawHooks[HookIdentifier.PREVAL_ALLOWLIST]?.initData
360
+ .inputs || []),
361
+ {
362
+ target: permission.data.address,
363
+ hasSelectorAllowlist: false,
364
+ hasERC20SpendLimit: false,
365
+ erc20SpendLimit: 0n,
366
+ selectors: [],
367
+ },
368
+ ],
369
+ },
370
+ };
371
+ break;
372
+ case PermissionType.ACCOUNT_FUNCTIONS:
373
+ if (permission.data.functions.length === 0) {
374
+ throw new Error("PERMISSION: ACCOUNT_FUNCTION => No functions provided"); // should be in add perm
375
+ }
376
+ break;
377
+ case PermissionType.FUNCTIONS_ON_ALL_CONTRACTS:
378
+ if (permission.data.functions.length === 0) {
379
+ throw new Error("PERMISSION: FUNCTIONS_ON_ALL_CONTRACTS => No functions provided");
380
+ }
381
+ rawHooks[HookIdentifier.PREVAL_ALLOWLIST] = {
382
+ hookConfig: {
383
+ address: getDefaultAllowlistModuleAddress(this.client.chain),
384
+ entityId,
385
+ hookType: HookType.VALIDATION,
386
+ hasPreHooks: true,
387
+ hasPostHooks: false,
388
+ },
389
+ initData: {
390
+ entityId,
391
+ inputs: [
392
+ // Add previous inputs if they exist
393
+ ...(rawHooks[HookIdentifier.PREVAL_ALLOWLIST]?.initData
394
+ .inputs || []),
395
+ {
396
+ target: zeroAddress,
397
+ hasSelectorAllowlist: false,
398
+ hasERC20SpendLimit: false,
399
+ erc20SpendLimit: 0n,
400
+ selectors: permission.data.functions,
401
+ },
402
+ ],
403
+ },
404
+ };
405
+ break;
406
+ case PermissionType.FUNCTIONS_ON_CONTRACT:
407
+ if (permission.data.functions.length === 0) {
408
+ throw new Error("PERMISSION: FUNCTIONS_ON_CONTRACT => No functions provided");
409
+ }
410
+ if (permission.data.address === zeroAddress) {
411
+ throw new Error("PERMISSION: FUNCTIONS_ON_CONTRACT => Zero address provided");
412
+ }
413
+ rawHooks[HookIdentifier.PREVAL_ALLOWLIST] = {
414
+ hookConfig: {
415
+ address: getDefaultAllowlistModuleAddress(this.client.chain),
416
+ entityId,
417
+ hookType: HookType.VALIDATION,
418
+ hasPreHooks: true,
419
+ hasPostHooks: false,
420
+ },
421
+ initData: {
422
+ entityId,
423
+ inputs: [
424
+ // Add previous inputs if they exist
425
+ ...(rawHooks[HookIdentifier.PREVAL_ALLOWLIST]?.initData
426
+ .inputs || []),
427
+ {
428
+ target: permission.data.address,
429
+ hasSelectorAllowlist: true,
430
+ hasERC20SpendLimit: false,
431
+ erc20SpendLimit: 0n,
432
+ selectors: permission.data.functions,
433
+ },
434
+ ],
435
+ },
436
+ };
437
+ break;
438
+ case PermissionType.ROOT:
439
+ // Root permission handled in addPermission
440
+ break;
441
+ default:
442
+ throw new Error(`Unsupported permission type: ${permission.type}`);
443
+ }
444
+ // isGlobal guaranteed to be false since it's only set with root permissions,
445
+ // we must add access to execute & executeBatch if there's a preVal allowlist hook set.
446
+ if (rawHooks[HookIdentifier.PREVAL_ALLOWLIST] !== undefined) {
447
+ const selectorsToAdd = [
448
+ ACCOUNT_EXECUTE_SELECTOR,
449
+ ACCOUNT_EXECUTEBATCH_SELECTOR,
450
+ ]; // execute, executeBatch
451
+ // Only add the selectors if they aren't already in this.selectors
452
+ const newSelectors = selectorsToAdd.filter((selector) => !this.selectors.includes(selector));
453
+ this.selectors = [...this.selectors, ...newSelectors];
454
+ }
455
+ });
456
+ return rawHooks;
457
+ }
458
+ addHooks(rawHooks) {
459
+ if (rawHooks[HookIdentifier.NATIVE_TOKEN_TRANSFER]) {
460
+ this.hooks.push({
461
+ hookConfig: rawHooks[HookIdentifier.NATIVE_TOKEN_TRANSFER].hookConfig,
462
+ initData: NativeTokenLimitModule.encodeOnInstallData(rawHooks[HookIdentifier.NATIVE_TOKEN_TRANSFER].initData),
463
+ });
464
+ }
465
+ if (rawHooks[HookIdentifier.ERC20_TOKEN_TRANSFER]) {
466
+ this.hooks.push({
467
+ hookConfig: rawHooks[HookIdentifier.ERC20_TOKEN_TRANSFER].hookConfig,
468
+ initData: AllowlistModule.encodeOnInstallData(rawHooks[HookIdentifier.ERC20_TOKEN_TRANSFER].initData),
469
+ });
470
+ }
471
+ if (rawHooks[HookIdentifier.GAS_LIMIT]) {
472
+ this.hooks.push({
473
+ hookConfig: rawHooks[HookIdentifier.GAS_LIMIT].hookConfig,
474
+ initData: NativeTokenLimitModule.encodeOnInstallData(rawHooks[HookIdentifier.GAS_LIMIT].initData),
475
+ });
476
+ }
477
+ if (rawHooks[HookIdentifier.PREVAL_ALLOWLIST]) {
478
+ this.hooks.push({
479
+ hookConfig: rawHooks[HookIdentifier.PREVAL_ALLOWLIST].hookConfig,
480
+ initData: AllowlistModule.encodeOnInstallData(rawHooks[HookIdentifier.PREVAL_ALLOWLIST].initData),
481
+ });
482
+ }
483
+ }
484
+ }
485
+ //# sourceMappingURL=permissionBuilder.js.map