UNPKG

@devasher/kuru-sdk

Version:

Ethers v6 SDK to interact with Kuru (forked from @kuru-labs/kuru-sdk)

125 lines 6.62 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TokenSwap = void 0; // ============ External Imports ============ const ethers_1 = require("ethers"); const utils_1 = require("../utils"); const utils_2 = require("../utils"); // ============ Config Imports ============ const IERC20_json_1 = __importDefault(require("../../abi/IERC20.json")); const Router_json_1 = __importDefault(require("../../abi/Router.json")); const txConfig_1 = __importDefault(require("../utils/txConfig")); class TokenSwap { /** * @dev Constructs a transaction for token swapping. * @param signer - The signer instance. * @param routerAddress - The address of the router contract. * @param routeOutput - The route output containing path and other swap details. * @param tokenInAmount - The amount of input tokens. * @param minTokenOutAmount - The minimum amount of output tokens to receive. * @param txOptions - Optional transaction parameters. * @returns A promise that resolves to the transaction request object. */ static async constructSwapTransaction(signer, routerAddress, routeOutput, tokenInAmount, minTokenOutAmount, txOptions) { const address = await signer.getAddress(); const routerInterface = new ethers_1.ethers.Interface(Router_json_1.default.abi); const data = routerInterface.encodeFunctionData('anyToAnySwap', [ routeOutput.route.path.map((pool) => pool.orderbook), routeOutput.isBuy, routeOutput.nativeSend, routeOutput.route.tokenIn, routeOutput.route.tokenOut, tokenInAmount, minTokenOutAmount, ]); const value = routeOutput.nativeSend[0] ? tokenInAmount : BigInt(0); return (0, txConfig_1.default)({ to: routerAddress, from: address, data, value, txOptions, signer, }); } /** * @dev Executes a token swap. * @param providerOrSigner - The ethers.js provider or signer to interact with the blockchain. * @param routerAddress - The address of the router contract. * @param routeOutput - The route output containing path and other swap details. * @param amountIn - The amount of input tokens. * @param inTokenDecimals - The decimals of the input token. * @param outTokenDecimals - The decimals of the output token. * @param slippageTolerance - The maximum acceptable slippage. * @param approveTokens - Whether to approve token spending before the swap. * @param approvalCallback - Callback function for approval transaction hash. * @param txOptions - Optional transaction parameters. * @param slippageOptions - Optional slippage options. * @returns A promise that resolves to the transaction receipt. */ static async swap(providerOrSigner, routerAddress, routeOutput, amountIn, inTokenDecimals, outTokenDecimals, slippageTolerance, approveTokens, approvalCallback, txOptions, slippageOptions) { try { // const router = new ethers.Contract(routerAddress, routerAbi.abi, providerOrSigner); const tokenContract = new ethers_1.ethers.Contract(routeOutput.route.tokenIn, IERC20_json_1.default.abi, providerOrSigner); const tokenInAmount = (0, ethers_1.parseUnits)(amountIn.toString(), inTokenDecimals); slippageTolerance = slippageOptions ? (0, utils_2.calculateDynamicSlippage)(slippageOptions.defaultSlippageBps, amountIn, slippageOptions.priceImpactBps, slippageOptions.ohlcvData) : slippageTolerance; const clippedOutput = Number((routeOutput.output * (100 - slippageTolerance)) / 100).toFixed(outTokenDecimals); const minTokenOutAmount = (0, ethers_1.parseUnits)(clippedOutput.toString(), outTokenDecimals); if (approveTokens) { const txHash = await (0, utils_1.approveToken)(tokenContract, routerAddress, tokenInAmount, providerOrSigner); if (approvalCallback) { approvalCallback(txHash); } } // Extract signer from contract or use provider/signer directly let signer; if ('getAddress' in providerOrSigner) { signer = providerOrSigner; } else { throw new Error('Provider must have a signer for transaction execution'); } const tx = await TokenSwap.constructSwapTransaction(signer, routerAddress, routeOutput, tokenInAmount, minTokenOutAmount, txOptions); console.log(tx); const transaction = await signer.sendTransaction(tx); const receipt = await transaction.wait(); if (!receipt) { throw new Error('Transaction receipt is null'); } return receipt; } catch (e) { console.error({ e }); if (!e.error) { throw e; } throw (0, utils_1.extractErrorMessage)(e); } } static async estimateGas(providerOrSigner, routerAddress, routeOutput, amountIn, inTokenDecimals, outTokenDecimals, slippageTolerance, approveTokens) { try { const tokenContract = new ethers_1.ethers.Contract(routeOutput.route.tokenIn, IERC20_json_1.default.abi, providerOrSigner); const tokenInAmount = (0, ethers_1.parseUnits)(amountIn.toString(), inTokenDecimals); if (approveTokens) { return (0, utils_1.estimateApproveGas)(tokenContract, routerAddress, tokenInAmount); } const router = new ethers_1.ethers.Contract(routerAddress, Router_json_1.default.abi, providerOrSigner); const minTokenOutAmount = (0, ethers_1.parseUnits)(((routeOutput.output * (100 - slippageTolerance)) / 100).toString(), outTokenDecimals); const gasEstimate = await router.anyToAnySwap.estimateGas(routeOutput.route.path.map((pool) => pool.orderbook), routeOutput.isBuy, routeOutput.nativeSend, routeOutput.route.tokenIn, routeOutput.route.tokenOut, tokenInAmount, minTokenOutAmount); return gasEstimate; } catch (e) { if (!e.error) { throw e; } throw (0, utils_1.extractErrorMessage)(e); } } } exports.TokenSwap = TokenSwap; //# sourceMappingURL=swap.js.map