UNPKG

tensaikit

Version:

An autonomous DeFi AI Agent Kit on Katana enabling AI agents to plan and execute on-chain financial operations.

121 lines (120 loc) 5.48 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.prepareAndSendSwapTransaction = void 0; const decimal_js_1 = __importDefault(require("decimal.js")); const errors_1 = require("../../../common/errors"); const fetchTokenMetadata_1 = require("./fetchTokenMetadata"); const utlis_1 = require("../utlis"); const utils_1 = require("../../../utils"); const viem_1 = require("viem"); const network_1 = require("../../../network"); /** * Prepares and sends a token swap transaction via the SushiSwap module using the provided wallet provider. * * This function handles the full lifecycle of a swap: * 1. Validates network and chain information from the wallet provider. * 2. Fetches token metadata to convert the input amount into base units. * 3. Checks and sets token allowance if needed. * 4. Fetches the swap calldata from the SushiSwap module. * 5. Simulates the transaction using Viem’s `publicClient.call` (for dry-run). * 6. Sends the transaction using the wallet provider and waits for confirmation. * * @param walletProvider - A Viem-compatible wallet provider to interact with the blockchain. * @param args - Swap details: * - tokenIn: Address of the input token. * - tokenOut: Address of the output token. * - maxSlippage: Maximum allowed slippage for the trade (in percent). * - amount: Human-readable input amount (e.g., 1.5 ETH). * * @returns A promise resolving to the transaction hash if successful. * If approval fails, returns an error string. * @throws Throws a formatted error if any stage in the swap process fails. */ const prepareAndSendSwapTransaction = async (walletProvider, args) => { try { const network = walletProvider.getNetwork(); const chainId = network.chainId; const networkId = network.networkId; if (!chainId || !networkId) { throw (0, errors_1.createError)("Invalid or missing network", errors_1.ErrorCode.INVALID_NETWORK); } const tokenMetadata = await (0, fetchTokenMetadata_1.fetchTokenMetadata)(chainId, args.tokenIn); if (!tokenMetadata?.decimals) { throw (0, errors_1.createError)("Failed to fetch token decimals", errors_1.ErrorCode.TOKEN_METADATA_ERROR); } const amountInBaseUnits = new decimal_js_1.default(args.amount) .mul(new decimal_js_1.default(10).pow(tokenMetadata.decimals)) .toFixed(0); const sushiSwapModule = await (0, utlis_1.SushiSwapModule)(); const typedChainId = chainId; const spender = (0, utlis_1.getSpender)(typedChainId); if (!(0, utils_1.isNativeToken)(args.tokenIn)) { const currentAllowance = await (0, utils_1.allowance)(walletProvider, args.tokenIn, spender); if (currentAllowance < BigInt(amountInBaseUnits)) { const approvalResult = await (0, utils_1.approve)(walletProvider, args.tokenIn, spender, BigInt(amountInBaseUnits)); if (approvalResult.startsWith("Error")) { return `Error approving SushiSwap as spender: ${approvalResult}`; } else { console.log(approvalResult); } } else { console.log("Sufficient allowance. Skipping approval."); } } else { console.log("Native token detected. No approval needed."); } // Step 1: Get swap quote const swapData = await sushiSwapModule.getSwap({ chainId: typedChainId, tokenIn: args.tokenIn, tokenOut: args.tokenOut, amount: BigInt(amountInBaseUnits), maxSlippage: args.maxSlippage, sender: walletProvider.getAddress(), }); if (swapData.status !== "Success") { throw (0, errors_1.createError)("Swap quote generation failed", "SWAP_QUOTE_FAILED"); } const { tx } = swapData; // Step 2: Simulate swap // TODO: Remove below code once Katana is available on Viem and is public let publicClient; if (chainId === "129399" || chainId === "747474") { publicClient = (0, viem_1.createPublicClient)({ chain: walletProvider.getChain(), transport: (0, viem_1.http)(), }); } else { publicClient = (0, viem_1.createPublicClient)({ chain: network_1.NETWORK_ID_TO_VIEM_CHAIN[networkId], transport: (0, viem_1.http)(), }); } const simulation = await publicClient.call({ account: tx.from, to: tx.to, data: tx.data, value: tx.value, }); console.log("Simulated output:", simulation); // Step 3: Send transaction const txHash = await walletProvider.sendTransaction({ to: tx.to, data: tx.data, value: tx.value, }); await walletProvider.waitForTransactionReceipt(txHash); return `Swap transaction successful. Transaction Hash: ${txHash}`; } catch (error) { throw (0, errors_1.handleError)("Failed to prepare and send swap transaction", error); } }; exports.prepareAndSendSwapTransaction = prepareAndSendSwapTransaction;