@biconomy/abstractjs
Version:
SDK for Biconomy integration with support for account abstraction, smart accounts, ERC-4337.
129 lines • 5.52 kB
JavaScript
/**
* Builds an instruction for transferring native tokens (e.g., ETH) from a smart contract account (SCA)
* to a recipient address. This function supports both static and runtime-composable parameters,
*
* If any of the parameters (`to` or `value`) are runtime-composable, or if `forceComposableEncoding`
* is set, the instruction will be encoded as a composable call using runtime encoding.
* Otherwise, a standard instruction is created.
*
* @module buildNativeTokenTransfer
*/
import { zeroAddress } from "viem";
import { ComposabilityVersion, ForwarderAbi } from "../../../constants/index.js";
import { isRuntimeComposableValue } from "../../../modules/index.js";
import buildComposable from "./buildComposable.js";
/**
* Builds an instruction for transferring native tokens (e.g., ETH) from the account to a recipient.
*
* @param baseParams - Base configuration for the instruction (account address, current instructions)
* @param parameters - Parameters for the native token transfer
* @param composabilityParams - Optional composability configuration (version, force encoding, etc.)
* @returns Promise resolving to an array of {@link Instruction}
*
* @example
* // Static transfer
* const instructions = await buildNativeTokenTransfer(
* { accountAddress: myAccount.address },
* { to: recipient, value: 1_000_000_000_000_000_000n, chainId: 1 }
* )
*
* @example
* // Composable transfer with runtime value
* const instructions = await buildNativeTokenTransfer(
* { accountAddress: myAccount.address },
* { to: { isRuntime: true, ... }, value: { isRuntime: true, ... }, chainId: 1 },
* { composabilityVersion: 2 }
* )
*/
export const buildNativeTokenTransfer = async (baseParams, parameters, composabilityParams) => {
const { currentInstructions = [], accountAddress, meeVersions } = baseParams;
const { chainId, value, gasLimit, to, metadata: metadataOverride, lowerBoundTimestamp, upperBoundTimestamp, executionSimulationRetryDelay, simulationOverrides } = parameters;
const { forceComposableEncoding } = composabilityParams ?? {
forceComposableEncoding: false
};
const [meeVersionInfo] = meeVersions.filter((meeVersion) => meeVersion.chainId === chainId);
if (!meeVersionInfo) {
throw new Error("MEE version is required to build a native token transfer");
}
const meeVersion = meeVersionInfo.version;
// Detect if any parameter is a runtime-composable value
const isRuntimeValues = [value, to].some((val) => isRuntimeComposableValue(val));
// Determine if the call should be encoded as composable
const isComposableCall = forceComposableEncoding ? true : isRuntimeValues;
let instructions;
if (isComposableCall) {
// Composable call: requires composability version and runtime encoding
if (!composabilityParams?.composabilityVersion) {
throw new Error("Composability version is required to build a composable native token transfer instruction");
}
if (isRuntimeValues &&
composabilityParams.composabilityVersion === ComposabilityVersion.V1_0_0) {
throw new Error("Runtime values for Native tokens are not supported for Composability v1.0.0");
}
// Compose metadata for the instruction, using RUNTIME_VALUE placeholders if needed
const metadata = [
{
type: "TRANSFER",
tokenAddress: zeroAddress,
fromAddress: accountAddress,
toAddress: isRuntimeComposableValue(to)
? "RUNTIME_VALUE"
: to,
amount: isRuntimeComposableValue(value)
? "RUNTIME_VALUE"
: value,
chainId: chainId
}
];
// Uses buildComposable to build a native token transfer via eth forwarder
instructions = await buildComposable(baseParams, {
to: meeVersion.ethForwarderAddress,
abi: ForwarderAbi,
functionName: "forward",
gasLimit,
value,
args: [to],
chainId,
metadata: metadataOverride || metadata,
lowerBoundTimestamp,
upperBoundTimestamp,
executionSimulationRetryDelay,
simulationOverrides
}, composabilityParams);
}
else {
// Standard (non-composable) native token transfer
const metadata = [
{
type: "TRANSFER",
tokenAddress: zeroAddress,
fromAddress: accountAddress,
toAddress: to,
amount: value,
chainId: chainId
}
];
instructions = [
{
calls: [
{
to: to,
value: value,
data: "0x" // No calldata for native token transfer
}
],
metadata: metadataOverride || metadata,
isComposable: false,
chainId,
lowerBoundTimestamp,
upperBoundTimestamp,
executionSimulationRetryDelay,
simulationOverrides
}
];
}
// Return the new instructions appended to any existing ones
return [...currentInstructions, ...instructions];
};
export default buildNativeTokenTransfer;
//# sourceMappingURL=buildNativeTokenTransfer.js.map