import { createSmartAccountClient, grantPermission, ownableActions, toNexusAccount, toOwnableModule, usePermission } from "@biconomy/abstractjs-canary" import { getSmartSessionsValidator, getSudoPolicy } from "@rhinestone/module-sdk" import { http, type LocalAccount, parseEther } from "viem" import { privateKeyToAccount } from "viem/accounts" import { COUNTER_ADDRESS } from "../src/addresses" import type { Infra } from "../src/toEcosystem" import { toClients } from "../src/utils" export const validateModules = async (infra: Infra) => { await validateOwnables(infra) await validateSmartSessions(infra) } export const validateOwnables = async (infra: Infra) => { const { bundler, network: { rpcUrl, chain, privateKey } } = infra const { walletClients: [_, __, walletClientTwo] } = await toClients({ rpcUrl, chain, privateKey }) const eoaAccount = privateKeyToAccount(privateKey) const redeemerAccount = walletClientTwo.account as LocalAccount const ownablesModule = toOwnableModule({ signer: eoaAccount, threshold: 1, owners: [redeemerAccount.address] }) const nexusAccount = await toNexusAccount({ signer: eoaAccount, chain, transport: http(rpcUrl), validators: [ownablesModule] }) const { testClient } = await toClients({ rpcUrl, chain, privateKey }) await testClient.setBalance({ address: nexusAccount.address, value: parseEther("1") }) const nexusClient = createSmartAccountClient({ account: nexusAccount, transport: http(bundler.url), mock: true }) const ownablesClient = nexusClient.extend(ownableActions()) const { userOpHash, userOp } = await ownablesClient.prepareForMultiSign({ calls: [ { to: COUNTER_ADDRESS, data: "0x273ea3e3" } ] }) const sig = await redeemerAccount.signMessage({ message: { raw: userOpHash } }) const multiSigHash = await ownablesClient.multiSign({ ...userOp, signatures: [sig] }) const receipt = await nexusClient.waitForUserOperationReceipt({ hash: multiSigHash }) if (!receipt.success) { throw new Error("Multi sign failed") } console.log("ownables module check passed ✅") } export const validateSmartSessions = async ({ bundler, network: { rpcUrl, chain, privateKey } }: Infra) => { const eoaAccount = privateKeyToAccount(privateKey) const { walletClients: [_, walletClientTwo], publicClient } = await toClients({ rpcUrl, chain, privateKey }) const dappAccount = walletClientTwo.account as LocalAccount const dappAccountAddress = dappAccount.address const nexusAccount = await toNexusAccount({ signer: eoaAccount, chain, transport: http(rpcUrl) }) const nexusClient = createSmartAccountClient({ account: nexusAccount, transport: http(bundler.url), mock: true }) // Install the smart sessions module on the Nexus client's smart contract account const hash = await nexusClient.installModule({ module: getSmartSessionsValidator({ useRegistry: false }) }) // Wait for the module installation transaction to be mined and check its success const { success: installSuccess } = await nexusClient.waitForUserOperationReceipt({ hash }) if (!installSuccess) { throw new Error("Smart sessions module installation failed") } const sessionDetails = await grantPermission(nexusClient, { redeemer: dappAccountAddress, actions: [ { actionTarget: COUNTER_ADDRESS, actionTargetSelector: "0x273ea3e3", actionPolicies: [getSudoPolicy()] } ] }) const emulatedAccount = await toNexusAccount({ accountAddress: nexusAccount.address, signer: dappAccount, chain, transport: http(rpcUrl) }) const emulatedClient = createSmartAccountClient({ account: emulatedAccount, transport: http(bundler.url), mock: true }) const userOpHashOne = await usePermission(emulatedClient, { sessionDetails, calls: [{ to: COUNTER_ADDRESS, data: "0x273ea3e3" }], mode: "ENABLE_AND_USE" }) const receiptOne = await nexusClient.waitForUserOperationReceipt({ hash: userOpHashOne }) if (!receiptOne.success) { throw new Error("Smart sessions module validation failed") } const userOpHashTwo = await usePermission(emulatedClient, { sessionDetails, calls: [{ to: COUNTER_ADDRESS, data: "0x273ea3e3" }], mode: "USE" }) const receiptTwo = await nexusClient.waitForUserOperationReceipt({ hash: userOpHashTwo }) if (!receiptTwo.success) { throw new Error("Smart sessions module validation failed") } console.log("Smart sessions module check passed ✅") }