import { BigNumber, BigNumberish } from 'ethers'; import { Provider } from '@ethersproject/providers'; import { UserOperation } from '@biconomy-sdk-dev/core-types'; import { ClientConfig } from './ClientConfig'; import { BytesLike } from '@ethersproject/bytes'; import { EntryPoint } from '@account-abstraction/contracts'; import { SmartWalletContractV100 } from '@biconomy-sdk-dev/ethers-lib'; import { TransactionDetailsForBatchUserOp } from './TransactionDetailsForUserOp'; import { IPaymasterAPI } from '@biconomy-sdk-dev/core-types'; import { NotPromise } from '@biconomy-sdk-dev/common'; import { GasOverheads } from './calcPreVerificationGas'; export interface BaseApiParams { provider: Provider; entryPointAddress: string; accountAddress?: string; overheads?: Partial; paymasterAPI?: IPaymasterAPI; } export interface UserOpResult { transactionHash: string; success: boolean; } /** * Base class for all Smart Wallet ERC-4337 Clients to implement. * Subclass should inherit 5 methods to support a specific wallet contract: * * - getAccountInitCode - return the value to put into the "initCode" field, if the account is not yet deployed. should create the account instance using a factory contract. * - getNonce - return current account's nonce value * - encodeExecute - encode the call from entryPoint through our account to the target contract. * - signUserOpHash - sign the hash of a UserOp. * * The user can use the following APIs: * - createUnsignedUserOp - given "target" and "calldata", fill userOp to perform that operation from the account. * - createSignedUserOp - helper to call the above createUnsignedUserOp, and then extract the userOpHash and sign it */ export declare abstract class BaseAccountAPI { readonly provider: Provider; readonly entryPoint: EntryPoint; readonly clientConfig: ClientConfig; readonly accountAddress?: string | undefined; readonly overheads?: Partial | undefined; private senderAddress; private isDeployed; /** * subclass MAY initialize to support custom paymaster */ paymasterAPI?: IPaymasterAPI; /** * our wallet contract. */ accountContract: SmartWalletContractV100; /** * base constructor. * subclass SHOULD add parameters that define the owner (signer) of this wallet * @param provider - read-only provider for view calls * @param entryPointAddress - the entryPoint to send requests through (used to calculate the request-id, and for gas estimations) * @param accountAddress. may be empty for new wallet (using factory to determine address) */ protected constructor(provider: Provider, entryPoint: EntryPoint, // we could just get an address : evaluate clientConfig: ClientConfig, // review the need to get entire clientconfig accountAddress?: string | undefined, overheads?: Partial | undefined); connectPaymaster(newPaymasterAPI: IPaymasterAPI): BaseAccountAPI; _getSmartAccountContract(): Promise; init(): Promise; /** * return the value to put into the "initCode" field, if the contract is not yet deployed. * this value holds the "factory" address, followed by this account's information */ abstract getAccountInitCode(): Promise; /** * return current account's nonce. */ abstract nonce(): Promise; /** * create a UserOperation, filling all details (except signature) * - if account is not yet created, add initCode to deploy it. * - if gas or nonce are missing, read them from the chain (note that we can't fill gaslimit before the account is created) * @param info */ abstract createUnsignedUserOp(info: TransactionDetailsForBatchUserOp): Promise; /** * encode the call from entryPoint through our wallet to the target contract. * @param target * @param value * @param data * @param isDelegateCall // added by Biconomy */ abstract encodeExecuteCall(target: string, value: BigNumberish, data: BytesLike): Promise; abstract encodeExecuteBatchCall(target: string[], value: BigNumberish[], data: BytesLike[]): Promise; /** * sign a userOp's hash (userOpHash). * @param userOpHash */ abstract signUserOpHash(userOpHash: string): Promise; /** * should cover cost of putting calldata on-chain, and some overhead. * actual overhead depends on the expected bundle size */ abstract getPreVerificationGas(userOp: Partial): Promise; /** * return maximum gas used for verification. * NOTE: createUnsignedUserOp will add to this value the cost of creation, if the contract is not yet created. */ abstract getVerificationGasLimit(): Promise; /** * check if the wallet is already deployed. */ checkAccountDeployed(): Promise; /** * calculate the wallet address even before it is deployed */ getCounterFactualAddress(): Promise; /** * return initCode value to into the UserOp. * (either deployment code, or empty hex if contract already deployed) */ getInitCode(): Promise; /** * ABI-encode a user operation. used for calldata cost estimation */ packUserOp(userOp: NotPromise): string; encodeUserOpCallDataAndGasLimit(detailsForUserOp: TransactionDetailsForBatchUserOp): Promise<{ callData: string; callGasLimit: BigNumber; }>; /** * return userOpHash for signing. * This value matches entryPoint.getUserOpHash (calculated off-chain, to avoid a view call) * @param userOp userOperation, (signature field ignored) */ getUserOpHash(userOp: UserOperation): Promise; /** * return the wallet's address. * this value is valid even before deploying the wallet. */ getAccountAddress(): Promise; estimateCreationGas(initCode?: string): Promise; /** * Sign the filled userOp. * @param userOp the UserOperation to sign (with signature field ignored) */ signUserOp(userOp: UserOperation): Promise; /** * helper method: create and sign a user operation. * @param info transaction details for the userOp */ createSignedUserOp(info: TransactionDetailsForBatchUserOp): Promise; /** * get the transaction that has this userOpHash mined, or null if not found * @param userOpHash returned by sendUserOpToBundler (or by getUserOpHash..) * @param timeout stop waiting after this timeout * @param interval time to wait between polls. * @return the transactionHash this userOp was mined, or null if not found. */ getUserOpReceipt(userOpHash: string, timeout?: number, interval?: number): Promise; }