import { type Abi, type EncodeFunctionDataParameters, type GetAbiItemParameters, type GetAbiItemReturnType, type Hex, encodeFunctionData, getAbiItem, isHex, zeroAddress } from "viem" import { type CALL, CallType } from "../actions/createMagicAddress" import { FLEX } from "../constants" import type { CreateActionFromArgsParameters } from "../types" export const createCall = < TAbi extends Abi | readonly unknown[], TFunctionName extends string | undefined = string >({ target, value, actionType, abi, functionName, args }: CreateActionFromArgsParameters): CALL => { let abiItem: GetAbiItemReturnType | undefined let tokenAddressOffset = 0n let tokenAmountOffset = 0n let data: Hex = "0x" if (abi) { abiItem = getAbiItem({ abi, name: functionName, args } as GetAbiItemParameters) if (abiItem?.type !== "function") { throw Error(`${functionName} not found in abi`) } const _args = Array.isArray(args) ? [...args] : [] const paramOffset = 4n abiItem.inputs?.forEach((input, index) => { if ( input.type.includes("int") && _args && _args[index] === FLEX.AMOUNT ) { _args[index] = BigInt(0) tokenAmountOffset = paramOffset + BigInt(index) * BigInt(32) } else if ( input.type.includes("address") && _args && _args[index] === FLEX.TOKEN_ADDRESS ) { _args[index] = zeroAddress tokenAddressOffset = paramOffset + BigInt(index) * BigInt(32) } }) data = encodeFunctionData({ abi, args: _args, functionName } as EncodeFunctionDataParameters) } if (target === FLEX.TOKEN_ADDRESS) { target = "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF" } if (value === FLEX.NATIVE_AMOUNT) { value = BigInt( "0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfFfffffFfFFFffffFfFfFfffff" ) } return { target, value: isHex(value) ? BigInt(value) : (value ?? BigInt(0)), callType: actionType ?? CallType.CALL, data: data, tokenAddressOffset, tokenAmountOffset } }