From a1778c25bd7fb5abf1d4094da4ea5f15a440a884 Mon Sep 17 00:00:00 2001 From: joepegler Date: Wed, 13 Nov 2024 13:21:15 +0000 Subject: [PATCH] chore: distributed session keys (#114) --- CHANGELOG.md | 6 + package.json | 2 +- src/sdk/account/utils/Constants.ts | 2 + .../clients/createNexusSessionClient.test.ts | 18 +- src/sdk/clients/createNexusSessionClient.ts | 4 +- .../decorators/dan/decorators/index.ts | 10 +- .../modules/smartSessionsValidator/Types.ts | 4 +- .../decorators/index.ts | 28 ++- .../smartSessions.decorators.test.ts | 2 +- .../decorators/useDistributedPermission.ts | 113 +++++++++++ .../decorators/usePermission.ts | 24 +-- .../toSmartSessionsValidator.dan.dx.test.ts | 191 ++++++++++++++++++ .../toSmartSessionsValidator.dx.test.ts | 10 +- .../toSmartSessionsValidator.test.ts | 9 +- .../toSmartSessionsValidator.ts | 20 +- ...oSmartSessionsValidator.uni.policy.test.ts | 15 +- src/sdk/modules/utils/Helpers.ts | 4 +- 17 files changed, 390 insertions(+), 72 deletions(-) create mode 100644 src/sdk/modules/smartSessionsValidator/decorators/useDistributedPermission.ts create mode 100644 src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dan.dx.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 494f93950..4dc51bd59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # @biconomy/sdk +## 0.0.10 + +### Patch Changes + +- Added Distributed Session Keys w/ Ownable & Session examples + ## 0.0.9 ### Patch Changes diff --git a/package.json b/package.json index b07e0e6b2..339f0e220 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@biconomy/sdk", - "version": "0.0.9", + "version": "0.0.10", "author": "Biconomy", "repository": "github:bcnmy/sdk", "main": "./dist/_cjs/index.js", diff --git a/src/sdk/account/utils/Constants.ts b/src/sdk/account/utils/Constants.ts index c9d17dd58..73e3e5a15 100644 --- a/src/sdk/account/utils/Constants.ts +++ b/src/sdk/account/utils/Constants.ts @@ -21,6 +21,8 @@ export const DefaultGasLimit = { } export const ERROR_MESSAGES = { + KEY_GEN_DATA_NOT_FOUND: "Key generation data is not available", + SIGNATURE_NOT_FOUND: "Signature not found from Dan", FAILED_COMPUTE_ACCOUNT_ADDRESS: "Failed to compute account address. Possible reasons:\n" + "- The factory contract does not have the function 'computeAccountAddress'\n" + diff --git a/src/sdk/clients/createNexusSessionClient.test.ts b/src/sdk/clients/createNexusSessionClient.test.ts index dfcb23a7f..ecf869f93 100644 --- a/src/sdk/clients/createNexusSessionClient.test.ts +++ b/src/sdk/clients/createNexusSessionClient.test.ts @@ -168,7 +168,7 @@ describe("nexus.session.client", async () => { account: smartSessionNexusClient.account, signer: sessionKeyAccount, moduleData: { - permissionId: cachedPermissionId + permissionIds: [cachedPermissionId] } }) @@ -177,11 +177,10 @@ describe("nexus.session.client", async () => { ) const userOpHash = await useSmartSessionNexusClient.usePermission({ - actions: [ + calls: [ { - target: testAddresses.Counter, - value: 0n, - callData: encodeFunctionData({ + to: testAddresses.Counter, + data: encodeFunctionData({ abi: CounterAbi, functionName: "incrementNumber", args: [] @@ -212,7 +211,7 @@ describe("nexus.session.client", async () => { account: nexusClient.account, signer: sessionKeyAccount, moduleData: { - permissionId: cachedPermissionId + permissionIds: [cachedPermissionId] } }) @@ -246,11 +245,10 @@ describe("nexus.session.client", async () => { expect( useSmartSessionNexusClient.usePermission({ - actions: [ + calls: [ { - target: testAddresses.Counter, - value: 0n, - callData: encodeFunctionData({ + to: testAddresses.Counter, + data: encodeFunctionData({ abi: CounterAbi, functionName: "decrementNumber" }) diff --git a/src/sdk/clients/createNexusSessionClient.ts b/src/sdk/clients/createNexusSessionClient.ts index fde3c0462..01042e331 100644 --- a/src/sdk/clients/createNexusSessionClient.ts +++ b/src/sdk/clients/createNexusSessionClient.ts @@ -4,6 +4,4 @@ import { type NexusClientConfig, createNexusClient } from "./createNexusClient" export type NexusSessionClientConfig = NexusClientConfig & { accountAddress: Address } -export const createNexusSessionClient = async ( - parameters: NexusSessionClientConfig -) => await createNexusClient({ ...parameters }) +export const createNexusSessionClient = createNexusClient diff --git a/src/sdk/clients/decorators/dan/decorators/index.ts b/src/sdk/clients/decorators/dan/decorators/index.ts index 30943e2ff..0be5d741b 100644 --- a/src/sdk/clients/decorators/dan/decorators/index.ts +++ b/src/sdk/clients/decorators/dan/decorators/index.ts @@ -38,10 +38,8 @@ export function danActions() { chain extends Chain | undefined >( client: Client - ): DanActions => { - return { - keyGen: (args) => keyGen(client, args), - sigGen: (parameters) => sigGen(client, parameters) - } - } + ): DanActions => ({ + keyGen: (args) => keyGen(client, args), + sigGen: (parameters) => sigGen(client, parameters) + }) } diff --git a/src/sdk/modules/smartSessionsValidator/Types.ts b/src/sdk/modules/smartSessionsValidator/Types.ts index 34669df5b..c650ccf06 100644 --- a/src/sdk/modules/smartSessionsValidator/Types.ts +++ b/src/sdk/modules/smartSessionsValidator/Types.ts @@ -55,13 +55,15 @@ export type SmartSessionModeType = */ export type UsePermissionModuleData = { /** The permission ID for the session. */ - permissionId: Hex + permissionIds: Hex[] /** The mode of the smart session. */ mode?: SmartSessionModeType /** Data for enabling the session. */ enableSessionData?: EnableSessionData /** Key generation data for the session. */ keyGenData?: KeyGenData + /** The index of the permission ID to use for the session. Defaults to 0. */ + permissionIdIndex?: number } type OptionalSessionKeyData = OneOf< diff --git a/src/sdk/modules/smartSessionsValidator/decorators/index.ts b/src/sdk/modules/smartSessionsValidator/decorators/index.ts index 93592e890..bbbec6906 100644 --- a/src/sdk/modules/smartSessionsValidator/decorators/index.ts +++ b/src/sdk/modules/smartSessionsValidator/decorators/index.ts @@ -1,13 +1,19 @@ import type { Chain, Client, Hash, Transport } from "viem" +import { danActions } from "../../../clients/decorators/dan/decorators" import type { ModularSmartAccount, Module } from "../../utils/Types" import type { GrantPermissionResponse } from "../Types" +import type { SmartSessionModule } from "../toSmartSessionsValidator" import { type GrantPermissionParameters, grantPermission } from "./grantPermission" import { type TrustAttestersParameters, trustAttesters } from "./trustAttesters" +import { + type DanClient, + type UseDistributedPermissionParameters, + useDistributedPermission +} from "./useDistributedPermission" import { type UsePermissionParameters, usePermission } from "./usePermission" - /** * Defines the shape of actions available for creating smart sessions. * @@ -54,6 +60,15 @@ export type SmartSessionUseActions< usePermission: ( args: UsePermissionParameters ) => Promise + /** + * Uses a session to perform multiple actions. + * + * @param args - Parameters for using a session. + * @returns A promise that resolves to the transaction hash. + */ + useDistributedPermission: ( + args: UseDistributedPermissionParameters + ) => Promise } /** @@ -79,13 +94,19 @@ export function smartSessionCreateActions(_: Module) { * @param smartSessionsModule - The smart sessions module to be set on the client's account. * @returns A function that takes a client and returns SmartSessionUseActions. */ -export function smartSessionUseActions(smartSessionsModule: Module) { +export function smartSessionUseActions( + smartSessionsModule: SmartSessionModule +) { return ( client: Client ): SmartSessionUseActions => { client?.account?.setModule(smartSessionsModule) return { - usePermission: (args) => usePermission(client, args) + usePermission: (args) => usePermission(client, args), + useDistributedPermission: (args) => { + const danClient = client.extend(danActions()) as unknown as DanClient + return useDistributedPermission(danClient, args) + } } } } @@ -93,3 +114,4 @@ export function smartSessionUseActions(smartSessionsModule: Module) { export * from "./grantPermission" export * from "./trustAttesters" export * from "./usePermission" +export * from "./useDistributedPermission" diff --git a/src/sdk/modules/smartSessionsValidator/decorators/smartSessions.decorators.test.ts b/src/sdk/modules/smartSessionsValidator/decorators/smartSessions.decorators.test.ts index ee36b553a..d9445b028 100644 --- a/src/sdk/modules/smartSessionsValidator/decorators/smartSessions.decorators.test.ts +++ b/src/sdk/modules/smartSessionsValidator/decorators/smartSessions.decorators.test.ts @@ -84,7 +84,7 @@ describe("modules.smartSessions.decorators", async () => { account: nexusClient.account, signer: sessionKeyAccount, moduleData: { - permissionId: "0x" + permissionIds: [] } }) diff --git a/src/sdk/modules/smartSessionsValidator/decorators/useDistributedPermission.ts b/src/sdk/modules/smartSessionsValidator/decorators/useDistributedPermission.ts new file mode 100644 index 000000000..fa82c488a --- /dev/null +++ b/src/sdk/modules/smartSessionsValidator/decorators/useDistributedPermission.ts @@ -0,0 +1,113 @@ +import type { Chain, Client, Hex, Transport } from "viem" +import { type BundlerClient, sendUserOperation } from "viem/account-abstraction" +import { getAction } from "viem/utils" +import { ERROR_MESSAGES } from "../../../account" +import { AccountNotFoundError } from "../../../account/utils/AccountNotFound" +import type { Call } from "../../../account/utils/Types" +import type { Signer } from "../../../account/utils/toSigner" +import type { DanActions } from "../../../clients/decorators/dan/decorators" +import { parseModule } from "../../utils/Helpers" +import type { ModularSmartAccount } from "../../utils/Types" +import type { SmartSessionModule } from "../toSmartSessionsValidator" + +/** + * Parameters for using a smart session to execute actions. + * + * @template TModularSmartAccount - Type of the modular smart account, extending ModularSmartAccount or undefined. + */ +export type UseDistributedPermissionParameters< + TModularSmartAccount extends ModularSmartAccount | undefined +> = { + /** Array of executions to perform in the session. Allows for batch transactions if the session is enabled for multiple actions. */ + calls: Call[] + /** The maximum fee per gas unit the transaction is willing to pay. */ + maxFeePerGas?: bigint + /** The maximum priority fee per gas unit the transaction is willing to pay. */ + maxPriorityFeePerGas?: bigint + /** The nonce of the transaction. If not provided, it will be determined automatically. */ + nonce?: bigint + /** The modular smart account to use for the session. If not provided, the client's account will be used. */ + account?: TModularSmartAccount + /** The signer to use for the session. Defaults to the signer of the client. */ + signer?: Signer +} + +export type DanClient = Client< + Transport, + Chain | undefined, + ModularSmartAccount +> & + DanActions & + BundlerClient + +/** + * Executes actions using a smart session. + * + * This function allows for the execution of one or more actions within an enabled smart session. + * It can handle batch transactions if the session is configured for multiple actions. + * + * @template TModularSmartAccount - Type of the modular smart account, extending ModularSmartAccount or undefined. + * @param client - The client used to interact with the blockchain. + * @param parameters - Parameters for using the session, including actions to execute and optional gas settings. + * @returns A promise that resolves to the hash of the sent user operation. + * + * @throws {AccountNotFoundError} If no account is provided and the client doesn't have an associated account. + * + * @example + * ```typescript + * const result = await useDistributedPermission(nexusClient, { + * calls: [ + * { + * to: '0x1234...', + * data: '0xabcdef...' + * } + * ], + * maxFeePerGas: 1000000000n + * }); + * console.log(`Transaction hash: ${result}`); + * ``` + * + * @remarks + * - Ensure that the session is enabled and has the necessary permissions for the actions being executed. + * - For batch transactions, all actions must be permitted within the same session. + * - The function uses the `sendUserOperation` method, which is specific to account abstraction implementations. + */ +export async function useDistributedPermission< + TModularSmartAccount extends ModularSmartAccount | undefined +>( + client: DanClient, + parameters: UseDistributedPermissionParameters +): Promise { + const { account: account_ = client.account } = parameters + + if (!account_) { + throw new AccountNotFoundError({ + docsPath: "/nexus-client/methods#sendtransaction" + }) + } + + const params = { ...parameters, account: account_ } + + const preppedUserOp = await client.prepareUserOperation(params) + const sessionsModule = parseModule(client) as SmartSessionModule + const keyGenData = sessionsModule?.moduleData?.keyGenData + + if (!keyGenData) { + throw new Error(ERROR_MESSAGES.KEY_GEN_DATA_NOT_FOUND) + } + + const { signature } = await client.sigGen({ ...preppedUserOp, keyGenData }) + + if (!signature) { + throw new Error(ERROR_MESSAGES.SIGNATURE_NOT_FOUND) + } + + const extendedSignature = sessionsModule.sigGen(signature) + + return await getAction( + client, + sendUserOperation, + "sendUserOperation" + // @ts-ignore + )({ ...preppedUserOp, account: account_, signature: extendedSignature }) +} diff --git a/src/sdk/modules/smartSessionsValidator/decorators/usePermission.ts b/src/sdk/modules/smartSessionsValidator/decorators/usePermission.ts index 8e83ef52e..374d3e72c 100644 --- a/src/sdk/modules/smartSessionsValidator/decorators/usePermission.ts +++ b/src/sdk/modules/smartSessionsValidator/decorators/usePermission.ts @@ -2,8 +2,9 @@ import type { Chain, Client, Hex, Transport } from "viem" import { sendUserOperation } from "viem/account-abstraction" import { getAction } from "viem/utils" import { AccountNotFoundError } from "../../../account/utils/AccountNotFound" +import type { Call } from "../../../account/utils/Types" import type { Signer } from "../../../account/utils/toSigner" -import type { Execution, ModularSmartAccount } from "../../utils/Types" +import type { ModularSmartAccount } from "../../utils/Types" /** * Parameters for using a smart session to execute actions. @@ -14,7 +15,7 @@ export type UsePermissionParameters< TModularSmartAccount extends ModularSmartAccount | undefined > = { /** Array of executions to perform in the session. Allows for batch transactions if the session is enabled for multiple actions. */ - actions: Execution[] + calls: Call[] /** The maximum fee per gas unit the transaction is willing to pay. */ maxFeePerGas?: bigint /** The maximum priority fee per gas unit the transaction is willing to pay. */ @@ -43,11 +44,10 @@ export type UsePermissionParameters< * @example * ```typescript * const result = await usePermission(nexusClient, { - * actions: [ + * calls: [ * { - * target: '0x1234...', - * value: 0n, - * callData: '0xabcdef...' + * to: '0x1234...', + * data: '0xabcdef...' * } * ], * maxFeePerGas: 1000000000n @@ -66,7 +66,7 @@ export async function usePermission< client: Client, parameters: UsePermissionParameters ): Promise { - const { account: account_ = client.account, actions, ...rest } = parameters + const { account: account_ = client.account } = parameters if (!account_) { throw new AccountNotFoundError({ @@ -78,12 +78,6 @@ export async function usePermission< client, sendUserOperation, "sendUserOperation" - )({ - ...rest, - calls: actions.map((action) => ({ - to: action.target, - value: BigInt(action.value.toString()), - data: action.callData - })) - }) + // @ts-ignore + )({ ...parameters, account: account_ }) } diff --git a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dan.dx.test.ts b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dan.dx.test.ts new file mode 100644 index 000000000..a2288bf44 --- /dev/null +++ b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dan.dx.test.ts @@ -0,0 +1,191 @@ +import { SmartSessionMode } from "@rhinestone/module-sdk/module" +import { + http, + type Chain, + type Hex, + type LocalAccount, + encodeFunctionData +} from "viem" +import { afterAll, beforeAll, describe, expect, test } from "vitest" +import { CounterAbi } from "../../../test/__contracts/abi/CounterAbi" +import { testAddresses } from "../../../test/callDatas" +import { toNetwork } from "../../../test/testSetup" +import { + fundAndDeployClients, + getTestAccount, + killNetwork, + toTestClient +} from "../../../test/testUtils" +import type { MasterClient, NetworkConfig } from "../../../test/testUtils" +import { + type NexusClient, + createNexusClient +} from "../../clients/createNexusClient" +import { createNexusSessionClient } from "../../clients/createNexusSessionClient" +import { danActions } from "../../clients/decorators/dan" +import type { Module } from "../utils/Types" +import { parse, stringify } from "./Helpers" +import type { CreateSessionDataParams, SessionData } from "./Types" +import { smartSessionCreateActions, smartSessionUseActions } from "./decorators" +import { toSmartSessionsValidator } from "./toSmartSessionsValidator" + +// This test suite demonstrates how to create and use a smart session using Biconomy's Distributed Sessions (DAN). +// Distributed Sessions enhance security and efficiency by storing session keys on Biconomy's Delegated Authorisation Network (DAN), +// providing features like automated transaction processing and reduced exposure of private keys. + +describe("modules.smartSessions.dan.dx", async () => { + let network: NetworkConfig + let chain: Chain + let bundlerUrl: string + + // Test utilities and variables + let testClient: MasterClient + let eoaAccount: LocalAccount + let usersNexusClient: NexusClient + let dappAccount: LocalAccount + let zippedSessionDatum: string + let sessionsModule: Module + + beforeAll(async () => { + // Setup test network and accounts + network = await toNetwork("BASE_SEPOLIA_FORKED") + chain = network.chain + bundlerUrl = network.bundlerUrl + eoaAccount = getTestAccount(0) + dappAccount = getTestAccount(7) + testClient = toTestClient(chain, getTestAccount(5)) + }) + + afterAll(async () => { + // Clean up the network after tests + await killNetwork([network?.rpcPort, network?.bundlerPort]) + }) + + test("should demonstrate creating a smart session using DAN", async () => { + // Initialize the user's Nexus client with DAN actions + usersNexusClient = await createNexusClient({ + signer: eoaAccount, + chain, + transport: http(), + bundlerTransport: http(bundlerUrl) + }) + + const danNexusClient = usersNexusClient.extend(danActions()) + + // Generate a session key using DAN + const keyGenData = await danNexusClient.keyGen() + const sessionPublicKey = keyGenData.sessionPublicKey + + // Fund and deploy the user's smart account + await fundAndDeployClients(testClient, [usersNexusClient]) + + // Initialize the smart sessions validator module + sessionsModule = toSmartSessionsValidator({ + account: usersNexusClient.account, + signer: eoaAccount + }) + + // Install the sessions module + const hash = await usersNexusClient.installModule({ + module: sessionsModule.moduleInitData + }) + + // Extend the Nexus client with smart session creation actions + const nexusSessionClient = usersNexusClient.extend( + smartSessionCreateActions(sessionsModule) + ) + + // Wait for the module installation to complete + const { success: installSuccess } = + await usersNexusClient.waitForUserOperationReceipt({ hash }) + + expect(installSuccess).toBe(true) + + // Define the permissions for the smart session + const sessionRequestedInfo: CreateSessionDataParams[] = [ + { + sessionPublicKey, // Public key of the session stored in DAN + actionPoliciesInfo: [ + { + contractAddress: testAddresses.Counter, + functionSelector: "0x273ea3e3" as Hex // Selector for 'incrementNumber' function + } + ] + } + ] + + // Create the smart session with the specified permissions + const createSessionsResponse = await nexusSessionClient.grantPermission({ + sessionRequestedInfo + }) + + // Wait for the permission grant operation to complete + const { success: sessionCreateSuccess } = + await usersNexusClient.waitForUserOperationReceipt({ + hash: createSessionsResponse.userOpHash + }) + + expect(installSuccess).toBe(sessionCreateSuccess) + + // Prepare the session data to be stored by the dApp. This could be saved in a Database or client side in local storage. + const sessionData: SessionData = { + granter: usersNexusClient.account.address, + sessionPublicKey, + moduleData: { + keyGenData, + permissionIds: createSessionsResponse.permissionIds, + mode: SmartSessionMode.USE + } + } + + // Serialize the session data + zippedSessionDatum = stringify(sessionData) + }, 200000) + + test("should demonstrate using a smart session using DAN", async () => { + // Parse the session data received from the user + const { moduleData, granter } = parse(zippedSessionDatum) + + // Initialize the smart session client's Nexus client + const smartSessionNexusClient = await createNexusSessionClient({ + chain, + accountAddress: granter, + signer: dappAccount, + transport: http(), + bundlerTransport: http(bundlerUrl) + }) + + // Initialize the smart sessions validator module with the received module data + const usePermissionsModule = toSmartSessionsValidator({ + account: smartSessionNexusClient.account, + signer: dappAccount, + moduleData // This includes the keyGenData + }) + + // Extend the Nexus client with smart session usage and dan actions + const danSessionClient = smartSessionNexusClient + .extend(smartSessionUseActions(usePermissionsModule)) + .extend(danActions()) + + // Use the distributed permission to execute a transaction + const userOpHash = await danSessionClient.useDistributedPermission({ + calls: [ + { + to: testAddresses.Counter, + data: encodeFunctionData({ + abi: CounterAbi, + functionName: "incrementNumber" + }) + } + ] + }) + + // Wait for the transaction to be processed + const { success: sessionUseSuccess } = + await danSessionClient.waitForUserOperationReceipt({ + hash: userOpHash + }) + + expect(sessionUseSuccess).toBe(true) + }, 200000) // Test timeout set to 200 seconds +}) diff --git a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dx.test.ts b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dx.test.ts index 1c25c59fd..c84df2611 100644 --- a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dx.test.ts +++ b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dx.test.ts @@ -140,11 +140,12 @@ describe("modules.smartSessions.dx", async () => { expect(installSuccess).toBe(sessionCreateSuccess) + // Prepare the session data to be stored by the dApp. This could be saved in a Database by the dApp, or client side in local storage. const sessionData: SessionData = { granter: usersNexusClient.account.address, sessionPublicKey, moduleData: { - permissionId: createSessionsResponse.permissionIds[0], + permissionIds: createSessionsResponse.permissionIds, mode: SmartSessionMode.USE } } @@ -184,11 +185,10 @@ describe("modules.smartSessions.dx", async () => { // Use the session to perform an action (increment the counter) const userOpHash = await useSmartSessionNexusClient.usePermission({ - actions: [ + calls: [ { - target: testAddresses.Counter, - value: 0n, - callData: encodeFunctionData({ + to: testAddresses.Counter, + data: encodeFunctionData({ abi: CounterAbi, functionName: "incrementNumber" }) diff --git a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.test.ts b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.test.ts index 305d437a0..98bab7cad 100644 --- a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.test.ts +++ b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.test.ts @@ -259,7 +259,7 @@ describe("modules.smartSessions", async () => { account: smartSessionNexusClient.account, signer: sessionKeyAccount, moduleData: { - permissionId: cachedPermissionId + permissionIds: [cachedPermissionId] } }) @@ -268,11 +268,10 @@ describe("modules.smartSessions", async () => { ) const userOpHash = await useSmartSessionNexusClient.usePermission({ - actions: [ + calls: [ { - target: testAddresses.Counter, - value: 0n, - callData: encodeFunctionData({ + to: testAddresses.Counter, + data: encodeFunctionData({ abi: CounterAbi, functionName: "incrementNumber" }) diff --git a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.ts b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.ts index 1d7160a9f..7f4ca78e6 100644 --- a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.ts +++ b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.ts @@ -13,10 +13,8 @@ import type { UsePermissionModuleData } from "./Types" const DUMMY_ECDSA_SIG = "0xe8b94748580ca0b4993c9a1b86b5be851bfc076ff5ce3a1ff65bf16392acfcb800f9b4f1aef1555c7fce5599fffb17e7c635502154a0333ba21f3ae491839af51c" -/** - * Represents the implementation parameters for a Smart Session module. - */ -export type SmartSessionImplementation = ModuleParameters & { +export type SmartSessionModule = Module & { + sigGen: (signature: Hex) => Hex moduleData?: UsePermissionModuleData } @@ -92,7 +90,7 @@ export const getUsePermissionInitData = ({ */ export const toSmartSessionsValidator = ( parameters: UsePermissionModuleParameters -): Module => { +): SmartSessionModule => { const { account, signer, @@ -102,7 +100,8 @@ export const toSmartSessionsValidator = ( moduleInitArgs: moduleInitArgs_ = { signerAddress: signer.address }, initArgs: initArgs_ = { signerAddress: signer.address }, moduleData: { - permissionId = "0x", + permissionIdIndex = 0, + permissionIds = [], mode = SmartSessionMode.USE, enableSessionData, keyGenData: _ @@ -114,6 +113,7 @@ export const toSmartSessionsValidator = ( moduleInitData_ ?? getUsePermissionModuleInitData(moduleInitArgs_) return toModule({ + ...parameters, signer, accountAddress: account.address, address: SMART_SESSIONS_ADDRESS, @@ -123,14 +123,14 @@ export const toSmartSessionsValidator = ( getStubSignature: async () => encodeSmartSessionSignature({ mode, - permissionId, + permissionId: permissionIds[permissionIdIndex], enableSessionData, signature: DUMMY_ECDSA_SIG }), signUserOpHash: async (userOpHash: Hex) => encodeSmartSessionSignature({ mode, - permissionId, + permissionId: permissionIds[permissionIdIndex], enableSessionData, signature: await signer.signMessage({ message: { raw: userOpHash as Hex } @@ -140,11 +140,11 @@ export const toSmartSessionsValidator = ( sigGen: (signature: Hex): Hex => { return encodeSmartSessionSignature({ mode, - permissionId, + permissionId: permissionIds[permissionIdIndex], enableSessionData, signature }) } } - }) + }) as SmartSessionModule } diff --git a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.uni.policy.test.ts b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.uni.policy.test.ts index bf78ee8e0..7856a883d 100644 --- a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.uni.policy.test.ts +++ b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.uni.policy.test.ts @@ -31,10 +31,7 @@ import { createNexusClient } from "../../clients/createNexusClient" import { createNexusSessionClient } from "../../clients/createNexusSessionClient" -import { - SIMPLE_SESSION_VALIDATOR_ADDRESS, - SMART_SESSIONS_ADDRESS -} from "../../constants" +import { SMART_SESSIONS_ADDRESS } from "../../constants" import type { Module } from "../utils/Types" import { isPermissionEnabled } from "./Helpers" import type { CreateSessionDataParams, Rule } from "./Types" @@ -289,7 +286,7 @@ describe("modules.smartSessions.uniPolicy", async () => { account: smartSessionNexusClient.account, signer: sessionKeyAccount, moduleData: { - permissionId: cachedPermissionId + permissionIds: [cachedPermissionId] } }) @@ -298,12 +295,10 @@ describe("modules.smartSessions.uniPolicy", async () => { ) const userOpHash = await useSmartSessionNexusClient.usePermission({ - account: nexusClient.account, - actions: [ + calls: [ { - target: testAddresses.MockCallee, - value: 0n, - callData: encodeFunctionData({ + to: testAddresses.MockCallee, + data: encodeFunctionData({ abi: MockCalleeAbi, functionName: "addBalance", args: [nexusAccountAddress, balToAddUint, balToAddBytes32 as Hex] diff --git a/src/sdk/modules/utils/Helpers.ts b/src/sdk/modules/utils/Helpers.ts index 5611d7506..6f9ae57dc 100644 --- a/src/sdk/modules/utils/Helpers.ts +++ b/src/sdk/modules/utils/Helpers.ts @@ -9,7 +9,7 @@ import { toHex } from "viem" import { ERROR_MESSAGES } from "../../account/index.js" -import type { ModularSmartAccount } from "./Types.js" +import type { AnyData, ModularSmartAccount } from "./Types.js" /** * Represents a hardcoded hex value reference. @@ -102,7 +102,7 @@ export const parseModule = < chain extends Chain | undefined >( client: Client -) => { +): AnyData => { const activeModule = client?.account?.getModule() if (!activeModule) { throw new Error(ERROR_MESSAGES.MODULE_NOT_ACTIVATED)