UNPKG

@biconomy/abstractjs

Version:

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

119 lines 4.65 kB
import { encodeFunctionData, erc20Abi } from "viem"; import { isComposableCallRequired, isRuntimeComposableValue } from "../../../modules/utils/composabilityCalls.js"; import { getFunctionContextFromAbi } from "../../../modules/utils/runtimeAbiEncoding.js"; import { buildComposableCall } from "./buildComposable.js"; /** * Builds an instruction for approving token spending. This is typically used * when the token doesn't support ERC20Permit and a standard approve transaction * is needed. * * @param baseParams - Base configuration for the instruction * @param baseParams.account - The account that will execute the approval * @param baseParams.currentInstructions - Optional array of existing instructions to append to * @param parameters - Parameters for the approval * @param parameters.chainId - Chain ID where the approval will be executed * @param parameters.tokenAddress - Address of the token to approve * @param parameters.amount - Amount to approve * @param composabilityParams.forceComposableEncoding - Optional boolean whether to force use composability or not * @param composabilityParams.composabilityVersion - Optional composability version to use * @param composabilityParams.efficientMode - Optional boolean whether to compress the calldata input params or not * @param [parameters.gasLimit] - Optional gas limit for the approval * @param [parameters.spender] - Optional spender address * * @returns Promise resolving to array of instructions * * @example * ```typescript * const instructions = await buildApprove( * { accountAddress: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' }, * { * chainId: 1, * tokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC * amount: 1000000n, // 1 USDC * gasLimit: 50000n, * spender: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e" * }, * { * forceComposableEncoding: false, * composabilityVersion: ComposabilityVersion.V1_0_0, * efficientMode: true * } * ); * ``` */ export const buildApprove = async (baseParams, parameters, composabilityParams) => { const { currentInstructions = [], accountAddress } = baseParams; const { chainId, tokenAddress, amount, gasLimit, spender, metadata, lowerBoundTimestamp, upperBoundTimestamp, executionSimulationRetryDelay, simulationOverrides } = parameters; const { forceComposableEncoding } = composabilityParams ?? { forceComposableEncoding: false }; const abi = erc20Abi; const functionSig = "approve"; const args = [ spender, amount ]; const functionContext = getFunctionContextFromAbi(functionSig, abi); // Check for the runtime arguments and detect the need for composable call const isComposableCall = forceComposableEncoding ? true : isComposableCallRequired(functionContext, args); let approvalCall; // If the composable call is detected, the call needs to composed with runtime encoding if (isComposableCall) { if (!composabilityParams) { throw new Error("Composability params are required to build a composable call"); } const composableCallParams = { to: tokenAddress, functionName: functionSig, args: args, abi, chainId, ...(gasLimit ? { gasLimit } : {}) }; approvalCall = await buildComposableCall(composableCallParams, composabilityParams); } else { approvalCall = [ { to: tokenAddress, data: encodeFunctionData({ abi, functionName: functionSig, args: args }), ...(gasLimit ? { gasLimit } : {}) } ]; } const defaultMetadata = [ { type: "APPROVE", tokenAddress: isRuntimeComposableValue(tokenAddress) ? "RUNTIME_VALUE" : tokenAddress, fromAddress: accountAddress, toAddress: spender, amount: isRuntimeComposableValue(amount) ? "RUNTIME_VALUE" : amount, chainId } ]; return [ ...currentInstructions, { calls: approvalCall, chainId, isComposable: isComposableCall, metadata: metadata || defaultMetadata, lowerBoundTimestamp, upperBoundTimestamp, executionSimulationRetryDelay, simulationOverrides } ]; }; export default buildApprove; //# sourceMappingURL=buildApprove.js.map