From e1a779668cf9e54481c0ac59e2781f3a12eb1f76 Mon Sep 17 00:00:00 2001 From: Joe Pegler Date: Thu, 5 Dec 2024 11:26:17 +0000 Subject: [PATCH] chore: retain action data in session payload --- .../clients/createNexusSessionClient.test.ts | 43 +++++++++++++------ .../modules/smartSessionsValidator/Types.ts | 11 +++-- .../decorators/grantPermission.ts | 2 +- .../toSmartSessionsValidator.dx.test.ts | 9 ++-- ...SmartSessionsValidator.sudo.policy.test.ts | 9 ++-- .../toSmartSessionsValidator.test.ts | 31 ++++++++++--- ...oSmartSessionsValidator.uni.policy.test.ts | 25 ++++++++--- 7 files changed, 89 insertions(+), 41 deletions(-) diff --git a/src/sdk/clients/createNexusSessionClient.test.ts b/src/sdk/clients/createNexusSessionClient.test.ts index 3cacf61d..0529b849 100644 --- a/src/sdk/clients/createNexusSessionClient.test.ts +++ b/src/sdk/clients/createNexusSessionClient.test.ts @@ -1,3 +1,4 @@ +import { SmartSessionMode } from "@rhinestone/module-sdk" import { http, type Address, type Chain, type Hex, toBytes, toHex } from "viem" import type { LocalAccount, PublicClient } from "viem" import { encodeFunctionData } from "viem" @@ -13,8 +14,14 @@ import { } from "../../test/testUtils" import type { MasterClient, NetworkConfig } from "../../test/testUtils" import { SMART_SESSIONS_ADDRESS } from "../constants" -import { isPermissionEnabled } from "../modules/smartSessionsValidator/Helpers" -import type { CreateSessionDataParams } from "../modules/smartSessionsValidator/Types" +import { + isPermissionEnabled, + stringify +} from "../modules/smartSessionsValidator/Helpers" +import type { + CreateSessionDataParams, + SessionData +} from "../modules/smartSessionsValidator/Types" import { smartSessionCreateActions, smartSessionUseActions @@ -36,7 +43,7 @@ describe("nexus.session.client", async () => { let nexusAccountAddress: Address let sessionKeyAccount: LocalAccount let sessionPublicKey: Address - let cachedPermissionId: Hex + let stringifiedSessionData: string let sessionsModule: Module @@ -135,7 +142,19 @@ describe("nexus.session.client", async () => { expect(createSessionsResponse.userOpHash).toBeDefined() expect(createSessionsResponse.permissionIds).toBeDefined() - ;[cachedPermissionId] = createSessionsResponse.permissionIds + + // 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: nexusSessionClient?.account?.address as Hex, + sessionPublicKey, + description: `Session to increment a counter for ${testAddresses.Counter}`, + moduleData: { + ...createSessionsResponse, + mode: SmartSessionMode.USE + } + } + + stringifiedSessionData = stringify(sessionData) const receipt = await nexusClient.waitForUserOperationReceipt({ hash: createSessionsResponse.userOpHash @@ -146,12 +165,14 @@ describe("nexus.session.client", async () => { const isEnabled = await isPermissionEnabled({ client: nexusClient.account.client as PublicClient, accountAddress: nexusClient.account.address, - permissionId: cachedPermissionId + permissionId: createSessionsResponse.permissionIds[0] }) expect(isEnabled).toBe(true) }, 60000) test("session signer should use session to increment a counter for a user (USE MODE)", async () => { + const sessionData = JSON.parse(stringifiedSessionData) as SessionData + const counterBefore = await testClient.readContract({ address: testAddresses.Counter, abi: CounterAbi, @@ -169,9 +190,7 @@ describe("nexus.session.client", async () => { const usePermissionsModule = toSmartSessionsValidator({ account: smartSessionNexusClient.account, signer: sessionKeyAccount, - moduleData: { - permissionIds: [cachedPermissionId] - } + moduleData: sessionData.moduleData }) const useSmartSessionNexusClient = smartSessionNexusClient.extend( @@ -209,12 +228,12 @@ describe("nexus.session.client", async () => { }, 60000) test("session signer is not allowed to send unauthorised action", async () => { + const sessionData = JSON.parse(stringifiedSessionData) as SessionData + const usePermissionsModule = toSmartSessionsValidator({ account: nexusClient.account, signer: sessionKeyAccount, - moduleData: { - permissionIds: [cachedPermissionId] - } + moduleData: sessionData.moduleData }) const smartSessionNexusClient = await createNexusSessionClient({ @@ -232,7 +251,7 @@ describe("nexus.session.client", async () => { const isEnabled = await isPermissionEnabled({ client: testClient as unknown as PublicClient, accountAddress: nexusClient.account.address, - permissionId: cachedPermissionId + permissionId: sessionData.moduleData.permissionIds[0] }) expect(isEnabled).toBe(true) diff --git a/src/sdk/modules/smartSessionsValidator/Types.ts b/src/sdk/modules/smartSessionsValidator/Types.ts index 2d8a93b3..7b2a16cd 100644 --- a/src/sdk/modules/smartSessionsValidator/Types.ts +++ b/src/sdk/modules/smartSessionsValidator/Types.ts @@ -24,6 +24,9 @@ export type SessionData = { /** Module-specific data containing session configuration and permissions. */ moduleData: UsePermissionModuleData + + /** Description of the session. Useful for keeping humancontext about the session. */ + description?: string } export type GrantPermissionActionReturnParams = { @@ -39,9 +42,7 @@ export type GrantPermissionActionReturnParams = { export type GrantPermissionResponse = { /** The hash of the user operation. */ userOpHash: Hex - /** Array of permission IDs for the created sessions. */ - permissionIds: Hex[] -} +} & GrantPermissionActionReturnParams /** * Represents the possible modes for a smart session. @@ -53,15 +54,13 @@ export type SmartSessionModeType = * Represents the data structure for using a session module. */ export type UsePermissionModuleData = { - /** The permission ID for the session. */ - permissionIds: Hex[] /** The mode of the smart session. */ mode?: SmartSessionModeType /** Data for enabling the session. */ enableSessionData?: EnableSessionData /** The index of the permission ID to use for the session. Defaults to 0. */ permissionIdIndex?: number -} +} & GrantPermissionActionReturnParams type OptionalSessionKeyData = OneOf< | { diff --git a/src/sdk/modules/smartSessionsValidator/decorators/grantPermission.ts b/src/sdk/modules/smartSessionsValidator/decorators/grantPermission.ts index 4191e731..f3fe1e4f 100644 --- a/src/sdk/modules/smartSessionsValidator/decorators/grantPermission.ts +++ b/src/sdk/modules/smartSessionsValidator/decorators/grantPermission.ts @@ -346,7 +346,7 @@ export async function grantPermission< return { userOpHash: userOpHash, - permissionIds: actionResponse.permissionIds + ...actionResponse } } throw new Error("Error getting enable sessions action") diff --git a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dx.test.ts b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dx.test.ts index 02e5cfd2..5055f68d 100644 --- a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dx.test.ts +++ b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.dx.test.ts @@ -42,7 +42,7 @@ describe("modules.smartSessions.dx", async () => { let sessionKeyAccount: LocalAccount let sessionPublicKey: Address - let zippedSessionDatum: string + let stringifiedSessionDatum: string let sessionsModule: Module beforeAll(async () => { @@ -147,14 +147,15 @@ describe("modules.smartSessions.dx", async () => { const sessionData: SessionData = { granter: usersNexusClient.account.address, sessionPublicKey, + description: `Session to increment a counter for ${testAddresses.Counter}`, moduleData: { - permissionIds: createSessionsResponse.permissionIds, + ...createSessionsResponse, mode: SmartSessionMode.USE } } // Zip the session data, and store it for later use by a dapp - zippedSessionDatum = stringify(sessionData) + stringifiedSessionDatum = stringify(sessionData) }, 200000) test("should demonstrate using a smart session from dapp's perspective", async () => { @@ -162,7 +163,7 @@ describe("modules.smartSessions.dx", async () => { // The following code demonstrates how a dapp can use the session to act on behalf of the user // Unzip the session data - const usersSessionData = parse(zippedSessionDatum) + const usersSessionData = parse(stringifiedSessionDatum) // Create a new Nexus client for the session // This client will be used to interact with the smart contract account using the session key diff --git a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.sudo.policy.test.ts b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.sudo.policy.test.ts index ad1120ce..d388ed80 100644 --- a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.sudo.policy.test.ts +++ b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.sudo.policy.test.ts @@ -44,7 +44,7 @@ describe("modules.smartSessions.sudo.policy", async () => { let sessionKeyAccount: LocalAccount let sessionPublicKey: Address - let zippedSessionDatum: string // Session data to be stored by the dApp + let stringifiedSessionDatum: string // Session data to be stored by the dApp let sessionsModule: Module @@ -130,14 +130,15 @@ describe("modules.smartSessions.sudo.policy", async () => { const sessionData: SessionData = { granter: usersNexusClient?.account?.address as Hex, sessionPublicKey, + description: `Session to increment a counter for ${testAddresses.Counter}`, moduleData: { - permissionIds: createSessionsResponse.permissionIds, + ...createSessionsResponse, mode: SmartSessionMode.USE } } // Zip the session data, and store it for later use by a dapp - zippedSessionDatum = stringify(sessionData) + stringifiedSessionDatum = stringify(sessionData) }) test("should demonstrate using a smart session from dapp's perspective", async () => { @@ -145,7 +146,7 @@ describe("modules.smartSessions.sudo.policy", async () => { // The following code demonstrates how a dapp can use the session to act on behalf of the user // Unzip the session data - const usersSessionData = parse(zippedSessionDatum) + const usersSessionData = parse(stringifiedSessionDatum) // Create a new Nexus client for the session // This client will be used to interact with the smart contract account using the session key diff --git a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.test.ts b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.test.ts index cdb0d099..c09ad2d1 100644 --- a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.test.ts +++ b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.test.ts @@ -1,3 +1,4 @@ +import { SmartSessionMode } from "@rhinestone/module-sdk" import { http, type Address, @@ -27,8 +28,13 @@ import { import { createNexusSessionClient } from "../../clients/createNexusSessionClient" import { parseReferenceValue } from "../utils/Helpers" import type { Module } from "../utils/Types" -import { abiToPoliciesInfo, toUniversalActionPolicy } from "./Helpers" -import type { CreateSessionDataParams } from "./Types" +import { + abiToPoliciesInfo, + parse, + stringify, + toUniversalActionPolicy +} from "./Helpers" +import type { CreateSessionDataParams, SessionData } from "./Types" import { ParamCondition } from "./Types" import { smartSessionCreateActions, smartSessionUseActions } from "./decorators" import { toSmartSessionsValidator } from "./toSmartSessionsValidator" @@ -42,7 +48,7 @@ describe("modules.smartSessions", async () => { let testClient: MasterClient let eoaAccount: LocalAccount let nexusClient: NexusClient - let cachedPermissionId: Hex + let stringifiedSessionData: string // Session data to be stored by the dApp let sessionKeyAccount: LocalAccount let sessionPublicKey: Address @@ -244,7 +250,18 @@ describe("modules.smartSessions", async () => { expect(createSessionsResponse.userOpHash).toBeDefined() expect(createSessionsResponse.permissionIds).toBeDefined() - ;[cachedPermissionId] = createSessionsResponse.permissionIds + + const sessionData: SessionData = { + granter: nexusClient.account.address, + description: `Session to increment a counter for ${testAddresses.Counter}`, + sessionPublicKey, + moduleData: { + ...createSessionsResponse, + mode: SmartSessionMode.USE + } + } + + stringifiedSessionData = stringify(sessionData) const receipt = await nexusClient.waitForUserOperationReceipt({ hash: createSessionsResponse.userOpHash @@ -260,6 +277,8 @@ describe("modules.smartSessions", async () => { functionName: "getNumber" }) + const parsedSessionData = parse(stringifiedSessionData) as SessionData + const smartSessionNexusClient = await createNexusSessionClient({ chain, accountAddress: nexusClient.account.address, @@ -271,9 +290,7 @@ describe("modules.smartSessions", async () => { const usePermissionsModule = toSmartSessionsValidator({ account: smartSessionNexusClient.account, signer: sessionKeyAccount, - moduleData: { - permissionIds: [cachedPermissionId] - } + moduleData: parsedSessionData.moduleData }) const useSmartSessionNexusClient = smartSessionNexusClient.extend( diff --git a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.uni.policy.test.ts b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.uni.policy.test.ts index 6da4c889..9401c541 100644 --- a/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.uni.policy.test.ts +++ b/src/sdk/modules/smartSessionsValidator/toSmartSessionsValidator.uni.policy.test.ts @@ -51,7 +51,7 @@ describe("modules.smartSessions.uni.policy", async () => { let nexusAccountAddress: Address let sessionKeyAccount: LocalAccount let sessionPublicKey: Address - let cachedPermissionId: Hex + let stringifiedSessionData: string let sessionsModule: Module @@ -227,7 +227,18 @@ describe("modules.smartSessions.uni.policy", async () => { expect(createSessionsResponse.userOpHash).toBeDefined() expect(createSessionsResponse.permissionIds).toBeDefined() - ;[cachedPermissionId] = createSessionsResponse.permissionIds + + const sessionData: SessionData = { + granter: nexusClient.account.address, + description: `Session to add balance to MockCallee for ${testAddresses.MockCallee}`, + sessionPublicKey, + moduleData: { + ...createSessionsResponse, + mode: SmartSessionMode.USE + } + } + + stringifiedSessionData = stringify(sessionData) const receipt = await nexusClient.waitForUserOperationReceipt({ hash: createSessionsResponse.userOpHash @@ -238,16 +249,18 @@ describe("modules.smartSessions.uni.policy", async () => { const isEnabled = await isPermissionEnabled({ client: nexusClient.account.client as PublicClient, accountAddress: nexusClient.account.address, - permissionId: cachedPermissionId + permissionId: sessionData.moduleData.permissionIds[0] }) expect(isEnabled).toBe(true) }, 200000) test("should make use of already enabled session (USE mode) to add balance to MockCallee using a session key", async () => { + const parsedSessionData = JSON.parse(stringifiedSessionData) as SessionData + const isEnabled = await isPermissionEnabled({ client: nexusClient.account.client as PublicClient, accountAddress: nexusClient.account.address, - permissionId: cachedPermissionId + permissionId: parsedSessionData.moduleData.permissionIds[0] }) expect(isEnabled).toBe(true) @@ -285,9 +298,7 @@ describe("modules.smartSessions.uni.policy", async () => { const usePermissionsModule = toSmartSessionsValidator({ account: smartSessionNexusClient.account, signer: sessionKeyAccount, - moduleData: { - permissionIds: [cachedPermissionId] - } + moduleData: parsedSessionData.moduleData }) const useSmartSessionNexusClient = smartSessionNexusClient.extend(