@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
JavaScript
;
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