UNPKG

@biconomy/abstractjs

Version:

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

103 lines 4 kB
import { concatHex, encodeAbiParameters, zeroAddress } from "viem"; import { encodeFunctionData } from "viem"; import { FORWARDER_ADDRESS } from "../../../constants/index.js"; import { ForwarderAbi } from "../../../constants/abi/ForwarderAbi.js"; export const FUSION_NATIVE_TRANSFER_PREFIX = "0x150b7a02"; export const ON_CHAIN_PREFIX = "0x177eee01"; /** * Generates a trigger call from a trigger * @private */ const generateTriggerCallFromTrigger = async ({ account, trigger, recipient, scaAddress }) => { let triggerCall; // build custom call if (trigger.call) { triggerCall = trigger.call; } else if (trigger.tokenAddress === zeroAddress) { // If the token address is zero address, we need to send eth via the ETH forwarder const forwardCalldata = encodeFunctionData({ abi: ForwarderAbi, functionName: "forward", args: [recipient] }); const [{ calls: [ethForwardCall] }] = await account.build({ type: "default", data: { calls: [ { to: FORWARDER_ADDRESS, data: forwardCalldata, value: trigger.amount } ], chainId: trigger.chainId } }); triggerCall = ethForwardCall; } else { // erc20 trigger // check if we have an explicit `approvalAmount` set and error if it's smaller than the trigger amount if (trigger.approvalAmount && trigger.amount !== undefined && trigger.approvalAmount < trigger.amount) { throw new Error(`Approval amount must be bigger or equal with the amount from the trigger (triggerAmount: ${trigger.amount} amount: ${trigger.approvalAmount})`); } const amount = trigger.approvalAmount ?? trigger.amount; const [{ calls: [approveCall] }] = await account.build({ type: "approve", data: { spender: scaAddress, tokenAddress: trigger.tokenAddress, chainId: trigger.chainId, amount } }); triggerCall = approveCall; } return triggerCall; }; /** * Signs a fusion quote with a tx send client side. * * @param client - The Mee client to use * @param params - The parameters for the fusion quote * @returns The signed quote * @example * const signedQuote = await signOnChainQuote(meeClient, { * quote: quotePayload, * account: smartAccount * }) */ export const signOnChainQuote = async (client, params) => { const { confirmations = 2, companionAccount: account_ = client.account, fusionQuote: { quote, trigger } } = params; const chainId = trigger.chainId; const { chain, walletClient, address: scaAddress } = account_.deploymentOn(chainId, true); // By default the trigger amount will be deposited to sca account. // if a custom recipient is defined ? It will deposit to the recipient address const recipient = trigger.recipientAddress || scaAddress; const triggerCall = await generateTriggerCallFromTrigger({ account: account_, trigger, recipient, scaAddress }); // This will be always a non composable transaction, so don't worry about the composability const dataOrPrefix = triggerCall?.data ?? FUSION_NATIVE_TRANSFER_PREFIX; const call = { ...triggerCall, data: concatHex([dataOrPrefix, quote.hash]) }; // @ts-ignore const hash = await walletClient.sendTransaction(call); // @ts-ignore await walletClient.waitForTransactionReceipt({ hash, confirmations }); const signature = concatHex([ ON_CHAIN_PREFIX, encodeAbiParameters([{ type: "bytes32" }, { type: "uint256" }], [hash, BigInt(chain.id)]) ]); return { ...quote, signature }; }; export default signOnChainQuote; //# sourceMappingURL=signOnChainQuote.js.map