UNPKG

@biconomy/abstractjs

Version:

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

335 lines 14.3 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 abi_2 = require("../constants/abi/index.js"); const toEmptyHook_1 = require("../modules/toEmptyHook.js"); const toDefaultModule_1 = require("../modules/validators/default/toDefaultModule.js"); const toLegacyK1Module_1 = require("../modules/validators/legacyK1/toLegacyK1Module.js"); const getFactoryData_1 = require("./decorators/getFactoryData.js"); const getNexusAddress_1 = require("./decorators/getNexusAddress.js"); const getNonceWithKey_1 = require("./decorators/getNonceWithKey.js"); const Constants_1 = require("./utils/Constants.js"); const Utils_1 = require("./utils/Utils.js"); const getVersion_1 = require("./utils/getVersion.js"); const toInitData_1 = require("./utils/toInitData.js"); const toSigner_1 = require("./utils/toSigner.js"); const toWalletClient_1 = require("./utils/toWalletClient.js"); const toNexusAccount = async (parameters) => { const { chain, transport: transportConfig, signer: _signer, index = 0n, validators: customValidators, executors: customExecutors, hook: customHook, fallbacks: customFallbacks, prevalidationHooks: customPrevalidationHooks, accountAddress: accountAddress_, nexusVersion, attesterThreshold = 1, useK1Config = false } = parameters; let { initData, factoryAddress = constants_1.NEXUS_ACCOUNT_FACTORY_ADDRESS, bootStrapAddress = constants_1.NEXUS_BOOTSTRAP_ADDRESS, implementationAddress = constants_1.NEXUS_IMPLEMENTATION_ADDRESS, registryAddress, attesters, k1ValidatorAddress, k1FactoryAddress } = parameters; if (nexusVersion && (0, getVersion_1.isVersionOlder)(nexusVersion, "1.2.0")) { ; ({ factoryAddress, bootStrapAddress, implementationAddress, registryAddress, attesters, k1ValidatorAddress, k1FactoryAddress } = (0, getVersion_1.getConfigFromNexusVersion)(nexusVersion)); if (useK1Config) { factoryAddress = k1FactoryAddress; } } const signer = await (0, toSigner_1.toSigner)({ signer: _signer }); const walletClient = (0, toWalletClient_1.toWalletClient)({ unresolvedSigner: _signer, resolvedSigner: signer, chain, transport: transportConfig }); const publicClient = (0, viem_1.createPublicClient)({ chain, transport: transportConfig }); const defaultValidator = (0, toDefaultModule_1.toDefaultModule)({ signer }); const validators = customValidators || []; let k1Validator = undefined; if (useK1Config && k1ValidatorAddress) { k1Validator = (0, toLegacyK1Module_1.toLegacyK1Module)({ signer, module: k1ValidatorAddress }); } let module = k1Validator || customValidators?.[0] || defaultValidator; const executors = customExecutors || []; const hook = customHook || (0, toEmptyHook_1.toEmptyHook)(); const fallbacks = customFallbacks || []; const prevalidationHooks = customPrevalidationHooks || []; let factoryData = "0x"; if (useK1Config) { factoryData = (0, getFactoryData_1.getK1FactoryData)({ signerAddress: signer.address, index, attesters: attesters, attesterThreshold }); } else { if (!initData) { initData = (0, getFactoryData_1.getInitData)({ defaultValidator: (0, toInitData_1.toInitData)(defaultValidator), prevalidationHooks, validators: validators.map(toInitData_1.toInitData), executors: executors.map(toInitData_1.toInitData), hook: (0, toInitData_1.toInitData)(hook), fallbacks: fallbacks.map(toInitData_1.toInitData), bootStrapAddress, registryAddress, attesters, attesterThreshold, nexusVersion }); factoryData = (0, getFactoryData_1.getFactoryData)({ initData, index }); } } const getInitCode = () => (0, viem_1.concatHex)([useK1Config ? k1FactoryAddress : factoryAddress, factoryData]); let _accountAddress = accountAddress_; const accountId = (await publicClient.readContract({ address: implementationAddress, abi: (0, viem_1.parseAbi)(["function accountId() public view returns (string)"]), functionName: "accountId", args: [] })); const getAddress = async () => { if (!(0, Utils_1.isNullOrUndefined)(_accountAddress)) return _accountAddress; const addressFromFactory = useK1Config ? await (0, getNexusAddress_1.getK1NexusAddress)({ k1FactoryAddress: k1FactoryAddress, index, ownerAddress: signer.address, attesters: attesters, attesterThreshold, publicClient }) : await (0, getNexusAddress_1.getNexusAddress)({ factoryAddress, index, initData: initData, publicClient }); if (!(0, Utils_1.addressEquals)(addressFromFactory, viem_1.zeroAddress)) { _accountAddress = addressFromFactory; return addressFromFactory; } throw new Error("Failed to get account address"); }; 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 encodeExecuteComposable = async (calls) => { const composableCalls = calls.map((call) => { return { to: call.to, value: call.value ?? 0n, functionSig: call.functionSig, inputParams: call.inputParams, outputParams: call.outputParams }; }); return (0, viem_1.encodeFunctionData)({ abi: abi_2.COMPOSABILITY_MODULE_ABI, functionName: "executeComposable", args: [composableCalls] }); }; const getNonceWithKey = async (accountAddress, parameters) => { const defaultNonceKey = await (0, getNonceWithKey_1.getDefaultNonceKey)(accountAddress, chain.id); const { key = defaultNonceKey, validationMode = "0x00", moduleAddress = module.module } = parameters ?? {}; return (0, getNonceWithKey_1.getNonceWithKeyUtil)(publicClient, accountAddress, { key, validationMode, moduleAddress }); }; const getNonce = async (parameters) => { const accountAddress = await getAddress(); const { nonce } = await getNonceWithKey(accountAddress, parameters); return nonce; }; 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 getAddress()); 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.module, signatureData]); return signature; } const setModule = (validationModule) => { module = validationModule; }; async function toDelegation(params) { const { authorization: authorization_, multiChain, delegatedContract } = params || {}; const contractAddress = delegatedContract || implementationAddress; const authorization = authorization_ || (await walletClient.signAuthorization({ contractAddress })); const eip7702Auth = { chainId: `0x${(multiChain ? 0 : chain.id).toString(16)}`, address: authorization.address, nonce: `0x${authorization.nonce.toString(16)}`, r: authorization.r, s: authorization.s, v: `0x${authorization.v.toString(16)}`, yParity: `0x${authorization.yParity.toString(16)}` }; return eip7702Auth; } async function isDelegated() { const code = await publicClient.getCode({ address: signer.address }); return (!!code && code ?.toLowerCase() .includes(constants_1.NEXUS_IMPLEMENTATION_ADDRESS.substring(2).toLowerCase())); } async function unDelegate(params) { const { authorization } = params || {}; const deAuthorization = authorization || (await walletClient.signAuthorization({ address: viem_1.zeroAddress, executor: "self" })); return await walletClient.sendTransaction({ to: signer.address, data: "0xdeadbeef", type: "eip7702", authorizationList: [deAuthorization] }); } return (0, account_abstraction_1.toSmartAccount)({ client: publicClient, entryPoint: { abi: abi_1.EntrypointAbi, address: constants_1.ENTRY_POINT_ADDRESS, version: "0.7" }, getAddress, encodeCalls: (calls) => { return calls.length === 1 ? encodeExecute(calls[0]) : encodeExecuteBatch(calls); }, getFactoryArgs: async () => ({ factory: factoryAddress, factoryData }), getStubSignature: async () => module.getStubSignature(), async signMessage({ message }) { const tempSignature = await module.signMessage(message); return (0, viem_1.encodePacked)(["address", "bytes"], [module.module, tempSignature]); }, signTypedData, signUserOperation: async (parameters) => { const { chainId = publicClient.chain.id, ...userOpWithoutSender } = parameters; const address = await getAddress(); 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: { isDelegated, toDelegation, unDelegate, entryPointAddress: account_abstraction_1.entryPoint07Address, getAddress, accountId, getInitCode, getNonceWithKey, encodeExecute, encodeExecuteBatch, encodeExecuteComposable, getUserOpHash, factoryData, factoryAddress, registryAddress, signer, walletClient, publicClient, chain, setModule, getModule: () => module } }); }; exports.toNexusAccount = toNexusAccount; //# sourceMappingURL=toNexusAccount.js.map