UNPKG

@biconomy/sdk

Version:

SDK for Biconomy integration with support for account abstraction, smart accounts, ERC-4337.

286 lines 11.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.toNexusAccount = void 0; const viem_1 = require("viem"); const account_abstraction_1 = require("viem/account-abstraction"); const constants_1 = require("../constants/index.js"); const abi_1 = require("../constants/abi/index.js"); const getNexusAddress_1 = require("./decorators/getNexusAddress.js"); const toK1Validator_1 = require("../modules/k1Validator/toK1Validator.js"); const getFactoryData_1 = require("./decorators/getFactoryData.js"); const getFactoryData_2 = require("./decorators/getFactoryData.js"); const Constants_1 = require("./utils/Constants.js"); const Utils_1 = require("./utils/Utils.js"); const toSigner_1 = require("./utils/toSigner.js"); const toNexusAccount = async (parameters) => { const { chain, transport, signer: _signer, index = 0n, module: module_, factoryAddress = constants_1.MAINNET_ADDRESS_K1_VALIDATOR_FACTORY_ADDRESS, validatorAddress = constants_1.MAINNET_ADDRESS_K1_VALIDATOR_ADDRESS, key = "nexus account", name = "Nexus Account", attesters: attesters_ = [constants_1.RHINESTONE_ATTESTER_ADDRESS], attesterThreshold = 1, bootStrapAddress = constants_1.NEXUS_BOOTSTRAP_ADDRESS, registryAddress = constants_1.REGISTRY_ADDRESS, useTestBundler = false } = parameters; const useMeeAccount = (0, Utils_1.addressEquals)(validatorAddress, constants_1.MEE_VALIDATOR_ADDRESS); const signer = await (0, toSigner_1.toSigner)({ signer: _signer }); const walletClient = (0, viem_1.createWalletClient)({ account: signer, chain, transport, key, name }).extend(viem_1.publicActions); const signerAddress = walletClient.account.address; const publicClient = (0, viem_1.createPublicClient)({ chain, transport }); const entryPointContract = (0, viem_1.getContract)({ address: constants_1.ENTRY_POINT_ADDRESS, abi: abi_1.EntrypointAbi, client: { public: publicClient, wallet: walletClient } }); const factoryData = useMeeAccount ? await (0, getFactoryData_2.getMeeFactoryData)({ signerAddress, index, publicClient, walletClient, bootStrapAddress, registryAddress, attesters: attesters_, attesterThreshold, validatorAddress }) : await (0, getFactoryData_1.getK1FactoryData)({ signerAddress, index, attesters: attesters_, attesterThreshold }); const getInitCode = () => (0, viem_1.concatHex)([factoryAddress, factoryData]); let _accountAddress = parameters.accountAddress; const getCounterFactualAddress = async () => { if (!(0, Utils_1.isNullOrUndefined)(_accountAddress)) return _accountAddress; try { await entryPointContract.simulate.getSenderAddress([getInitCode()]); } catch (e) { if (e?.cause?.data?.errorName === "SenderAddressResult") { const accountAddressFromError = e?.cause.data.args[0]; if (!(0, Utils_1.addressEquals)(accountAddressFromError, viem_1.zeroAddress)) { _accountAddress = accountAddressFromError; return accountAddressFromError; } } } const addressFromFactory = useMeeAccount ? await (0, getNexusAddress_1.getMeeNexusAddress)({ publicClient, signerAddress, index }) : await (0, getNexusAddress_1.getK1NexusAddress)({ publicClient, signerAddress, index, attesters: attesters_, threshold: attesterThreshold, factoryAddress }); if (!(0, Utils_1.addressEquals)(addressFromFactory, viem_1.zeroAddress)) { _accountAddress = addressFromFactory; return addressFromFactory; } throw new Error("Failed to get counterfactual account address"); }; let module = module_ ?? (0, toK1Validator_1.toK1Validator)({ address: validatorAddress, accountAddress: await getCounterFactualAddress(), initData: signerAddress, deInitData: "0x", signer }); const isDeployed = async () => { const address = await getCounterFactualAddress(); const contractCode = await publicClient.getCode({ address }); return (contractCode?.length ?? 0) > 2; }; const getUserOpHash = (userOp) => (0, account_abstraction_1.getUserOperationHash)({ chainId: chain.id, entryPointAddress: account_abstraction_1.entryPoint07Address, entryPointVersion: "0.7", userOperation: userOp }); const encodeExecuteBatch = async (calls, mode = Constants_1.EXECUTE_BATCH) => { const executionAbiParams = { type: "tuple[]", components: [ { name: "target", type: "address" }, { name: "value", type: "uint256" }, { name: "callData", type: "bytes" } ] }; const executions = calls.map((tx) => ({ target: tx.to, callData: tx.data ?? "0x", value: BigInt(tx.value ?? 0n) })); const executionCalldataPrep = (0, viem_1.encodeAbiParameters)([executionAbiParams], [executions]); return (0, viem_1.encodeFunctionData)({ abi: (0, viem_1.parseAbi)([ "function execute(bytes32 mode, bytes calldata executionCalldata) external" ]), functionName: "execute", args: [mode, executionCalldataPrep] }); }; const encodeExecute = async (call, mode = Constants_1.EXECUTE_SINGLE) => { const executionCalldata = (0, viem_1.encodePacked)(["address", "uint256", "bytes"], [call.to, BigInt(call.value ?? 0n), (call.data ?? "0x")]); return (0, viem_1.encodeFunctionData)({ abi: (0, viem_1.parseAbi)([ "function execute(bytes32 mode, bytes calldata executionCalldata) external" ]), functionName: "execute", args: [mode, executionCalldata] }); }; const getNonce = async (parameters) => { try { const TIMESTAMP_ADJUSTMENT = 16777215n; const defaultedKey = BigInt(parameters?.key ?? 0n) % TIMESTAMP_ADJUSTMENT; const defaultedValidationMode = parameters?.validationMode ?? "0x00"; const key = (0, viem_1.concat)([ (0, viem_1.toHex)(defaultedKey, { size: 3 }), defaultedValidationMode, parameters?.moduleAddress ?? module.address ]); const accountAddress = await getCounterFactualAddress(); return await entryPointContract.read.getNonce([ accountAddress, BigInt(key) ]); } catch (e) { return 0n; } }; const setModule = (validationModule) => { module = validationModule; }; const signMessage = async ({ message }) => { const tempSignature = await module.signMessage(message); const signature = (0, viem_1.encodePacked)(["address", "bytes"], [module.address, tempSignature]); const erc6492Signature = (0, viem_1.concat)([ (0, viem_1.encodeAbiParameters)([ { type: "address", name: "create2Factory" }, { type: "bytes", name: "factoryCalldata" }, { type: "bytes", name: "originalERC1271Signature" } ], [factoryAddress, factoryData, signature]), Constants_1.MAGIC_BYTES ]); const accountIsDeployed = await isDeployed(); return accountIsDeployed ? signature : erc6492Signature; }; async function signTypedData(parameters) { const { message, primaryType, types: _types, domain } = parameters; if (!domain) throw new Error("Missing domain"); if (!message) throw new Error("Missing message"); const types = { EIP712Domain: (0, Utils_1.getTypesForEIP712Domain)({ domain }), ..._types }; const messageStuff = message.stuff; (0, viem_1.validateTypedData)({ domain, message, primaryType, types }); const appDomainSeparator = (0, viem_1.domainSeparator)({ domain }); const accountDomainStructFields = await (0, Utils_1.getAccountDomainStructFields)(publicClient, await getCounterFactualAddress()); const parentStructHash = (0, viem_1.keccak256)((0, viem_1.encodePacked)(["bytes", "bytes"], [ (0, viem_1.encodeAbiParameters)((0, viem_1.parseAbiParameters)(["bytes32, bytes32"]), [ (0, viem_1.keccak256)((0, viem_1.toBytes)(Constants_1.PARENT_TYPEHASH)), messageStuff ]), accountDomainStructFields ])); const wrappedTypedHash = (0, Utils_1.eip712WrapHash)(parentStructHash, appDomainSeparator); let signature = await module.signMessage({ raw: (0, viem_1.toBytes)(wrappedTypedHash) }); const contentsType = (0, viem_1.toBytes)((0, Utils_1.typeToString)(types)[1]); const signatureData = (0, viem_1.concatHex)([ signature, appDomainSeparator, messageStuff, (0, viem_1.toHex)(contentsType), (0, viem_1.toHex)(contentsType.length, { size: 2 }) ]); signature = (0, viem_1.encodePacked)(["address", "bytes"], [module.address, signatureData]); return signature; } return (0, account_abstraction_1.toSmartAccount)({ client: walletClient, entryPoint: { abi: abi_1.EntrypointAbi, address: constants_1.ENTRY_POINT_ADDRESS, version: "0.7" }, getAddress: getCounterFactualAddress, encodeCalls: (calls) => { return calls.length === 1 ? encodeExecute(calls[0]) : encodeExecuteBatch(calls); }, getFactoryArgs: async () => ({ factory: factoryAddress, factoryData }), getStubSignature: async () => module.getStubSignature(), signMessage, signTypedData, signUserOperation: async (parameters) => { const { chainId = publicClient.chain.id, ...userOpWithoutSender } = parameters; const address = await getCounterFactualAddress(); const userOperation = { ...userOpWithoutSender, sender: address }; const hash = (0, account_abstraction_1.getUserOperationHash)({ chainId, entryPointAddress: account_abstraction_1.entryPoint07Address, entryPointVersion: "0.7", userOperation }); return await module.signUserOpHash(hash); }, getNonce, extend: { entryPointAddress: account_abstraction_1.entryPoint07Address, getCounterFactualAddress, isDeployed, getInitCode, encodeExecute, encodeExecuteBatch, getUserOpHash, setModule, getModule: () => module, factoryData, factoryAddress, validatorAddress, signer, walletClient, publicClient, attesters: attesters_, useTestBundler } }); }; exports.toNexusAccount = toNexusAccount; //# sourceMappingURL=toNexusAccount.js.map