Skip to content

Commit

Permalink
chore: retain action data in session payload
Browse files Browse the repository at this point in the history
  • Loading branch information
joepegler committed Dec 5, 2024
1 parent d1cb310 commit df169a9
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 43 deletions.
44 changes: 32 additions & 12 deletions src/sdk/clients/createNexusSessionClient.test.ts
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -13,8 +14,15 @@ 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,
parse,
stringify
} from "../modules/smartSessionsValidator/Helpers"
import type {
CreateSessionDataParams,
SessionData
} from "../modules/smartSessionsValidator/Types"
import {
smartSessionCreateActions,
smartSessionUseActions
Expand All @@ -36,7 +44,7 @@ describe("nexus.session.client", async () => {
let nexusAccountAddress: Address
let sessionKeyAccount: LocalAccount
let sessionPublicKey: Address
let cachedPermissionId: Hex
let stringifiedSessionData: string

let sessionsModule: Module

Expand Down Expand Up @@ -135,7 +143,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
Expand All @@ -146,12 +166,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 = parse(stringifiedSessionData) as SessionData

const counterBefore = await testClient.readContract({
address: testAddresses.Counter,
abi: CounterAbi,
Expand All @@ -169,9 +191,7 @@ describe("nexus.session.client", async () => {
const usePermissionsModule = toSmartSessionsValidator({
account: smartSessionNexusClient.account,
signer: sessionKeyAccount,
moduleData: {
permissionIds: [cachedPermissionId]
}
moduleData: sessionData.moduleData
})

const useSmartSessionNexusClient = smartSessionNexusClient.extend(
Expand Down Expand Up @@ -209,12 +229,12 @@ describe("nexus.session.client", async () => {
}, 60000)

test("session signer is not allowed to send unauthorised action", async () => {
const sessionData = parse(stringifiedSessionData) as SessionData

const usePermissionsModule = toSmartSessionsValidator({
account: nexusClient.account,
signer: sessionKeyAccount,
moduleData: {
permissionIds: [cachedPermissionId]
}
moduleData: sessionData.moduleData
})

const smartSessionNexusClient = await createNexusSessionClient({
Expand All @@ -232,7 +252,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)

Expand Down
11 changes: 5 additions & 6 deletions src/sdk/modules/smartSessionsValidator/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -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.
Expand All @@ -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<
| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ export async function grantPermission<

return {
userOpHash: userOpHash,
permissionIds: actionResponse.permissionIds
...actionResponse
}
}
throw new Error("Error getting enable sessions action")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down Expand Up @@ -147,22 +147,23 @@ 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 () => {
// Now assume the user has left the dapp and the usersNexusClient signer is no longer available
// 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -130,22 +130,23 @@ 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 () => {
// Now assume the user has left the dapp and the usersNexusClient signer is no longer available
// 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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SmartSessionMode } from "@rhinestone/module-sdk"
import {
http,
type Address,
Expand Down Expand Up @@ -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"
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
} from "viem"
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
import { afterAll, beforeAll, describe, expect, test } from "vitest"
import { CounterAbi, MockRegistryAbi } from "../../../test/__contracts/abi"
import { MockCalleeAbi } from "../../../test/__contracts/abi/MockCalleeAbi"
import { testAddresses } from "../../../test/callDatas"
import { toNetwork } from "../../../test/testSetup"
Expand All @@ -33,7 +32,7 @@ import {
import { createNexusSessionClient } from "../../clients/createNexusSessionClient"
import { SMART_SESSIONS_ADDRESS } from "../../constants"
import type { Module } from "../utils/Types"
import { abiToPoliciesInfo, isPermissionEnabled } from "./Helpers"
import { isPermissionEnabled, parse, stringify } from "./Helpers"
import type { CreateSessionDataParams, Rule, SessionData } from "./Types"
import { ParamCondition } from "./Types"
import { smartSessionCreateActions, smartSessionUseActions } from "./decorators"
Expand All @@ -51,7 +50,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

Expand Down Expand Up @@ -227,7 +226,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
Expand All @@ -238,16 +248,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 = 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)

Expand Down Expand Up @@ -285,9 +297,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(
Expand Down

0 comments on commit df169a9

Please sign in to comment.