import { config, ValidationError, type RequestOptions, type RoutesResponse, } from '@lifi/sdk'; import { isRoutesRequest } from '../typeguards.js'; import { ChainId } from '../types/base.js'; import { request } from '../utils/request.js'; import type { RoutesRequest } from '../types/api.js'; // SUI import type { RoutesCetusParams } from '../routes/Sui/Cetus/types.js'; import { getRoutesCetus, formatRoutesCetus, } from '../routes/Sui/Cetus/index.js'; import type { RoutesFlowXParams } from '../routes/Sui/FlowX/types.js'; import { getRoutesFlowX, formatRoutesFlowX, } from '../routes/Sui/FlowX/index.js'; import type { RoutesSeventKParams } from '../routes/Sui/SeventK/types.js'; import { getRoutesSeventK, formatRoutesSeventK, } from '../routes/Sui/SeventK/index.js'; import type { RoutesAftermathParams } from '../routes/Sui/Aftermath/types.js'; import { getRoutesAftermath, formatRoutesAftermath, } from '../routes/Sui/Aftermath/index.js'; import type { RoutesNaviParams } from '../routes/Sui/Navi/types.js'; import { getRoutesNavi, formatRoutesNavi } from '../routes/Sui/Navi/index.js'; // import type { RoutesHopParams } from '../routes/Sui/Hop/types.js'; // import { getRoutesHop, formatRoutesHop } from '../routes/Sui/Hop/index.js'; // TON import type { RoutesSwapCoffeeParams } from '../routes/Ton/SwapCoffee/types.js'; import { getRoutesSwapCoffee, formatRoutesSwapCoffee, } from '../routes/Ton/SwapCoffee/index.js'; import type { RoutesRainbowParams } from '../routes/Ton/Rainbow/types.js'; import { getRoutesRainbow, formatRoutesRainbow, } from '../routes/Ton/Rainbow/index.js'; // SVM import type { RoutesJupParams } from '../routes/Svm/Jup/types.js'; import { getRoutesJup, formatRoutesJup } from '../routes/Svm/Jup/index.js'; import type { RoutesOrcaParams as RoutesOrcaParamsSVM } from '../routes/Svm/Orca/types.js'; import { getRoutesOrca as getRoutesOrcaSVM, formatRoutesOrca as formatRoutesOrcaSVM, } from '../routes/Svm/Orca/index.js'; // ECLIPSE import type { RoutesSolarParams } from '../routes/Eclipse/Solar/types.js'; import { getRoutesSolar, formatRoutesSolar, } from '../routes/Eclipse/Solar/index.js'; import type { RoutesOrcaParams } from '../routes/Eclipse/Orca/types.js'; import { getRoutesOrca, formatRoutesOrca, } from '../routes/Eclipse/Orca/index.js'; import type { RoutesLifinityParams } from '../routes/Eclipse/Lifinity/types.js'; import { getRoutesLifinity, formatRoutesLifinity, } from '../routes/Eclipse/Lifinity/index.js'; import type { RoutesInvariantParams } from '../routes/Eclipse/Invariant/types.js'; import { formatRoutesInvariant, getRoutesInvariant, } from '../routes/Eclipse/Invariant/index.js'; /** * Get a set of routes for a request that describes a transfer of tokens. * @param params - A description of the transfer. * @param options - Request options * @returns The resulting routes that can be used to realize the described transfer of tokens. * @throws {LiFiError} Throws a LiFiError if request fails. */ export const getRoutes = async ( params: RoutesRequest, options?: RequestOptions, ): Promise => { if (!isRoutesRequest(params)) { throw new ValidationError('Invalid routes request.'); } const _config = config.get(); // apply defaults params.options = { integrator: _config.integrator, ..._config.routeOptions, ...params.options, }; // send request if (params.fromChainId === ChainId.TON) { try { const [rainbowRoutes, swapCoffeeRoutes] = await Promise.allSettled([ getRoutesRainbow({ fromToken: params.fromTokenAddress, toToken: params.toTokenAddress, fromAmount: params.fromAmount, senderAddress: params.fromAddress, } as RoutesRainbowParams), getRoutesSwapCoffee({ fromToken: params.fromTokenAddress, toToken: params.toTokenAddress, fromAmount: params.fromAmount, fromTokenDecimals: params?.fromToken?.decimals, } as RoutesSwapCoffeeParams), ]).catch((e) => { console.error('>>> e', e); throw new Error(e.message); }); // swap coffee let swapCoffeeRoute = {}; if (swapCoffeeRoutes && (swapCoffeeRoutes as any).value) { swapCoffeeRoute = formatRoutesSwapCoffee(swapCoffeeRoutes, params); } // rainbow let rainbowRoute = {}; if (rainbowRoutes && (rainbowRoutes as any).value) { rainbowRoute = formatRoutesRainbow(rainbowRoutes, params); } const sortRoute = [swapCoffeeRoute, rainbowRoute] ?.filter((obj) => Object.keys(obj).length !== 0) ?.sort((a: any, b: any) => { const aAmount = BigInt(a?.toAmount || 0); const bAmount = BigInt(b?.toAmount || 0); return bAmount > aAmount ? 1 : bAmount < aAmount ? -1 : 0; }) ?.filter( (item: any) => item.fromAmountUSD !== 0 || item.toAmountUSD !== 0, ); return { routes: [ { ...sortRoute[0], tags: ['RECOMMENDED', 'CHEAPEST', 'FASTEST'], }, ...sortRoute.slice(1), ], unavailableRoutes: [], } as any; } catch (e) { console.error(e); return { routes: [], unavailableRoutes: { filteredOut: [], failed: [], }, }; } } if (params.fromChainId === ChainId.MOVE) { try { const [ cetusRoutes, // hopRoutes, flowxRoutes, seventkRoutes, aftermathRoutes, naviRoutes, ] = await Promise.allSettled([ getRoutesCetus({ fromToken: params.fromToken?.address || '', toToken: params.toToken?.address || '', fromAmount: params.fromAmount, } as RoutesCetusParams), // getRoutesHop({ // fromToken: params.fromToken?.address || '', // toToken: params.toToken?.address || '', // fromAmount: params.fromAmount, // } as RoutesHopParams), getRoutesFlowX({ fromToken: params.fromToken?.address || '', toToken: params.toToken?.address || '', fromAmount: params.fromAmount, } as RoutesFlowXParams), getRoutesSeventK({ fromToken: params.fromToken?.address || '', toToken: params.toToken?.address || '', fromAmount: params?.fromAmount, commission: params?.commissionBpsSDK || 0, } as RoutesSeventKParams), getRoutesAftermath({ fromToken: params.fromToken?.address || '', toToken: params.toToken?.address || '', fromAmount: params?.fromAmount, isBuildTx: false, } as RoutesAftermathParams), getRoutesNavi({ fromToken: params.fromToken?.address || '', toToken: params.toToken?.address || '', fromAmount: params?.fromAmount, } as RoutesNaviParams), ]).catch((e) => { console.error('>>> e', e); throw new Error(e.message); }); // hop.ag // let hopRoute = {}; // if (hopRoutes && (hopRoutes as any)?.value) { // hopRoute = formatRoutesHop(hopRoutes, params); // } // aftermath let aftermathRoute = {}; if (aftermathRoutes && (aftermathRoutes as any)?.value) { aftermathRoute = formatRoutesAftermath(aftermathRoutes, params); } // flowx let flowXRoute = {}; if (flowxRoutes && (flowxRoutes as any)?.value) { flowXRoute = formatRoutesFlowX(flowxRoutes, params); } // 7k let seventkRoute = {}; if (seventkRoutes && (seventkRoutes as any)?.value) { seventkRoute = formatRoutesSeventK(seventkRoutes, params); } // cetus let cetusRoute = {}; if (cetusRoutes && (cetusRoutes as any)?.value) { cetusRoute = formatRoutesCetus(cetusRoutes, params); } // navi let naviRoute = {}; if (naviRoutes && (naviRoutes as any)?.value) { naviRoute = formatRoutesNavi(naviRoutes, params); } const sortRoute = [ seventkRoute, flowXRoute, cetusRoute, aftermathRoute, naviRoute, // hopRoute, ] ?.filter((obj) => Object.keys(obj).length !== 0) ?.sort((a: any, b: any) => { const aAmount = BigInt(a?.toAmount || 0); const bAmount = BigInt(b?.toAmount || 0); return bAmount > aAmount ? 1 : bAmount < aAmount ? -1 : 0; }) ?.filter( (item: any) => item.fromAmountUSD !== 0 || item.toAmountUSD !== 0, ); return { routes: [ { ...sortRoute[0], tags: ['RECOMMENDED', 'CHEAPEST', 'FASTEST'], }, ...sortRoute.slice(1), ], unavailableRoutes: [], } as any; } catch (e) { console.error(e); return { routes: [], unavailableRoutes: { filteredOut: [], failed: [], }, }; } } if (params.fromChainId === ChainId.ECLIPSE) { try { const [solarRoutes, orcaRoutes, lifinityRoutes, invariantRoutes] = await Promise.allSettled([ getRoutesSolar({ fromToken: params.fromToken?.address || '', toToken: params.toToken?.address || '', fromAmount: params?.fromAmount, slippage: params?.slippage || 0, } as RoutesSolarParams), getRoutesOrca({ fromToken: params.fromToken?.address || '', toToken: params.toToken?.address || '', fromAmount: params?.fromAmount, slippage: params?.slippage || 0, account: params.account.address, fromTokenDecimals: params?.fromToken?.decimals, toTokenDecimals: params?.toToken?.decimals, } as RoutesOrcaParams), getRoutesLifinity({ fromToken: params.fromToken?.address || '', toToken: params.toToken?.address || '', fromAmount: params?.fromAmount, slippage: params?.slippage || 0, fromTokenDecimals: params?.fromToken?.decimals, toTokenDecimals: params?.toToken?.decimals, } as RoutesLifinityParams), getRoutesInvariant({ fromToken: params.fromToken?.address || '', toToken: params.toToken?.address || '', fromAmount: params?.fromAmount, slippage: params?.slippage || 0, account: params.account, fromTokenDecimals: params?.fromToken?.decimals, toTokenDecimals: params?.toToken?.decimals, } as RoutesInvariantParams), ]).catch((e) => { console.error('>>> e', e); throw new Error(e.message); }); // solar let solarRoute = {}; if (solarRoutes && (solarRoutes as any).value) { const dataRoutesSolar = formatRoutesSolar(solarRoutes, params); solarRoute = dataRoutesSolar.toAmountUSD !== 0 ? dataRoutesSolar : {}; } // orca let orcaRoute = {}; if (orcaRoutes && (orcaRoutes as any).value) { const dataRoutesOrca = formatRoutesOrca(orcaRoutes, params); orcaRoute = dataRoutesOrca.toAmountUSD !== 0 ? dataRoutesOrca : {}; } // lifinity let lifinityRoute = {}; if (lifinityRoutes && (lifinityRoutes as any).value) { const dataRoutesLifinity = formatRoutesLifinity(lifinityRoutes, params); lifinityRoute = dataRoutesLifinity.toAmountUSD !== 0 ? dataRoutesLifinity : {}; } let invariantRoute = {}; if (invariantRoutes && (invariantRoutes as any).value) { const dataRoutesInvariant = formatRoutesInvariant( invariantRoutes, params, ); invariantRoute = dataRoutesInvariant.toAmountUSD !== 0 ? dataRoutesInvariant : {}; } const sortRoute = [solarRoute, orcaRoute, lifinityRoute, invariantRoute] .filter((obj) => Object.keys(obj).length !== 0) .sort((a: any, b: any) => { const aAmount = BigInt(a?.toAmount || 0); const bAmount = BigInt(b?.toAmount || 0); return bAmount > aAmount ? 1 : bAmount < aAmount ? -1 : 0; }) ?.filter( (item: any) => item.fromAmountUSD !== 0 || item.toAmountUSD !== 0, ); return { routes: [ { ...sortRoute[0], tags: ['RECOMMENDED', 'CHEAPEST', 'FASTEST'], }, ...sortRoute.slice(1), ], unavailableRoutes: [], } as any; } catch (e) { console.error(e); return { routes: [], unavailableRoutes: { filteredOut: [], failed: [], }, }; } } if (params.fromChainId === ChainId.SOL) { try { const [jupRoutes, orcaRoutes] = await Promise.allSettled([ getRoutesJup({ fromToken: params.fromToken?.address || '', toToken: params.toToken?.address || '', fromAmount: params?.fromAmount, slippage: Number(params.slippage) * 100 || 0, } as RoutesJupParams), getRoutesOrcaSVM({ fromToken: params.fromToken?.address || '', toToken: params.toToken?.address || '', fromAmount: params?.fromAmount, slippage: Number(params.slippage) * 100 || 0, wallet: params.account.address, } as RoutesOrcaParamsSVM), ]).catch((e) => { console.error('>>> e', e); throw new Error(e.message); }); let jupRoute = {}; if (jupRoutes && (jupRoutes as any).value) { const dataRoutesJup = formatRoutesJup(jupRoutes, params); jupRoute = dataRoutesJup.toAmountUSD !== 0 ? dataRoutesJup : {}; } let orcaRoute = {}; if (orcaRoutes && (orcaRoutes as any).value) { const dataRoutesOrca = formatRoutesOrcaSVM(orcaRoutes, params); orcaRoute = dataRoutesOrca.toAmountUSD !== 0 ? dataRoutesOrca : {}; } const sortRoute = [jupRoute, orcaRoute] .filter((obj) => Object.keys(obj).length !== 0) .sort((a: any, b: any) => { const aAmount = BigInt(a?.toAmount || 0); const bAmount = BigInt(b?.toAmount || 0); return bAmount > aAmount ? 1 : bAmount < aAmount ? -1 : 0; }) ?.filter( (item: any) => item.fromAmountUSD !== 0 || item.toAmountUSD !== 0, ); return { routes: [ { ...sortRoute[0], tags: ['RECOMMENDED', 'CHEAPEST', 'FASTEST'], }, ...sortRoute.slice(1), ], unavailableRoutes: [], } as any; } catch (e) { console.error(e); } } return await request(`${_config.apiUrl}/advanced/routes`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(params), signal: options?.signal, }); };