From d94699a0331a3cd12774fb882d122961a34a2895 Mon Sep 17 00:00:00 2001 From: howydev <132113803+howydev@users.noreply.github.com> Date: Wed, 18 Dec 2024 01:22:30 -0500 Subject: [PATCH] feat: add calldata wrapping to install+uninstallvalidation --- .../src/ma-v2/account/account.ts | 25 +++++--- .../install-validation/installValidation.ts | 61 +++++++++++-------- .../src/ma-v2/client/client.test.ts | 5 +- .../src/ma-v2/client/client.ts | 19 ++++-- 4 files changed, 69 insertions(+), 41 deletions(-) diff --git a/account-kit/smart-contracts/src/ma-v2/account/account.ts b/account-kit/smart-contracts/src/ma-v2/account/account.ts index 71486ee75d..783bdca96c 100644 --- a/account-kit/smart-contracts/src/ma-v2/account/account.ts +++ b/account-kit/smart-contracts/src/ma-v2/account/account.ts @@ -36,6 +36,10 @@ const executeUserOpSelector: Hex = "0x8DD7712F"; export const DEFAULT_OWNER_ENTITY_ID = 0; +export type CalldataEncoder = { + encodeCallData: (callData: Hex) => Promise; +}; + export type ExecutionDataView = { module: Address; skipRuntimeValidation: boolean; @@ -56,13 +60,15 @@ export type ValidationDataParams = { }; export type SMAV2Account< - TSigner extends SmartAccountSigner = SmartAccountSigner -> = SmartContractAccountWithSigner<"SMAV2Account", TSigner, "0.7.0"> & { - getExecutionData: (selector: Hex) => Promise; - getValidationData: ( - args: ValidationDataParams - ) => Promise; -}; + TSigner extends SmartAccountSigner = SmartAccountSigner, + TCalldataEncoder extends CalldataEncoder = CalldataEncoder +> = SmartContractAccountWithSigner<"SMAV2Account", TSigner, "0.7.0"> & + TCalldataEncoder & { + getExecutionData: (selector: Hex) => Promise; + getValidationData: ( + args: ValidationDataParams + ) => Promise; + }; export type CreateSMAV2AccountParams< TTransport extends Transport = Transport, @@ -83,8 +89,8 @@ export type CreateSMAV2AccountParams< entityId: number; } | { - isGlobalValidation: never; - entityId: never; + isGlobalValidation?: never; + entityId?: never; } ); @@ -258,5 +264,6 @@ export async function createSMAV2Account( getValidationData, encodeExecute, encodeBatchExecute, + encodeCallData, }; } diff --git a/account-kit/smart-contracts/src/ma-v2/actions/install-validation/installValidation.ts b/account-kit/smart-contracts/src/ma-v2/actions/install-validation/installValidation.ts index f2d77d386c..d76b837cba 100644 --- a/account-kit/smart-contracts/src/ma-v2/actions/install-validation/installValidation.ts +++ b/account-kit/smart-contracts/src/ma-v2/actions/install-validation/installValidation.ts @@ -6,9 +6,9 @@ import { type GetAccountParameter, type GetEntryPointFromAccount, type SendUserOperationResult, - type SmartContractAccount, type SmartAccountClient, type UserOperationOverridesParameter, + type SmartContractAccount, } from "@aa-sdk/core"; import { type Address, @@ -26,6 +26,7 @@ import { serializeHookConfig, serializeModuleEntity, } from "../common/utils.js"; +import type { CalldataEncoder } from "../../account/account.js"; export type InstallValidationParams< TAccount extends SmartContractAccount | undefined = @@ -72,7 +73,7 @@ export const installValidationActions: < TChain extends Chain | undefined = Chain | undefined, TAccount extends SmartContractAccount = SmartContractAccount >( - client: SmartAccountClient + client: SmartAccountClient & CalldataEncoder ) => InstallValidationActions = (client) => ({ installValidation: async ({ validationConfig, @@ -98,18 +99,22 @@ export const installValidationActions: < throw new EntityIdOverrideError(); } - const callData = encodeFunctionData({ - abi: semiModularAccountBytecodeAbi, - functionName: "installValidation", - args: [ - serializeValidationConfig(validationConfig), - selectors, - installData, - hooks.map((hook: { hookConfig: HookConfig; initData: Hex }) => - concatHex([serializeHookConfig(hook.hookConfig), hook.initData]) - ), - ], - }); + const { encodeCallData } = client; + + const callData = await encodeCallData( + encodeFunctionData({ + abi: semiModularAccountBytecodeAbi, + functionName: "installValidation", + args: [ + serializeValidationConfig(validationConfig), + selectors, + installData, + hooks.map((hook: { hookConfig: HookConfig; initData: Hex }) => + concatHex([serializeHookConfig(hook.hookConfig), hook.initData]) + ), + ], + }) + ); return client.sendUserOperation({ uo: callData, @@ -138,18 +143,22 @@ export const installValidationActions: < ); } - const callData = encodeFunctionData({ - abi: semiModularAccountBytecodeAbi, - functionName: "uninstallValidation", - args: [ - serializeModuleEntity({ - moduleAddress, - entityId, - }), - uninstallData, - hookUninstallDatas, - ], - }); + const { encodeCallData } = client; + + const callData = await encodeCallData( + encodeFunctionData({ + abi: semiModularAccountBytecodeAbi, + functionName: "uninstallValidation", + args: [ + serializeModuleEntity({ + moduleAddress, + entityId, + }), + uninstallData, + hookUninstallDatas, + ], + }) + ); return client.sendUserOperation({ uo: callData, diff --git a/account-kit/smart-contracts/src/ma-v2/client/client.test.ts b/account-kit/smart-contracts/src/ma-v2/client/client.test.ts index 1d89805cdb..2d2bfd4e5e 100644 --- a/account-kit/smart-contracts/src/ma-v2/client/client.test.ts +++ b/account-kit/smart-contracts/src/ma-v2/client/client.test.ts @@ -13,7 +13,8 @@ import { SingleSignerValidationModule } from "../modules/single-signer-validatio describe("MA v2 Tests", async () => { const instance = local070Instance; - let client: ReturnType; + let client: ReturnType & + ReturnType; beforeAll(async () => { client = instance.getClient().extend(publicActions); @@ -165,7 +166,7 @@ describe("MA v2 Tests", async () => { signer: sessionKey, transport: custom(instance.getClient()), accountAddress: provider.getAddress(), - entityId: 1n, + entityId: 1, isGlobalValidation: true, }); diff --git a/account-kit/smart-contracts/src/ma-v2/client/client.ts b/account-kit/smart-contracts/src/ma-v2/client/client.ts index f2e3b36335..44685e0ead 100644 --- a/account-kit/smart-contracts/src/ma-v2/client/client.ts +++ b/account-kit/smart-contracts/src/ma-v2/client/client.ts @@ -8,6 +8,7 @@ import { type Chain, type CustomTransport, type Transport } from "viem"; import { createSMAV2Account, + type CalldataEncoder, type CreateSMAV2AccountParams, type SMAV2Account, } from "../account/account.js"; @@ -24,10 +25,13 @@ export type CreateSMAV2AccountClientParams< export function createSMAV2AccountClient< TChain extends Chain = Chain, - TSigner extends SmartAccountSigner = SmartAccountSigner + TSigner extends SmartAccountSigner = SmartAccountSigner, + TCalldataEncoder extends CalldataEncoder = CalldataEncoder >( args: CreateSMAV2AccountClientParams -): Promise>>; +): Promise< + SmartAccountClient & TCalldataEncoder +>; /** * Creates a MAv2 account client using the provided configuration parameters. @@ -60,13 +64,20 @@ export function createSMAV2AccountClient< */ export async function createSMAV2AccountClient({ ...config -}: CreateSMAV2AccountClientParams): Promise { +}: CreateSMAV2AccountClientParams): Promise< + SmartAccountClient & CalldataEncoder +> { const maV2Account = await createSMAV2Account({ ...config, }); - return createSmartAccountClient({ + const client = createSmartAccountClient({ ...config, account: maV2Account, }); + + return { + ...client, + encodeCallData: maV2Account.encodeCallData, + }; }