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

174 lines 7.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.toSmartContractAccount = exports.getAccountAddress = exports.parseFactoryAddressFromAccountInitCode = exports.isSmartAccountWithSigner = void 0; const viem_1 = require("viem"); const accounts_1 = require("viem/accounts"); const bundlerClient_js_1 = require("../client/bundlerClient.js"); const account_js_1 = require("../errors/account.js"); const client_js_1 = require("../errors/client.js"); const entrypoint_js_1 = require("../errors/entrypoint.js"); const logger_js_1 = require("../logger.js"); const utils_js_1 = require("../signer/utils.js"); const base_js_1 = require("./base.js"); const isSmartAccountWithSigner = (account) => { return "getSigner" in account; }; exports.isSmartAccountWithSigner = isSmartAccountWithSigner; const parseFactoryAddressFromAccountInitCode = (initCode) => { const factoryAddress = `0x${initCode.substring(2, 42)}`; const factoryCalldata = `0x${initCode.substring(42)}`; return [factoryAddress, factoryCalldata]; }; exports.parseFactoryAddressFromAccountInitCode = parseFactoryAddressFromAccountInitCode; const getAccountAddress = async ({ client, entryPoint, accountAddress, getAccountInitCode, }) => { if (accountAddress) return accountAddress; const entryPointContract = (0, viem_1.getContract)({ address: entryPoint.address, abi: entryPoint.abi, client, }); const initCode = await getAccountInitCode(); logger_js_1.Logger.verbose("[BaseSmartContractAccount](getAddress) initCode: ", initCode); try { await entryPointContract.simulate.getSenderAddress([initCode]); } catch (err) { logger_js_1.Logger.verbose("[BaseSmartContractAccount](getAddress) getSenderAddress err: ", err); if (err.cause?.data?.errorName === "SenderAddressResult") { logger_js_1.Logger.verbose("[BaseSmartContractAccount](getAddress) entryPoint.getSenderAddress result:", err.cause.data.args[0]); return err.cause.data.args[0]; } if (err.details === "Invalid URL") { throw new client_js_1.InvalidRpcUrlError(); } } throw new account_js_1.GetCounterFactualAddressError(); }; exports.getAccountAddress = getAccountAddress; async function toSmartContractAccount({ transport, chain, entryPoint, source, accountAddress, getAccountInitCode, signMessage, signTypedData, encodeBatchExecute, encodeExecute, getDummySignature, signUserOperationHash, encodeUpgradeToAndCall, }) { const client = (0, bundlerClient_js_1.createBundlerClient)({ transport: (opts) => transport({ ...opts, chain, retryCount: 0 }), chain, }); const entryPointContract = (0, viem_1.getContract)({ address: entryPoint.address, abi: entryPoint.abi, client, }); const accountAddress_ = await (0, exports.getAccountAddress)({ client, entryPoint: entryPoint, accountAddress, getAccountInitCode, }); let deploymentState = base_js_1.DeploymentState.UNDEFINED; const getInitCode = async () => { if (deploymentState === base_js_1.DeploymentState.DEPLOYED) { return "0x"; } const contractCode = await client.getBytecode({ address: accountAddress_, }); if ((contractCode?.length ?? 0) > 2) { deploymentState = base_js_1.DeploymentState.DEPLOYED; return "0x"; } else { deploymentState = base_js_1.DeploymentState.NOT_DEPLOYED; } return getAccountInitCode(); }; const signUserOperationHash_ = signUserOperationHash ?? (async (uoHash) => { return signMessage({ message: { raw: (0, viem_1.hexToBytes)(uoHash) } }); }); const getFactoryAddress = async () => (0, exports.parseFactoryAddressFromAccountInitCode)(await getAccountInitCode())[0]; const getFactoryData = async () => (0, exports.parseFactoryAddressFromAccountInitCode)(await getAccountInitCode())[1]; const encodeUpgradeToAndCall_ = encodeUpgradeToAndCall ?? (() => { throw new account_js_1.UpgradesNotSupportedError(source); }); const isAccountDeployed = async () => { const initCode = await getInitCode(); return initCode === "0x"; }; const getNonce = async (nonceKey = 0n) => { if (!(await isAccountDeployed())) { return 0n; } return entryPointContract.read.getNonce([ accountAddress_, nonceKey, ]); }; const account = (0, accounts_1.toAccount)({ address: accountAddress_, signMessage, signTypedData, signTransaction: () => { throw new account_js_1.SignTransactionNotSupportedError(); }, }); const create6492Signature = async (isDeployed, signature) => { if (isDeployed) { return signature; } const [factoryAddress, factoryCalldata] = (0, exports.parseFactoryAddressFromAccountInitCode)(await getAccountInitCode()); return (0, utils_js_1.wrapSignatureWith6492)({ factoryAddress, factoryCalldata, signature, }); }; const signMessageWith6492 = async (message) => { const [isDeployed, signature] = await Promise.all([ isAccountDeployed(), account.signMessage(message), ]); return create6492Signature(isDeployed, signature); }; const signTypedDataWith6492 = async (typedDataDefinition) => { const [isDeployed, signature] = await Promise.all([ isAccountDeployed(), account.signTypedData(typedDataDefinition), ]); return create6492Signature(isDeployed, signature); }; const getImplementationAddress = async () => { const storage = await client.getStorageAt({ address: account.address, slot: "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", }); if (storage == null) { throw new account_js_1.FailedToGetStorageSlotError("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", "Proxy Implementation Address"); } return (0, viem_1.trim)(storage); }; if (entryPoint.version !== "0.6.0" && entryPoint.version !== "0.7.0") { throw new entrypoint_js_1.InvalidEntryPointError(chain, entryPoint.version); } return { ...account, source, signUserOperationHash: signUserOperationHash_, getFactoryAddress, getFactoryData, encodeBatchExecute: encodeBatchExecute ?? (() => { throw new account_js_1.BatchExecutionNotSupportedError(source); }), encodeExecute, getDummySignature, getInitCode, encodeUpgradeToAndCall: encodeUpgradeToAndCall_, getEntryPoint: () => entryPoint, isAccountDeployed, getNonce, signMessageWith6492, signTypedDataWith6492, getImplementationAddress, }; } exports.toSmartContractAccount = toSmartContractAccount; //# sourceMappingURL=smartContractAccount.js.map