From 8ce67b1ebd55e1d869911039d3f509ded40223e3 Mon Sep 17 00:00:00 2001 From: Joe Pegler Date: Tue, 17 Sep 2024 13:09:25 +0100 Subject: [PATCH] chore: refactor signer -> holder --- packages/sdk/account/index.ts | 2 - packages/sdk/account/signers/local-account.ts | 55 ---- packages/sdk/account/signers/wallet-client.ts | 48 ---- packages/sdk/account/toNexusAccount.test.ts | 5 +- packages/sdk/account/toNexusAccount.ts | 67 ++--- packages/sdk/account/utils/EthersSigner.ts | 42 --- packages/sdk/account/utils/HttpRequests.ts | 80 ------ packages/sdk/account/utils/Types.ts | 265 +----------------- packages/sdk/account/utils/Utils.ts | 15 +- packages/sdk/account/utils/convertSigner.ts | 76 ----- packages/sdk/account/utils/index.ts | 4 +- packages/sdk/account/utils/toHolder.ts | 85 ++++++ .../clients/createBicoBundlerClient.test.ts | 2 +- .../sdk/clients/createNexusClient.test.ts | 2 +- packages/sdk/clients/createNexusClient.ts | 9 +- .../erc7579/erc7579.actions.test.ts | 2 +- .../smartAccount/erc7579.actions.test.ts | 2 +- packages/sdk/modules/base/BaseModule.ts | 8 +- .../sdk/modules/base/BaseValidationModule.ts | 22 +- .../sdk/modules/executors/OwnableExecutor.ts | 20 +- .../modules/interfaces/IValidationModule.ts | 4 +- packages/sdk/modules/smart.sessions.test.ts | 2 +- packages/sdk/modules/utils/Types.ts | 67 +---- .../modules/validators/K1ValidatorModule.ts | 12 +- .../modules/validators/ValidationModule.ts | 10 +- .../modules/validators/k1Validator.test.ts | 3 +- packages/test/playground.test.ts | 4 +- packages/test/testUtils.ts | 2 +- scripts/send:userOp.ts | 2 +- scripts/viem:bundler.ts | 9 +- 30 files changed, 212 insertions(+), 714 deletions(-) delete mode 100644 packages/sdk/account/signers/local-account.ts delete mode 100644 packages/sdk/account/signers/wallet-client.ts delete mode 100644 packages/sdk/account/utils/EthersSigner.ts delete mode 100644 packages/sdk/account/utils/HttpRequests.ts delete mode 100644 packages/sdk/account/utils/convertSigner.ts create mode 100644 packages/sdk/account/utils/toHolder.ts diff --git a/packages/sdk/account/index.ts b/packages/sdk/account/index.ts index a7d2a4d2f..57756f3eb 100644 --- a/packages/sdk/account/index.ts +++ b/packages/sdk/account/index.ts @@ -1,4 +1,2 @@ export * from "./utils/index.js" -export * from "./signers/local-account.js" -export * from "./signers/wallet-client.js" export * from "./toNexusAccount.js" diff --git a/packages/sdk/account/signers/local-account.ts b/packages/sdk/account/signers/local-account.ts deleted file mode 100644 index 65bf3c521..000000000 --- a/packages/sdk/account/signers/local-account.ts +++ /dev/null @@ -1,55 +0,0 @@ -import type { - HDAccount, - Hex, - LocalAccount, - PrivateKeyAccount, - SignableMessage, - TypedData, - TypedDataDefinition -} from "viem" -import { mnemonicToAccount, privateKeyToAccount } from "viem/accounts" -import type { SmartAccountSigner } from "../utils/Types.js" - -export class LocalAccountSigner< - T extends HDAccount | PrivateKeyAccount | LocalAccount -> implements SmartAccountSigner -{ - inner: T - signerType: string - - constructor(inner: T) { - this.inner = inner - this.signerType = inner.type // type: "local" - } - - readonly signMessage: (message: SignableMessage) => Promise<`0x${string}`> = ( - message - ) => { - return this.inner.signMessage({ message }) - } - - readonly signTypedData = async < - const TTypedData extends TypedData | { [key: string]: unknown }, - TPrimaryType extends string = string - >( - params: TypedDataDefinition - ): Promise => { - return this.inner.signTypedData(params) - } - - readonly getAddress: () => Promise<`0x${string}`> = async () => { - return this.inner.address - } - - static mnemonicToAccountSigner(key: string): LocalAccountSigner { - const signer = mnemonicToAccount(key) - return new LocalAccountSigner(signer) - } - - static privateKeyToAccountSigner( - key: Hex - ): LocalAccountSigner { - const signer = privateKeyToAccount(key) - return new LocalAccountSigner(signer) - } -} diff --git a/packages/sdk/account/signers/wallet-client.ts b/packages/sdk/account/signers/wallet-client.ts deleted file mode 100644 index 69c10fe5a..000000000 --- a/packages/sdk/account/signers/wallet-client.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { - type Hex, - type SignableMessage, - type TypedData, - type TypedDataDefinition, - type WalletClient, - getAddress -} from "viem" -import type { SmartAccountSigner } from "../utils/Types.js" - -export class WalletClientSigner implements SmartAccountSigner { - signerType: string - inner: WalletClient - - constructor(client: WalletClient, signerType: string) { - this.inner = client - if (!signerType) { - throw new Error(`InvalidSignerTypeError: ${signerType}`) - } - this.signerType = signerType - } - - getAddress: () => Promise<`0x${string}`> = async () => { - const addresses = await this.inner.getAddresses() - return getAddress(addresses[0]) - } - - readonly signMessage: (message: SignableMessage) => Promise<`0x${string}`> = - async (message) => { - const account = this.inner.account ?? (await this.getAddress()) - - return this.inner.signMessage({ message, account }) - } - - signTypedData = async < - const TTypedData extends TypedData | { [key: string]: unknown }, - TPrimaryType extends string = string - >( - typedData: TypedDataDefinition - ): Promise => { - const account = this.inner.account ?? (await this.getAddress()) - - return this.inner.signTypedData({ - account, - ...typedData - }) - } -} diff --git a/packages/sdk/account/toNexusAccount.test.ts b/packages/sdk/account/toNexusAccount.test.ts index adad3c9dc..42d58a347 100644 --- a/packages/sdk/account/toNexusAccount.test.ts +++ b/packages/sdk/account/toNexusAccount.test.ts @@ -78,7 +78,7 @@ describe("nexus.account", async () => { }) nexusClient = await createNexusClient({ - owner: account, + holder: account, chain, transport: http(), bundlerTransport: http(bundlerUrl) @@ -275,7 +275,7 @@ describe("nexus.account", async () => { expect(contractResponse).toBe(eip1271MagicValue) }) - test.skip("should sign using signTypedData SDK method", async () => { + test("should sign using signTypedData SDK method", async () => { const appDomain = { chainId: chain.id, name: "TokenWithPermit", @@ -348,7 +348,6 @@ describe("nexus.account", async () => { }) const permitTokenResponse = await nexusClient.writeContract({ - account: account, address: mockAddresses.TokenWithPermit, abi: TokenWithPermitAbi, functionName: "permitWith1271", diff --git a/packages/sdk/account/toNexusAccount.ts b/packages/sdk/account/toNexusAccount.ts index c2ed0cfcd..a7a60b5a6 100644 --- a/packages/sdk/account/toNexusAccount.ts +++ b/packages/sdk/account/toNexusAccount.ts @@ -10,6 +10,7 @@ import { type RpcSchema, type SignableMessage, type Transport, + type TypedData, type TypedDataDefinition, type UnionPartialBy, concat, @@ -37,7 +38,6 @@ import { getUserOperationHash, toSmartAccount } from "viem/account-abstraction" -import { parseAccount } from "viem/accounts" import contracts from "../__contracts" import { EntrypointAbi, K1ValidatorFactoryAbi } from "../__contracts/abi" import type { Call, GetNonceArgs, UserOperationStruct } from "./utils/Types" @@ -53,19 +53,20 @@ import { import type { BaseExecutionModule } from "../modules/base/BaseExecutionModule" import type { BaseValidationModule } from "../modules/base/BaseValidationModule" import { K1ValidatorModule } from "../modules/validators/K1ValidatorModule" -import { WalletClientSigner } from "./signers/wallet-client" import { + type TypedDataWith712, eip712WrapHash, getAccountDomainStructFields, getTypesForEIP712Domain, packUserOp, typeToString } from "./utils/Utils" +import { type UnknownHolder, toHolder } from "./utils/toHolder" export type ToNexusSmartAccountParameters = { chain: Chain transport: ClientConfig["transport"] - owner: Account | Address + holder: UnknownHolder index?: bigint | undefined activeModule?: BaseValidationModule executorModule?: BaseExecutionModule @@ -123,7 +124,7 @@ export const toNexusAccount = async ( const { chain, transport, - owner, + holder: holder_, index = 0n, activeModule, executorModule: _, @@ -133,8 +134,10 @@ export const toNexusAccount = async ( name = "Nexus Account" } = parameters + const holder = await toHolder({ holder: holder_ }) + const masterClient = createWalletClient({ - account: parseAccount(owner), + account: holder, chain, transport, key, @@ -143,7 +146,6 @@ export const toNexusAccount = async ( .extend(walletActions) .extend(publicActions) - const moduleSigner = new WalletClientSigner(masterClient, "viem") const signerAddress = masterClient.account.address const entryPointContract = getContract({ address: contracts.entryPoint.address, @@ -169,7 +171,7 @@ export const toNexusAccount = async ( context: signerAddress, additionalContext: "0x" }, - moduleSigner + holder ) let _accountAddress: Address @@ -337,8 +339,8 @@ export const toNexusAccount = async ( message }: { message: SignableMessage }): Promise => { const tempSignature = await defaultedActiveModule - .getSigner() - .signMessage(message) + .getHolder() + .signMessage({ message }) const signature = encodePacked( ["address", "bytes"], @@ -370,33 +372,32 @@ export const toNexusAccount = async ( return accountIsDeployed ? signature : erc6492Signature } - const signTypedData = async ( - // biome-ignore lint/suspicious/noExplicitAny: - typedData: any - ): Promise => { + async function signTypedData< + const typedData extends TypedData | Record, + primaryType extends keyof typedData | "EIP712Domain" = keyof typedData + >(parameters: TypedDataDefinition): Promise { + const { message, primaryType, types: _types, domain } = parameters + + if (!domain) throw new Error("Missing domain") + if (!message) throw new Error("Missing message") + const types = { - EIP712Domain: getTypesForEIP712Domain({ - domain: typedData.domain - }), - ...typedData.types + EIP712Domain: getTypesForEIP712Domain({ domain }), + ..._types } + // @ts-ignore: Comes from nexus parent typehash + const messageStuff: Hex = message.stuff + + // @ts-ignore validateTypedData({ - domain: typedData.domain, - message: typedData.message, - primaryType: typedData.primaryType, + domain, + message, + primaryType, types - } as TypedDataDefinition) - - const appDomainSeparator = domainSeparator({ - domain: { - name: typedData.domain.name, - version: typedData.domain.version, - chainId: typedData.domain.chainId, - verifyingContract: typedData.domain.verifyingContract - } }) + const appDomainSeparator = domainSeparator({ domain }) const accountDomainStructFields = await getAccountDomainStructFields( masterClient as unknown as PublicClient, await getAddress() @@ -408,14 +409,14 @@ export const toNexusAccount = async ( [ encodeAbiParameters(parseAbiParameters(["bytes32, bytes32"]), [ keccak256(toBytes(PARENT_TYPEHASH)), - typedData.message.stuff + messageStuff ]), accountDomainStructFields ] ) ) - const wrappedTypedHash = await eip712WrapHash( + const wrappedTypedHash = eip712WrapHash( parentStructHash, appDomainSeparator ) @@ -424,12 +425,12 @@ export const toNexusAccount = async ( toBytes(wrappedTypedHash) ) - const contentsType = toBytes(typeToString(types)[1]) + const contentsType = toBytes(typeToString(types as TypedDataWith712)[1]) const signatureData = concatHex([ signature, appDomainSeparator, - typedData.message.stuff, + messageStuff, toHex(contentsType), toHex(contentsType.length, { size: 2 }) ]) diff --git a/packages/sdk/account/utils/EthersSigner.ts b/packages/sdk/account/utils/EthersSigner.ts deleted file mode 100644 index bed5708bd..000000000 --- a/packages/sdk/account/utils/EthersSigner.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { Hex, SignableMessage } from "viem" -import type { LightSigner, SmartAccountSigner } from "./Types.js" - -export class EthersSigner - implements SmartAccountSigner -{ - signerType = "ethers" - - inner: T - - constructor(inner: T, signerType: string) { - this.inner = inner - this.signerType = signerType - } - - async getAddress() { - return (await this.inner.getAddress()) as Hex - } - - async signMessage(_message: SignableMessage): Promise { - const message = typeof _message === "string" ? _message : _message.raw - const signature = await this.inner?.signMessage(message) - return this.#correctSignature(signature as Hex) - } - - // biome-ignore lint/suspicious/noExplicitAny: - async signTypedData(_: any): Promise { - throw new Error("signTypedData is not supported for Ethers Signer") - } - - #correctSignature = (_signature: Hex): Hex => { - let signature = _signature - const potentiallyIncorrectV = Number.parseInt(signature.slice(-2), 16) - if (![27, 28].includes(potentiallyIncorrectV)) { - const correctV = potentiallyIncorrectV + 27 - signature = signature.slice(0, -2) + correctV.toString(16) - } - return signature as Hex - } -} - -export default EthersSigner diff --git a/packages/sdk/account/utils/HttpRequests.ts b/packages/sdk/account/utils/HttpRequests.ts deleted file mode 100644 index 474b12e70..000000000 --- a/packages/sdk/account/utils/HttpRequests.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Logger } from "./Logger.js" -import type { Service } from "./Types.js" -import { getAAError } from "./getAAError.js" - -export enum HttpMethod { - Get = "get", - Post = "post", - Delete = "delete" -} - -export interface HttpRequest { - url: string - method: HttpMethod - // biome-ignore lint/suspicious/noExplicitAny: - body?: Record -} - -export async function sendRequest( - { url, method, body }: HttpRequest, - service: Service -): Promise { - const stringifiedBody = JSON.stringify(body) - - Logger.log(`${service} RPC Request`, { url, body: stringifiedBody }) - - const response = await fetch(url, { - method, - headers: { - Accept: "application/json", - "Content-Type": "application/json" - }, - body: stringifiedBody - }) - - // biome-ignore lint/suspicious/noExplicitAny: - let jsonResponse: any - try { - jsonResponse = await response.json() - Logger.log(`${service} RPC Response`, jsonResponse) - } catch (error) { - if (!response.ok) { - throw await getAAError(response.statusText, response.status, service) - } - } - - if (response.ok) { - return jsonResponse as T - } - if (jsonResponse.error) { - throw await getAAError( - `Error coming from ${service}: ${jsonResponse.error.message}` - ) - } - if (jsonResponse.message) { - throw await getAAError(jsonResponse.message, response.status, service) - } - if (jsonResponse.msg) { - throw await getAAError(jsonResponse.msg, response.status, service) - } - if (jsonResponse.data) { - throw await getAAError(jsonResponse.data, response.status, service) - } - if (jsonResponse.detail) { - throw await getAAError(jsonResponse.detail, response.status, service) - } - if (jsonResponse.message) { - throw await getAAError(jsonResponse.message, response.status, service) - } - if (jsonResponse.nonFieldErrors) { - throw await getAAError( - jsonResponse.nonFieldErrors, - response.status, - service - ) - } - if (jsonResponse.delegate) { - throw await getAAError(jsonResponse.delegate, response.status, service) - } - throw await getAAError(response.statusText, response.status, service) -} diff --git a/packages/sdk/account/utils/Types.ts b/packages/sdk/account/utils/Types.ts index 3bf528760..b36dbe2b8 100644 --- a/packages/sdk/account/utils/Types.ts +++ b/packages/sdk/account/utils/Types.ts @@ -1,20 +1,8 @@ -import type { - Address, - Chain, - Hash, - Hex, - Log, - PrivateKeyAccount, - PublicClient, - SignTypedDataParameters, - SignableMessage, - TypedData, - TypedDataDefinition, - WalletClient -} from "viem" +import type { Address, Hash, Hex, Log, SignTypedDataParameters } from "viem" import type { ModuleInfo, ModuleType } from "../../modules" import type { BaseValidationModule } from "../../modules/base/BaseValidationModule" import type { MODE_MODULE_ENABLE, MODE_VALIDATION } from "./Constants" +import type { Holder } from "./toHolder" export type EntryPointAddresses = Record export type BiconomyFactories = Record @@ -235,8 +223,6 @@ export interface GasOverheads { export type BaseSmartAccountConfig = { /** index: helps to not conflict with other smart account instances */ index?: bigint - /** provider: WalletClientSigner from viem */ - provider?: WalletClient /** entryPointAddress: address of the smart account entry point */ entryPointAddress?: string /** accountAddress: address of the smart account, potentially counterfactual */ @@ -276,21 +262,14 @@ export type ConditionalBundlerProps = RequireAtLeastOne< export type ResolvedBundlerProps = { bundler: IBundler } -export type ConditionalValidationProps = RequireAtLeastOne< - { - defaultValidationModule: BaseValidationModule - signer: SupportedSigner - }, - "defaultValidationModule" | "signer" -> export type ResolvedValidationProps = { /** defaultValidationModule: {@link BaseValidationModule} */ defaultValidationModule: BaseValidationModule /** activeValidationModule: {@link BaseValidationModule}. The active validation module. Will default to the defaultValidationModule */ activeValidationModule: BaseValidationModule - /** signer: ethers Wallet, viemWallet or alchemys SmartAccountSigner */ - signer: SmartAccountSigner + /** holder */ + holder: Holder /** rpcUrl */ rpcUrl: string } @@ -301,48 +280,6 @@ export type ConfigurationAddresses = { entryPointAddress: Hex } -export type NexusSmartAccountConfigBaseProps = { - /** chain: The chain from viem */ - chain: Chain - /** Factory address of biconomy factory contract or some other contract you have deployed on chain */ - factoryAddress?: Hex - /** K1Validator Address */ - k1ValidatorAddress?: Hex - /** Sender address: If you want to override the Signer address with some other address and get counterfactual address can use this to pass the EOA and get SA address */ - senderAddress?: Hex - /** implementation of smart contract address or some other contract you have deployed and want to override */ - implementationAddress?: Hex - /** defaultFallbackHandler: override the default fallback contract address */ - defaultFallbackHandler?: Hex - /** rpcUrl */ - rpcUrl?: string - /** paymasterUrl: The Paymaster URL retrieved from the Biconomy dashboard */ - paymasterUrl?: string - /** biconomyPaymasterApiKey: The API key retrieved from the Biconomy dashboard */ - biconomyPaymasterApiKey?: string - /** activeValidationModule: The active validation module. Will default to the defaultValidationModule */ - activeValidationModule?: BaseValidationModule - /** scanForUpgradedAccountsFromV1: set to true if you you want the userwho was using biconomy SA v1 to upgrade to biconomy SA v2 */ - scanForUpgradedAccountsFromV1?: boolean - /** the index of SA the EOA have generated and till which indexes the upgraded SA should scan */ - maxIndexForScan?: bigint - /** The initial code to be used for the smart account */ - initCode?: Hex - /** Used for session key manager module */ - sessionData?: ModuleInfo -} -export type NexusSmartAccountConfig = NexusSmartAccountConfigBaseProps & - BaseSmartAccountConfig & - ConditionalBundlerProps & - ConditionalValidationProps - -export type NexusSmartAccountConfigConstructorProps = - NexusSmartAccountConfigBaseProps & - BaseSmartAccountConfig & - ResolvedBundlerProps & - ResolvedValidationProps & - ConfigurationAddresses - /** * Represents options for building a user operation. * @typedef BuildUserOpOptions @@ -530,12 +467,6 @@ export type Signer = LightSigner & { provider: any } export type SupportedSignerName = "alchemy" | "ethers" | "viem" -export type SupportedSigner = - | SmartAccountSigner - | WalletClient - | Signer - | LightSigner - | PrivateKeyAccount export type Service = "Bundler" | "Paymaster" export interface LightSigner { @@ -580,38 +511,6 @@ export type UserOperationStruct = { } //#endregion UserOperationStruct -//#region SmartAccountSigner -/** - * A signer that can sign messages and typed data. - * - * @template Inner - the generic type of the inner client that the signer wraps to provide functionality such as signing, etc. - * - * @var signerType - the type of the signer (e.g. local, hardware, etc.) - * @var inner - the inner client of @type {Inner} - * - * @method getAddress - get the address of the signer - * @method signMessage - sign a message - * @method signTypedData - sign typed data - */ - -// biome-ignore lint/suspicious/noExplicitAny: -export interface SmartAccountSigner { - signerType: string - inner: Inner - - getAddress: () => Promise
- - signMessage: (message: SignableMessage) => Promise - - signTypedData: < - const TTypedData extends TypedData | { [key: string]: unknown }, - TPrimaryType extends string = string - >( - params: TypedDataDefinition - ) => Promise -} -//#endregion SmartAccountSigner - //#region UserOperationCallData export type UserOperationCallData = | { @@ -631,162 +530,6 @@ export type BatchUserOperationCallData = Exclude[] export type SignTypedDataParams = Omit -export type BaseSmartContractAccountProps = - NexusSmartAccountConfigConstructorProps & { - /** chain: The chain from viem */ - chain: Chain - /** factoryAddress: The address of the factory */ - factoryAddress: Hex - /** entryPointAddress: The address of the entry point */ - entryPointAddress: Hex - /** accountAddress: The address of the account */ - accountAddress?: Address - } - -export interface ISmartContractAccount< - TSigner extends SmartAccountSigner = SmartAccountSigner -> { - /** - * The RPC provider the account uses to make RPC calls - */ - publicClient: PublicClient - - /** - * @returns the init code for the account - */ - getInitCode(): Promise - - /** - * This is useful for estimating gas costs. It should return a signature that doesn't cause the account to revert - * when validation is run during estimation. - * - * @returns a dummy signature that doesn't cause the account to revert during estimation - */ - getDummySignature(): Hex - - /** - * Encodes a call to the account's execute function. - * - * @param target - the address receiving the call data - * @param value - optionally the amount of native token to send - * @param data - the call data or "0x" if empty - */ - encodeExecute(transaction: Call, useExecutor: boolean): Promise - - /** - * Encodes a batch of transactions to the account's batch execute function. - * NOTE: not all accounts support batching. - * @param txs - An Array of objects containing the target, value, and data for each transaction - * @returns the encoded callData for a UserOperation - */ - encodeBatchExecute(txs: BatchUserOperationCallData): Promise - - /** - * @returns the nonce of the account - */ - getNonce( - validationMode?: typeof MODE_VALIDATION | typeof MODE_MODULE_ENABLE - ): Promise - - /** - * If your account handles 1271 signatures of personal_sign differently - * than it does UserOperations, you can implement two different approaches to signing - * - * @param uoHash -- The hash of the UserOperation to sign - * @returns the signature of the UserOperation - */ - signUserOperationHash(uoHash: Hash): Promise - - /** - * Returns a signed and prefixed message. - * - * @param msg - the message to sign - * @returns the signature of the message - */ - signMessage(msg: string | Uint8Array | Hex): Promise - - /** - * Signs a typed data object as per ERC-712 - * - * @param typedData - * @returns the signed hash for the message passed - */ - - signTypedData(typedData: SignTypedDataParams): Promise - - /** - * If the account is not deployed, it will sign the message and then wrap it in 6492 format - * - * @param msg - the message to sign - * @returns ths signature wrapped in 6492 format - */ - signMessageWith6492(msg: string | Uint8Array | Hex): Promise - - /** - * If the account is not deployed, it will sign the typed data blob and then wrap it in 6492 format - * - * @param params - {@link SignTypedDataParams} - * @returns the signed hash for the params passed in wrapped in 6492 format - */ - signTypedDataWith6492(params: SignTypedDataParams): Promise - - /** - * @returns the address of the account - */ - getAddress(): Promise
- - /** - * @returns the current account signer instance that the smart account client - * operations are being signed with. - * - * The signer is expected to be the owner or one of the owners of the account - * for the signatures to be valid for the acting account. - */ - getSigner(): TSigner - - /** - * @returns the address of the factory contract for the smart account - */ - getFactoryAddress(): Address - - /** - * @returns the address of the entry point contract for the smart account - */ - getEntryPointAddress(): Address - - /** - * Allows you to add additional functionality and utility methods to this account - * via a decorator pattern. - * - * NOTE: this method does not allow you to override existing methods on the account. - * - * @example - * ```ts - * const account = new BaseSmartCobntractAccount(...).extend((account) => ({ - * readAccountState: async (...args) => { - * return this.rpcProvider.readContract({ - * address: await this.getAddress(), - * abi: ThisContractsAbi - * args: args - * }); - * } - * })); - * - * account.debugSendUserOperation(...); - * ``` - * - * @param extendFn -- this function gives you access to the created account instance and returns an object - * with the extension methods - * @returns -- the account with the extension methods added - */ - extend: (extendFn: (self: this) => R) => this & R - - encodeUpgradeToAndCall: ( - upgradeToImplAddress: Address, - upgradeToInitData: Hex - ) => Promise -} - export type TransferOwnershipCompatibleModule = | "0x0000001c5b32F37F5beA87BDD5374eB2aC54eA8e" | "0x000000824dc138db84FD9109fc154bdad332Aa8E" diff --git a/packages/sdk/account/utils/Utils.ts b/packages/sdk/account/utils/Utils.ts index fdd27d33b..a0c024c7b 100644 --- a/packages/sdk/account/utils/Utils.ts +++ b/packages/sdk/account/utils/Utils.ts @@ -4,6 +4,7 @@ import { type Hash, type Hex, type PublicClient, + type TypedData, type TypedDataDomain, type TypedDataParameter, concat, @@ -33,7 +34,6 @@ import { type ModuleType, moduleTypeIds } from "../../modules/utils/Types" import type { AccountMetadata, EIP712DomainReturn, - TypeDefinition, UserOperationStruct } from "./Types" @@ -289,15 +289,24 @@ export const accountMetadata = async ( export const eip712WrapHash = (typedHash: Hex, appDomainSeparator: Hex): Hex => keccak256(concat(["0x1901", appDomainSeparator, typedHash])) -export function typeToString(typeDef: TypeDefinition): string[] { +export type TypedDataWith712 = { + EIP712Domain: TypedDataParameter[] +} & TypedData + +export function typeToString(typeDef: TypedDataWith712): string[] { return Object.entries(typeDef).map(([key, fields]) => { - const fieldStrings = fields + const fieldStrings = (fields ?? []) .map((field) => `${field.type} ${field.name}`) .join(",") return `${key}(${fieldStrings})` }) } +/** @ignore */ +export function bigIntReplacer(_key: string, value: any): any { + return typeof value === "bigint" ? value.toString() : value +} + export const getAccountDomainStructFields = async ( publicClient: PublicClient, accountAddress: Address diff --git a/packages/sdk/account/utils/convertSigner.ts b/packages/sdk/account/utils/convertSigner.ts deleted file mode 100644 index ec169c5ad..000000000 --- a/packages/sdk/account/utils/convertSigner.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { - http, - type PrivateKeyAccount, - type WalletClient, - createWalletClient -} from "viem" -import { ERROR_MESSAGES, WalletClientSigner } from "../index.js" -import type { Signer, SmartAccountSigner, SupportedSigner } from "../index.js" -import { EthersSigner } from "./EthersSigner.js" - -interface SmartAccountResult { - signer: SmartAccountSigner -} - -function isPrivateKeyAccount( - signer: SupportedSigner -): signer is PrivateKeyAccount { - return (signer as PrivateKeyAccount).type === "local" -} - -export function isWalletClient( - signer: SupportedSigner -): signer is WalletClient { - return (signer as WalletClient).name === "Wallet Client" -} - -function isEthersSigner(signer: SupportedSigner): signer is Signer { - return (signer as Signer).provider !== undefined -} - -function isAlchemySigner( - signer: SupportedSigner -): signer is SmartAccountSigner { - return (signer as SmartAccountSigner).signerType !== undefined -} - -export const convertSigner = async ( - signer: SupportedSigner, - rpcUrl?: string -): Promise => { - let resolvedSmartAccountSigner: SmartAccountSigner - - if (!isAlchemySigner(signer)) { - if (isEthersSigner(signer)) { - const ethersSigner = signer as Signer - if (!rpcUrl) throw new Error(ERROR_MESSAGES.MISSING_RPC_URL) - if (!ethersSigner.provider) { - throw new Error("Cannot consume an ethers Wallet without a provider") - } - // convert ethers Wallet to alchemy's SmartAccountSigner under the hood - resolvedSmartAccountSigner = new EthersSigner(ethersSigner, "ethers") - } else if (isWalletClient(signer)) { - const walletClient = signer as WalletClient - if (!walletClient.account) { - throw new Error("Cannot consume a viem wallet without an account") - } - // convert viems walletClient to alchemy's SmartAccountSigner under the hood - resolvedSmartAccountSigner = new WalletClientSigner(walletClient, "viem") - } else if (isPrivateKeyAccount(signer)) { - if (!rpcUrl) throw new Error(ERROR_MESSAGES.MISSING_RPC_URL) - const walletClient = createWalletClient({ - account: signer as PrivateKeyAccount, - transport: http(rpcUrl) - }) - resolvedSmartAccountSigner = new WalletClientSigner(walletClient, "viem") - } else { - throw new Error("Unsupported signer") - } - } else { - if (!rpcUrl) throw new Error(ERROR_MESSAGES.MISSING_RPC_URL) - resolvedSmartAccountSigner = signer as SmartAccountSigner - } - return { - signer: resolvedSmartAccountSigner - } -} diff --git a/packages/sdk/account/utils/index.ts b/packages/sdk/account/utils/index.ts index b1f3d8378..36c7543f6 100644 --- a/packages/sdk/account/utils/index.ts +++ b/packages/sdk/account/utils/index.ts @@ -1,8 +1,6 @@ export * from "./Types.js" export * from "./Utils.js" export * from "./Constants.js" -export * from "./convertSigner.js" export * from "./getChain.js" export * from "./Logger.js" -export * from "./HttpRequests.js" -export * from "./EthersSigner.js" +export * from "./toHolder.js" diff --git a/packages/sdk/account/utils/toHolder.ts b/packages/sdk/account/utils/toHolder.ts new file mode 100644 index 000000000..94d2948fa --- /dev/null +++ b/packages/sdk/account/utils/toHolder.ts @@ -0,0 +1,85 @@ +import { + type Account, + type Address, + type Chain, + type EIP1193Provider, + type EIP1193RequestFn, + type EIP1474Methods, + type LocalAccount, + type OneOf, + type Transport, + type WalletClient, + createWalletClient, + custom +} from "viem" +import { toAccount } from "viem/accounts" + +import { signTypedData } from "viem/actions" +import { getAction } from "viem/utils" + +export type Holder = LocalAccount +export type UnknownHolder = OneOf< + | EIP1193Provider + | WalletClient + | LocalAccount +> +export async function toHolder({ + holder, + address +}: { + holder: UnknownHolder + address?: Address +}): Promise { + if ("type" in holder && holder.type === "local") { + return holder as LocalAccount + } + + let walletClient: + | WalletClient + | undefined = undefined + + if ("request" in holder) { + if (!address) { + try { + ;[address] = await (holder.request as EIP1193RequestFn)( + { + method: "eth_requestAccounts" + } + ) + } catch { + ;[address] = await (holder.request as EIP1193RequestFn)( + { + method: "eth_accounts" + } + ) + } + } + if (!address) throw new Error("address required") + + walletClient = createWalletClient({ + account: address, + transport: custom(holder as EIP1193Provider) + }) + } + + if (!walletClient) { + walletClient = holder as WalletClient + } + + return toAccount({ + address: walletClient.account.address, + async signMessage({ message }) { + return walletClient.signMessage({ message }) + }, + async signTypedData(typedData) { + return getAction( + walletClient, + signTypedData, + "signTypedData" + )(typedData as any) + }, + async signTransaction(_) { + throw new Error("Not supported") + } + }) +} diff --git a/packages/sdk/clients/createBicoBundlerClient.test.ts b/packages/sdk/clients/createBicoBundlerClient.test.ts index d09869290..2592ff0d0 100644 --- a/packages/sdk/clients/createBicoBundlerClient.test.ts +++ b/packages/sdk/clients/createBicoBundlerClient.test.ts @@ -34,7 +34,7 @@ describe("bico.bundler", async () => { testClient = toTestClient(chain, getTestAccount(5)) nexusAccount = await toNexusAccount({ - owner: account, + holder: account, chain, transport: http() }) diff --git a/packages/sdk/clients/createNexusClient.test.ts b/packages/sdk/clients/createNexusClient.test.ts index f1c7d208d..90f3f661b 100644 --- a/packages/sdk/clients/createNexusClient.test.ts +++ b/packages/sdk/clients/createNexusClient.test.ts @@ -60,7 +60,7 @@ describe("nexus.client", async () => { testClient = toTestClient(chain, getTestAccount(5)) nexusClient = await createNexusClient({ - owner: account, + holder: account, chain, transport: http(), bundlerTransport: http(bundlerUrl) diff --git a/packages/sdk/clients/createNexusClient.ts b/packages/sdk/clients/createNexusClient.ts index 6f989c60c..4611c2de2 100644 --- a/packages/sdk/clients/createNexusClient.ts +++ b/packages/sdk/clients/createNexusClient.ts @@ -1,6 +1,5 @@ import { http, - type Account, type Address, type Chain, type Client, @@ -23,6 +22,7 @@ import contracts from "../__contracts" import type { Call } from "../account/utils/Types" import { type NexusAccount, toNexusAccount } from "../account/toNexusAccount" +import type { UnknownHolder } from "../account/utils/toHolder" import type { BaseExecutionModule } from "../modules/base/BaseExecutionModule" import type { BaseValidationModule } from "../modules/base/BaseValidationModule" import { type Erc7579Actions, erc7579Actions } from "./decorators/erc7579" @@ -109,7 +109,7 @@ export type NexusClientConfig< } | undefined /** Owner of the account. */ - owner: Address | Account + holder: UnknownHolder /** Index of the account. */ index?: bigint /** Active module of the account. */ @@ -128,7 +128,7 @@ export async function createNexusClient( const { client: client_, chain = parameters.chain ?? client_?.chain, - owner, + holder, index = 0n, key = "nexus client", name = "Nexus Client", @@ -158,7 +158,7 @@ export async function createNexusClient( const nexusAccount = await toNexusAccount({ transport, chain, - owner, + holder, index, activeModule, executorModule, @@ -167,6 +167,7 @@ export async function createNexusClient( }) const bundler = createBundlerClient({ + ...parameters, key, name, account: nexusAccount, diff --git a/packages/sdk/clients/decorators/erc7579/erc7579.actions.test.ts b/packages/sdk/clients/decorators/erc7579/erc7579.actions.test.ts index c4432a449..e8d5c7cc5 100644 --- a/packages/sdk/clients/decorators/erc7579/erc7579.actions.test.ts +++ b/packages/sdk/clients/decorators/erc7579/erc7579.actions.test.ts @@ -37,7 +37,7 @@ describe("erc7579.decorators", async () => { testClient = toTestClient(chain, getTestAccount(5)) nexusClient = await createNexusClient({ - owner: account, + holder: account, chain, transport: http(), bundlerTransport: http(bundlerUrl) diff --git a/packages/sdk/clients/decorators/smartAccount/erc7579.actions.test.ts b/packages/sdk/clients/decorators/smartAccount/erc7579.actions.test.ts index ee5a3bd05..7dfa9c8d8 100644 --- a/packages/sdk/clients/decorators/smartAccount/erc7579.actions.test.ts +++ b/packages/sdk/clients/decorators/smartAccount/erc7579.actions.test.ts @@ -38,7 +38,7 @@ describe("account.decorators", async () => { testClient = toTestClient(chain, getTestAccount(5)) nexusClient = await createNexusClient({ - owner: account, + holder: account, chain, transport: http(), bundlerTransport: http(bundlerUrl) diff --git a/packages/sdk/modules/base/BaseModule.ts b/packages/sdk/modules/base/BaseModule.ts index 21f9a8915..7b6e9d216 100644 --- a/packages/sdk/modules/base/BaseModule.ts +++ b/packages/sdk/modules/base/BaseModule.ts @@ -1,6 +1,6 @@ import { type Address, type Hex, encodeFunctionData, parseAbi } from "viem" import contracts from "../../__contracts/index.js" -import type { SmartAccountSigner } from "../../account/index.js" +import type { Holder } from "../../account/utils/toHolder.js" import type { Module } from "../../clients/decorators/erc7579/index.js" import { type ModuleType, @@ -16,15 +16,15 @@ export abstract class BaseModule { hook?: Address version: ModuleVersion = "1.0.0-beta" entryPoint: Address = contracts.entryPoint.address - signer: SmartAccountSigner + holder: Holder - constructor(module: Module, signer: SmartAccountSigner) { + constructor(module: Module, holder: Holder) { this.address = module.address this.context = module.context ?? "0x" this.additionalContext = module.additionalContext ?? "0x" this.hook = module.hook this.type = module.type - this.signer = signer + this.holder = holder } public installModule(): Hex { diff --git a/packages/sdk/modules/base/BaseValidationModule.ts b/packages/sdk/modules/base/BaseValidationModule.ts index 2d7625a45..6bc74508d 100644 --- a/packages/sdk/modules/base/BaseValidationModule.ts +++ b/packages/sdk/modules/base/BaseValidationModule.ts @@ -1,10 +1,10 @@ import { type Hex, getAddress } from "viem" -import type { SmartAccountSigner } from "../../account/index.js" +import type { Holder } from "../../account/utils/toHolder.js" import { BaseModule } from "./BaseModule.js" export abstract class BaseValidationModule extends BaseModule { - public getSigner(): SmartAccountSigner { - return this.signer + public getHolder(): Holder { + return this.holder } getDummySignature(): Hex { @@ -19,16 +19,18 @@ export abstract class BaseValidationModule extends BaseModule { } async signUserOpHash(userOpHash: string): Promise { - const signature = await this.signer.signMessage({ raw: userOpHash as Hex }) + const signature = await this.holder.signMessage({ + message: { raw: userOpHash as Hex } + }) return signature as Hex } - async signMessageSmartAccountSigner( + async signMessageHolder( _message: string | Uint8Array, - signer: SmartAccountSigner + holder: Holder ): Promise { const message = typeof _message === "string" ? _message : { raw: _message } - let signature: `0x${string}` = await signer.signMessage(message) + let signature: `0x${string}` = await holder.signMessage({ message }) const potentiallyIncorrectV = Number.parseInt(signature.slice(-2), 16) if (![27, 28].includes(potentiallyIncorrectV)) { @@ -40,15 +42,15 @@ export abstract class BaseValidationModule extends BaseModule { } /** - * Signs a message using the appropriate method based on the type of signer. + * Signs a message using the appropriate method based on the type of holder. * * @param {Uint8Array | string} message - The message to be signed. * @returns {Promise} A promise resolving to the signature or error message. - * @throws {Error} If the signer type is invalid or unsupported. + * @throws {Error} If the holder type is invalid or unsupported. */ async signMessage(_message: Uint8Array | string): Promise { const message = typeof _message === "string" ? _message : { raw: _message } - let signature = await this.signer.signMessage(message) + let signature = await this.holder.signMessage({ message }) const potentiallyIncorrectV = Number.parseInt(signature.slice(-2), 16) if (![27, 28].includes(potentiallyIncorrectV)) { diff --git a/packages/sdk/modules/executors/OwnableExecutor.ts b/packages/sdk/modules/executors/OwnableExecutor.ts index 3e923082b..fd9b94d9e 100644 --- a/packages/sdk/modules/executors/OwnableExecutor.ts +++ b/packages/sdk/modules/executors/OwnableExecutor.ts @@ -1,8 +1,11 @@ import { + type Account, type Address, + type Chain, type Hash, type Hex, type PublicClient, + type Transport, type WalletClient, encodeAbiParameters, encodeFunctionData, @@ -10,13 +13,12 @@ import { getAddress, parseAbi } from "viem" -import { WalletClientSigner } from "../../account/signers/wallet-client" import { SENTINEL_ADDRESS } from "../../account/utils/Constants" +import { type Holder, toHolder } from "../../account/utils/toHolder" import type { NexusClient } from "../../clients/createNexusClient" import type { Module } from "../../clients/decorators/erc7579" import { BaseExecutionModule } from "../base/BaseExecutionModule" import type { Execution } from "../utils/Types" - export class OwnableExecutorModule extends BaseExecutionModule { public nexusClient: NexusClient public owners: Address[] @@ -26,12 +28,10 @@ export class OwnableExecutorModule extends BaseExecutionModule { module: Module, nexusClient: NexusClient, owners: Address[], - address: Address + address: Address, + holder: Holder ) { - super( - module, - new WalletClientSigner(nexusClient.account.client as WalletClient, "viem") - ) + super(module, holder) this.nexusClient = nexusClient this.owners = owners this.context = module.context ?? "0x" @@ -59,11 +59,15 @@ export class OwnableExecutorModule extends BaseExecutionModule { functionName: "getOwners", args: [await nexusClient.account.getAddress()] }) + const holder = await toHolder({ holder: nexusClient.account.client } as { + holder: WalletClient + }) return new OwnableExecutorModule( module, nexusClient, owners as Address[], - address + address, + holder ) } diff --git a/packages/sdk/modules/interfaces/IValidationModule.ts b/packages/sdk/modules/interfaces/IValidationModule.ts index fd451989d..1ab6b5c67 100644 --- a/packages/sdk/modules/interfaces/IValidationModule.ts +++ b/packages/sdk/modules/interfaces/IValidationModule.ts @@ -1,10 +1,10 @@ import type { Hex } from "viem" -import type { SmartAccountSigner } from "../../account/utils/Types" +import type { Holder } from "../../account/utils/toHolder" export interface IValidationModule { getAddress(): Hex getInitData(): Promise - getSigner(): Promise + getHolder(): Promise signUserOpHash(_userOpHash: string): Promise signMessage(_message: string | Uint8Array): Promise getDummySignature(): Promise diff --git a/packages/sdk/modules/smart.sessions.test.ts b/packages/sdk/modules/smart.sessions.test.ts index 5b6ea8e9c..de07b3101 100644 --- a/packages/sdk/modules/smart.sessions.test.ts +++ b/packages/sdk/modules/smart.sessions.test.ts @@ -40,7 +40,7 @@ describe("smart.sessions", async () => { testClient = toTestClient(chain, getTestAccount(5)) nexusClient = await createNexusClient({ - owner: account, + holder: account, chain, transport: http(), bundlerTransport: http(bundlerUrl) diff --git a/packages/sdk/modules/utils/Types.ts b/packages/sdk/modules/utils/Types.ts index 3519ea962..ba755135e 100644 --- a/packages/sdk/modules/utils/Types.ts +++ b/packages/sdk/modules/utils/Types.ts @@ -1,10 +1,7 @@ import type { Address, Chain, Hex } from "viem" -import type { - SimulationType, - SmartAccountSigner, - SupportedSigner, - UserOperationStruct -} from "../../account/utils/Types" +import type { SimulationType } from "../../account/utils/Types" +import type { Holder, UnknownHolder } from "../../account/utils/toHolder" + export type ModuleVersion = "1.0.0-beta" // | 'V1_0_1' export interface BaseValidationModuleConfig { @@ -18,7 +15,7 @@ export interface K1ValidationModuleConfig extends BaseValidationModuleConfig { /** Version of the module */ version?: ModuleVersion /** Signer: viemWallet or ethers signer. Ingested when passed into smartAccount */ - signer: SupportedSigner + signer: UnknownHolder } export interface K1ValidatorModuleConfigConstructorProps @@ -27,41 +24,8 @@ export interface K1ValidatorModuleConfigConstructorProps 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 -// /** SmartAccount address */ -// smartAccountAddress: Hex -// storageType?: StorageType -// sessionStorageClient?: ISessionStorage -// } - -// export interface BatchedSessionRouterModuleConfig -// extends BaseValidationModuleConfig { -// /** Address of the module */ -// moduleAddress?: Hex -// /** Version of the module */ -// version?: ModuleVersion -// /** Session Key Manager module: Could be BaseValidationModule */ -// sessionKeyManagerModule?: SessionKeyManagerModule -// /** Session Key Manager module address */ -// sessionManagerModuleAddress?: Hex -// /** Address of the associated smart account */ -// smartAccountAddress: Hex -// /** Storage type, e.g. local storage */ -// storageType?: StorageType -// } - -export enum StorageType { - LOCAL_STORAGE = 0, - MEMORY_STORAGE = 1 + /** Signer: Converted from viemWallet or ethers signer to Holder */ + holder: Holder } export type SessionDataTuple = [ @@ -77,7 +41,7 @@ export type SessionParams = { /** ID of the session */ sessionID?: string /** Session Signer: viemWallet or ethers signer. Ingested when passed into smartAccount */ - sessionSigner: SupportedSigner + sessionSigner: UnknownHolder /** 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 */ @@ -86,7 +50,7 @@ export type SessionParams = { export type StrictSessionParams = { sessionID: string - sessionSigner: SupportedSigner + sessionSigner: UnknownHolder } export type ModuleInfo = { @@ -94,7 +58,7 @@ export type ModuleInfo = { // sessionParams?: SessionParams[] // where SessionParams is below four sessionID?: string /** Session Signer: viemWallet or ethers signer. Ingested when passed into smartAccount */ - sessionSigner?: SupportedSigner + sessionHolder?: UnknownHolder /** 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 */ @@ -144,7 +108,7 @@ export interface MultiChainValidationModuleConfig /** Version of the module */ version?: ModuleVersion /** Signer: viemWallet or ethers signer. Ingested when passed into smartAccount */ - signer: SupportedSigner + signer: UnknownHolder } export interface MultiChainValidationModuleConfigConstructorProps extends BaseValidationModuleConfig { @@ -153,16 +117,7 @@ export interface MultiChainValidationModuleConfigConstructorProps /** 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 + holder: Holder } export interface BaseSessionKeyData { diff --git a/packages/sdk/modules/validators/K1ValidatorModule.ts b/packages/sdk/modules/validators/K1ValidatorModule.ts index 3c51e6b9b..eb9f7415f 100644 --- a/packages/sdk/modules/validators/K1ValidatorModule.ts +++ b/packages/sdk/modules/validators/K1ValidatorModule.ts @@ -1,25 +1,25 @@ import addresses from "../../__contracts/addresses.js" -import type { SmartAccountSigner } from "../../account/index.js" +import type { Holder } from "../../account/utils/toHolder.js" import type { Module } from "../../clients/decorators/erc7579/index.js" import { BaseValidationModule } from "../base/BaseValidationModule.js" export class K1ValidatorModule extends BaseValidationModule { // biome-ignore lint/complexity/noUselessConstructor: - public constructor(moduleConfig: Module, signer: SmartAccountSigner) { - super(moduleConfig, signer) + public constructor(moduleConfig: Module, holder: Holder) { + super(moduleConfig, holder) } public static async create( - signer: SmartAccountSigner, + holder: Holder, k1ValidatorAddress = addresses.K1Validator ): Promise { const module: Module = { address: k1ValidatorAddress, type: "validator", - context: await signer.getAddress(), + context: holder.address, additionalContext: "0x" } - const instance = new K1ValidatorModule(module, signer) + const instance = new K1ValidatorModule(module, holder) return instance } } diff --git a/packages/sdk/modules/validators/ValidationModule.ts b/packages/sdk/modules/validators/ValidationModule.ts index e75c627bc..4a57b9ce1 100644 --- a/packages/sdk/modules/validators/ValidationModule.ts +++ b/packages/sdk/modules/validators/ValidationModule.ts @@ -1,15 +1,15 @@ import type { Address, Hex } from "viem" -import type { SmartAccountSigner } from "../../account/index.js" +import type { Holder } from "../../account/utils/toHolder.js" import type { Module } from "../../clients/decorators/erc7579/index.js" import { BaseValidationModule } from "../base/BaseValidationModule.js" export class ValidationModule extends BaseValidationModule { - private constructor(moduleConfig: Module, signer: SmartAccountSigner) { - super(moduleConfig, signer) + private constructor(moduleConfig: Module, holder: Holder) { + super(moduleConfig, holder) } public static async create( - signer: SmartAccountSigner, + holder: Holder, address: Address, context: Hex ): Promise { @@ -19,7 +19,7 @@ export class ValidationModule extends BaseValidationModule { context, additionalContext: "0x" } - const instance = new ValidationModule(module, signer) + const instance = new ValidationModule(module, holder) return instance } } diff --git a/packages/sdk/modules/validators/k1Validator.test.ts b/packages/sdk/modules/validators/k1Validator.test.ts index 95090acb1..e50d06928 100644 --- a/packages/sdk/modules/validators/k1Validator.test.ts +++ b/packages/sdk/modules/validators/k1Validator.test.ts @@ -40,7 +40,7 @@ describe("modules.k1Validator.write", async () => { testClient = toTestClient(chain, getTestAccount(5)) nexusClient = await createNexusClient({ - owner: account, + holder: account, chain, transport: http(), bundlerTransport: http(bundlerUrl) @@ -109,7 +109,6 @@ describe("modules.k1Validator.write", async () => { const byteCode = await testClient.getCode({ address: addresses.K1Validator }) - console.log({ byteCode }) const hash = await nexusClient.uninstallModule({ module: { diff --git a/packages/test/playground.test.ts b/packages/test/playground.test.ts index 776006bfc..176280202 100644 --- a/packages/test/playground.test.ts +++ b/packages/test/playground.test.ts @@ -74,7 +74,7 @@ describe.skipIf(!playgroundTrue)("playground", () => { test("should init the smart account", async () => { nexusClient = await createNexusClient({ - owner: account, + holder: account, chain, transport: http(), bundlerTransport: http(bundlerUrl), @@ -141,7 +141,7 @@ describe.skipIf(!playgroundTrue)("playground", () => { } nexusClient = await createNexusClient({ - owner: account, + holder: account, chain, transport: http(), bundlerTransport: http(bundlerUrl), diff --git a/packages/test/testUtils.ts b/packages/test/testUtils.ts index 1554c4198..f43290be6 100644 --- a/packages/test/testUtils.ts +++ b/packages/test/testUtils.ts @@ -310,7 +310,7 @@ export const toFundedTestClients = async ({ const testClient = toTestClient(chain, getTestAccount()) const nexus = await createNexusClient({ - owner: account, + holder: account, transport: http(), bundlerTransport: http(bundlerUrl), chain diff --git a/scripts/send:userOp.ts b/scripts/send:userOp.ts index 8592219ec..6d9133450 100644 --- a/scripts/send:userOp.ts +++ b/scripts/send:userOp.ts @@ -49,7 +49,7 @@ const accountTwo = privateKeyToAccount(`0x${privateKeyTwo}`) const recipient = accountTwo.address const nexusClient = await createNexusClient({ - owner: account, + holder: account, chain, transport: http(), bundlerTransport: http(bundlerUrl), diff --git a/scripts/viem:bundler.ts b/scripts/viem:bundler.ts index d28353140..d2c54b67c 100644 --- a/scripts/viem:bundler.ts +++ b/scripts/viem:bundler.ts @@ -1,6 +1,7 @@ import { http, type PublicClient, createPublicClient, parseEther } from "viem" import { privateKeyToAccount } from "viem/accounts" import { toNexusAccount } from "../packages/sdk/account/toNexusAccount" +import { bigIntReplacer } from "../packages/sdk/account/utils/Utils" import { getChain } from "../packages/sdk/account/utils/getChain" import { createBicoBundlerClient } from "../packages/sdk/clients/createBicoBundlerClient" @@ -61,7 +62,7 @@ const publicClient = createPublicClient({ const main = async () => { const nexusAccount = await toNexusAccount({ - owner: account, + holder: account, chain, transport: http(), k1ValidatorAddress, @@ -108,8 +109,12 @@ const main = async () => { }) ]) console.timeEnd("read methods") + + const successCount = results.filter((result) => result.status === "fulfilled") console.log( - `${results}: running the ${usesAltoBundler ? "Alto" : "Bico"} bundler` + `running the ${usesAltoBundler ? "Alto" : "Bico"} bundler with ${ + successCount.length + } successful calls` ) console.time("write methods")