diff --git a/packages/account/src/index.ts b/packages/account/src/index.ts index 615c0a6da..e88375a35 100644 --- a/packages/account/src/index.ts +++ b/packages/account/src/index.ts @@ -36,6 +36,11 @@ export { DEFAULT_SESSION_KEY_MANAGER_MODULE, DEFAULT_MULTICHAIN_MODULE, DEFAULT_BATCHED_SESSION_ROUTER_MODULE, + type ECDSAOwnershipValidationModuleConfig, + type BatchedSessionRouterModuleConfig, + type SessionKeyManagerModuleConfig, + type MultiChainValidationModuleConfig, + type SessionValidationModuleConfig, } from "@biconomy/modules"; export const createSmartAccountClient = BiconomySmartAccountV2.create; diff --git a/packages/account/src/utils/Types.ts b/packages/account/src/utils/Types.ts index 0967d0f8f..65f26b5e4 100644 --- a/packages/account/src/utils/Types.ts +++ b/packages/account/src/utils/Types.ts @@ -20,7 +20,7 @@ export type BiconomyFactoriesByVersion = Record; export type BiconomyImplementationsByVersion = Record; export type SmartAccountConfig = { - /** entryPointAddress: address of the smart account factory */ + /** entryPointAddress: address of the entry point */ entryPointAddress: string; /** factoryAddress: address of the smart account factory */ bundler?: IBundler; diff --git a/packages/bundler/CHANGELOG.md b/packages/bundler/CHANGELOG.md index 35465063e..8d1c22faf 100644 --- a/packages/bundler/CHANGELOG.md +++ b/packages/bundler/CHANGELOG.md @@ -6,6 +6,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline ## 4.0.0 (2023-07-02) Export createBundler alias for static Bundler.create call +Abstract away chainId: [0fefb35](https://github.com/bcnmy/biconomy-client-sdk/pull/375/commits/0fefb358e3927d7b026774a785d3711e80f1049a) ## 3.1.3 (2023-12-28) diff --git a/packages/modules/src/BatchedSessionRouterModule.ts b/packages/modules/src/BatchedSessionRouterModule.ts index 4c8847e17..ac6745196 100644 --- a/packages/modules/src/BatchedSessionRouterModule.ts +++ b/packages/modules/src/BatchedSessionRouterModule.ts @@ -62,7 +62,6 @@ export class BatchedSessionRouterModule extends BaseValidationModule { const sessionModule = await SessionKeyManagerModule.create({ moduleAddress: instance.sessionManagerModuleAddress, smartAccountAddress: moduleConfig.smartAccountAddress, - nodeClientUrl: moduleConfig.nodeClientUrl, storageType: moduleConfig.storageType, }); diff --git a/packages/modules/src/utils/Types.ts b/packages/modules/src/utils/Types.ts index b4b96a2c7..e55d5c8a5 100644 --- a/packages/modules/src/utils/Types.ts +++ b/packages/modules/src/utils/Types.ts @@ -1,44 +1,56 @@ import { Chain, Hex } from "viem"; -import { UserOperationStruct, SmartAccountSigner } from "@alchemy/aa-core"; +import { SmartAccountSigner, UserOperationStruct } from "@alchemy/aa-core"; import { SessionKeyManagerModule } from "../SessionKeyManagerModule"; import { ISessionStorage } from "../interfaces/ISessionStorage.js"; import { SupportedSigner } from "@biconomy/common"; export type ModuleVersion = "V1_0_0"; // | 'V1_0_1' export interface BaseValidationModuleConfig { + /** entryPointAddress: address of the entry point */ entryPointAddress?: Hex; } export interface ECDSAOwnershipValidationModuleConfig extends BaseValidationModuleConfig { + /** Address of the module */ moduleAddress?: Hex; + /** Version of the module */ version?: ModuleVersion; + /** Signer: viemWallet or ethers signer. Ingested when passed into smartAccount */ signer: SupportedSigner; } export interface ECDSAOwnershipValidationModuleConfigConstructorProps extends BaseValidationModuleConfig { + /** Address of the module */ moduleAddress?: Hex; + /** Version of the module */ version?: ModuleVersion; + /** Signer: Converted from viemWallet or ethers signer to SmartAccountSigner */ signer: SmartAccountSigner; } export interface SessionKeyManagerModuleConfig extends BaseValidationModuleConfig { + /** Address of the module */ moduleAddress?: Hex; + /** Version of the module */ version?: ModuleVersion; - nodeClientUrl?: string; + /** SmartAccount address */ smartAccountAddress: string; storageType?: StorageType; sessionStorageClient?: ISessionStorage; } export interface BatchedSessionRouterModuleConfig extends BaseValidationModuleConfig { + /** Address of the module */ moduleAddress?: Hex; + /** Version of the module */ version?: ModuleVersion; - - sessionKeyManagerModule?: SessionKeyManagerModule; // could be BaseValidationModule - + /** Session Key Manager module: Could be BaseValidationModule */ + sessionKeyManagerModule?: SessionKeyManagerModule; + /** Session Key Manager module address */ sessionManagerModuleAddress?: Hex; - nodeClientUrl?: string; + /** Address of the associated smart account */ smartAccountAddress: string; + /** Storage type, e.g. local storage */ storageType?: StorageType; } @@ -47,9 +59,13 @@ export enum StorageType { } export type SessionParams = { + /** Redundant now as we've favoured uuid() */ sessionID?: string; + /** Session Signer: viemWallet or ethers signer. Ingested when passed into smartAccount */ sessionSigner: SupportedSigner; + /** The session validation module is a sub-module smart-contract which works with session key manager validation module. It validates the userop calldata against the defined session permissions (session key data) within the contract. */ sessionValidationModule?: Hex; + /** Additional info if needed to be appended in signature */ additionalSessionData?: string; }; @@ -57,21 +73,28 @@ export type ModuleInfo = { // Could be a full object of below params and that way it can be an array too! // sessionParams?: SessionParams[] // where SessionParams is below four sessionID?: string; + /** Session Signer: viemWallet or ethers signer. Ingested when passed into smartAccount */ sessionSigner?: SupportedSigner; + /** The session validation module is a sub-module smart-contract which works with session key manager validation module. It validates the userop calldata against the defined session permissions (session key data) within the contract. */ sessionValidationModule?: Hex; + /** Additional info if needed to be appended in signature */ additionalSessionData?: string; batchSessionParams?: SessionParams[]; }; export interface SendUserOpParams extends ModuleInfo { + /** "validation_and_execution" is recommended during development for improved debugging & devEx, but will add some additional latency to calls. "validation" can be used in production ro remove this latency once flows have been tested. */ simulationType?: SimulationType; } export type SimulationType = "validation" | "validation_and_execution"; export type SignerData = { + /** Public key */ pbKey: string; + /** Private key */ pvKey: `0x${string}`; + /** Network Id */ chainId?: Chain; }; @@ -81,27 +104,38 @@ export type CreateSessionDataResponse = { }; export interface CreateSessionDataParams { + /** window end for the session key */ validUntil: number; + /** window start for the session key */ validAfter: number; sessionValidationModule: Hex; sessionPublicKey: Hex; sessionKeyData: Hex; + /** we generate uuid based sessionId. but if you prefer to track it on your side and attach custom session identifier this can be passed */ preferredSessionId?: string; } export interface MultiChainValidationModuleConfig extends BaseValidationModuleConfig { + /** Address of the module */ moduleAddress?: Hex; + /** Version of the module */ version?: ModuleVersion; + /** Signer: viemWallet or ethers signer. Ingested when passed into smartAccount */ signer: SupportedSigner; } export interface MultiChainValidationModuleConfigConstructorProps extends BaseValidationModuleConfig { + /** Address of the module */ moduleAddress?: Hex; + /** Version of the module */ version?: ModuleVersion; + /** Signer: viemWallet or ethers signer. Ingested when passed into smartAccount */ signer: SmartAccountSigner; } export type MultiChainUserOpDto = { + /** window end timestamp */ validUntil?: number; + /** window start timestamp */ validAfter?: number; chainId: number; userOp: Partial; @@ -112,11 +146,15 @@ export interface BaseSessionKeyData { } export interface ERC20SessionKeyData extends BaseSessionKeyData { + /** ERC20 token address */ token: Hex; + /** Recipient address */ recipient: Hex; + /** ERC20 amount (Bigint) */ maxAmount: bigint; } export interface SessionValidationModuleConfig { + /** Address of the module */ moduleAddress: string; } diff --git a/packages/modules/tests/ecdsaValidationModule.e2e.spec.ts b/packages/modules/tests/ecdsaValidationModule.e2e.spec.ts new file mode 100644 index 000000000..84b3f627e --- /dev/null +++ b/packages/modules/tests/ecdsaValidationModule.e2e.spec.ts @@ -0,0 +1,63 @@ +import { PaymasterMode } from "@biconomy/paymaster"; +import { TestData } from "../../../tests"; +import { createSmartAccountClient } from "../../account/src/index"; +import { Hex, encodeFunctionData, parseAbi } from "viem"; +import { DEFAULT_MULTICHAIN_MODULE, createECDSAOwnershipValidationModule } from "@biconomy/modules"; + +describe("Account with ECDSAOwnershipValidationModule Module Tests", () => { + let mumbai: TestData; + let baseSepolia: TestData; + + beforeEach(() => { + // @ts-ignore: Comes from setup-e2e-tests + [mumbai, baseSepolia] = testDataPerChain; + }); + + it("should create a ECDSAOwnershipValidationModule with signer", async () => { + const { + bundlerUrl, + whale: { viemWallet: signer }, + } = mumbai; + + const defaultValidationModule = await createECDSAOwnershipValidationModule({ signer }); + // Should not require a signer or chainId + const smartAccount = await createSmartAccountClient({ + bundlerUrl, + defaultValidationModule, + signer, + }); + const address = await smartAccount.getAccountAddress(); + expect(address).toBeTruthy(); + expect(smartAccount.activeValidationModule).toEqual(defaultValidationModule); + }); + + it("should create a ECDSAOwnershipValidationModule without signer", async () => { + const { + bundlerUrl, + whale: { viemWallet: signer }, + } = mumbai; + + const defaultValidationModule = await createECDSAOwnershipValidationModule({ signer }); + // Should not require a signer or chainId + const smartAccount = await createSmartAccountClient({ + bundlerUrl, + defaultValidationModule, + }); + const address = await smartAccount.getAccountAddress(); + expect(address).toBeTruthy(); + expect(smartAccount.activeValidationModule).toEqual(defaultValidationModule); + }); + + it("should create a ECDSAOwnershipValidationModule by default, without explicitly setting it on the smart account", async () => { + const { + bundlerUrl, + whale: { viemWallet: signer }, + } = mumbai; + const defaultValidationModule = await createECDSAOwnershipValidationModule({ signer }); + const smartAccount = await createSmartAccountClient({ bundlerUrl, signer }); + const address = await smartAccount.getAccountAddress(); + expect(address).toBeTruthy(); + const smartAccountValidationModuleAddress = await smartAccount.activeValidationModule.getAddress(); + expect(smartAccountValidationModuleAddress).toEqual(defaultValidationModule.moduleAddress); + }); +});