UNPKG

@alchemy/aa-core

Version:

viem based SDK that enables interactions with ERC-4337 Smart Accounts. ABIs are based off the definitions generated in @account-abstraction/contracts

257 lines 10.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseSmartContractAccount = exports.DeploymentState = void 0; const viem_1 = require("viem"); const EntryPointAbi_v6_js_1 = require("../abis/EntryPointAbi_v6.js"); const bundlerClient_js_1 = require("../client/bundlerClient.js"); const index_js_1 = require("../entrypoint/index.js"); const account_js_1 = require("../errors/account.js"); const client_js_1 = require("../errors/client.js"); const logger_js_1 = require("../logger.js"); const utils_js_1 = require("../signer/utils.js"); const schema_js_1 = require("./schema.js"); var DeploymentState; (function (DeploymentState) { DeploymentState["UNDEFINED"] = "0x0"; DeploymentState["NOT_DEPLOYED"] = "0x1"; DeploymentState["DEPLOYED"] = "0x2"; })(DeploymentState || (exports.DeploymentState = DeploymentState = {})); class BaseSmartContractAccount { constructor(params_) { Object.defineProperty(this, "factoryAddress", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "deploymentState", { enumerable: true, configurable: true, writable: true, value: DeploymentState.UNDEFINED }); Object.defineProperty(this, "accountAddress", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "accountInitCode", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "signer", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "entryPoint", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "entryPointAddress", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "rpcProvider", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "encodeUpgradeToAndCall", { enumerable: true, configurable: true, writable: true, value: async (_upgradeToImplAddress, _upgradeToInitData) => { throw new account_js_1.UpgradeToAndCallNotSupportedError("BaseAccount"); } }); Object.defineProperty(this, "extend", { enumerable: true, configurable: true, writable: true, value: (fn) => { const extended = fn(this); for (const key in this) { delete extended[key]; } return Object.assign(this, extended); } }); const params = (0, schema_js_1.createBaseSmartAccountParamsSchema)().parse(params_); this.entryPointAddress = params.entryPointAddress ?? (0, index_js_1.getEntryPoint)(params.chain).address; const rpcUrl = typeof params.rpcClient === "string" ? params.rpcClient : params.rpcClient.transport.type === "http" ? params.rpcClient.transport.url || params.chain.rpcUrls.default.http[0] : undefined; const fetchOptions = typeof params.rpcClient === "string" ? undefined : params.rpcClient.transport.type === "http" ? params.rpcClient.transport.fetchOptions : undefined; this.rpcProvider = rpcUrl ? (0, bundlerClient_js_1.createBundlerClient)({ chain: params.chain, transport: (0, viem_1.http)(rpcUrl, { fetchOptions: { ...fetchOptions, headers: { ...fetchOptions?.headers, ...(rpcUrl.toLowerCase().indexOf("alchemy") > -1 ? { "Alchemy-Aa-Sdk-Signer": params.signer?.signerType || "unknown", "Alchemy-Aa-Sdk-Factory-Address": params.factoryAddress, } : undefined), }, }, }), }) : params.rpcClient; this.accountAddress = params.accountAddress; this.factoryAddress = params.factoryAddress; this.signer = params.signer; this.accountInitCode = params.initCode; this.entryPoint = (0, viem_1.getContract)({ address: this.entryPointAddress, abi: EntryPointAbi_v6_js_1.EntryPointAbi_v6, client: this.rpcProvider, }); } async signUserOperationHash(uoHash) { return this.signMessage(uoHash); } async signTypedData(_params) { throw new Error("signTypedData not supported"); } async signMessageWith6492(msg) { const [isDeployed, signature] = await Promise.all([ this.isAccountDeployed(), this.signMessage(msg), ]); return this.create6492Signature(isDeployed, signature); } async signTypedDataWith6492(params) { const [isDeployed, signature] = await Promise.all([ this.isAccountDeployed(), this.signTypedData(params), ]); return this.create6492Signature(isDeployed, signature); } async encodeBatchExecute(_txs) { throw new account_js_1.BatchExecutionNotSupportedError("BaseAccount"); } async getNonce() { if (!(await this.isAccountDeployed())) { return 0n; } const address = await this.getAddress(); return this.entryPoint.read.getNonce([address, BigInt(0)]); } async getInitCode() { if (this.deploymentState === DeploymentState.DEPLOYED) { return "0x"; } const contractCode = await this.rpcProvider.getBytecode({ address: await this.getAddress(), }); if ((contractCode?.length ?? 0) > 2) { this.deploymentState = DeploymentState.DEPLOYED; return "0x"; } else { this.deploymentState = DeploymentState.NOT_DEPLOYED; } return this._getAccountInitCode(); } async getAddress() { if (!this.accountAddress) { const initCode = await this._getAccountInitCode(); logger_js_1.Logger.verbose("[BaseSmartContractAccount](getAddress) initCode: ", initCode); try { await this.entryPoint.simulate.getSenderAddress([initCode]); } catch (err) { logger_js_1.Logger.verbose("[BaseSmartContractAccount](getAddress) getSenderAddress err: ", err); if (err.cause?.data?.errorName === "SenderAddressResult") { this.accountAddress = err.cause.data.args[0]; logger_js_1.Logger.verbose("[BaseSmartContractAccount](getAddress) entryPoint.getSenderAddress result:", this.accountAddress); return this.accountAddress; } if (err.details === "Invalid URL") { throw new client_js_1.InvalidRpcUrlError(); } } throw new account_js_1.GetCounterFactualAddressError(); } return this.accountAddress; } getSigner() { return this.signer; } getFactoryAddress() { return this.factoryAddress; } getEntryPointAddress() { return this.entryPointAddress; } async isAccountDeployed() { return (await this.getDeploymentState()) === DeploymentState.DEPLOYED; } async getDeploymentState() { if (this.deploymentState === DeploymentState.UNDEFINED) { const initCode = await this.getInitCode(); return initCode === "0x" ? DeploymentState.DEPLOYED : DeploymentState.NOT_DEPLOYED; } else { return this.deploymentState; } } async parseFactoryAddressFromAccountInitCode() { const initCode = await this._getAccountInitCode(); const factoryAddress = `0x${initCode.substring(2, 42)}`; const factoryCalldata = `0x${initCode.substring(42)}`; return [factoryAddress, factoryCalldata]; } async getImplementationAddress() { const accountAddress = await this.getAddress(); const storage = await this.rpcProvider.getStorageAt({ address: accountAddress, slot: "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", }); if (storage == null) { throw new account_js_1.FailedToGetStorageSlotError("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", "Proxy Implementation Address"); } return (0, viem_1.trim)(storage); } async _getAccountInitCode() { return this.accountInitCode ?? this.getAccountInitCode(); } async create6492Signature(isDeployed, signature) { if (isDeployed) { return signature; } const [factoryAddress, factoryCalldata] = await this.parseFactoryAddressFromAccountInitCode(); logger_js_1.Logger.verbose(`[BaseSmartContractAccount](create6492Signature)\ factoryAddress: ${factoryAddress}, factoryCalldata: ${factoryCalldata}`); return (0, utils_js_1.wrapSignatureWith6492)({ factoryAddress, factoryCalldata, signature, }); } } exports.BaseSmartContractAccount = BaseSmartContractAccount; //# sourceMappingURL=base.js.map