UNPKG

@crypto-dex-sdk/path-finder-api

Version:

Zenlink Interface Path Finder Api

143 lines (125 loc) 4.46 kB
import type { VercelRequest, VercelResponse } from '@vercel/node' import { ParachainId } from '@crypto-dex-sdk/chain' import { Native } from '@crypto-dex-sdk/currency' import { Router } from '@crypto-dex-sdk/smart-router' import { BigNumber } from 'ethers' import { z } from 'zod' import { getDataFetcher, V2_CHAINS } from './config' import { getToken } from './tokens' const querySchema = z.object({ chainId: z.coerce.number().int().gte(0).lte(2 ** 256).default(ParachainId.ASTAR), fromTokenId: z.string().default('Native'), toTokenId: z.string().default('Native'), gasPrice: z.coerce.number().int().gte(1), amount: z.coerce.string(), to: z.optional(z.string()), priceImpact: z.optional(z.coerce.number()), }) export function getRouteProcessorAddressForChainId(chainId: ParachainId) { switch (chainId) { case ParachainId.ASTAR: return '0x41479dBb983b85587bfEDd11D1Fcfe6ACe138AE1' default: throw new Error(`Unsupported route processor network for ${chainId}`) } } export function getRouteProcessor2AddressForChainId(chainId: ParachainId) { switch (chainId) { case ParachainId.ARBITRUM_ONE: return '0x6A6FC6B4d33E27087410Ff5d5F15995dabDF4Ce7' default: throw new Error(`Unsupported route processor network for ${chainId}`) } } export function getFeeSettlementAddressForChainId(chainId: ParachainId) { switch (chainId) { case ParachainId.ASTAR: return '0x24d20B28a0B5E2B5B724f9b6C60E32E6B505Eb35' case ParachainId.ARBITRUM_ONE: return '0xAFCCA0f68e0883b797c71525377DE46B2E65AB28' default: throw new Error(`Unsupported route processor network for ${chainId}`) } } export default async (request: VercelRequest, response: VercelResponse) => { const { chainId, fromTokenId, toTokenId, amount, gasPrice, to, priceImpact, } = querySchema.parse(request.query) const dataFetcher = getDataFetcher(chainId) if (!dataFetcher) return response.status(400).json({ message: `Unsupported chainId ${chainId}` }) const [fromToken, toToken] = await Promise.all([ getToken(chainId, fromTokenId), getToken(chainId, toTokenId), ]) if (!fromToken || !toToken) return response.status(400).json({ message: `Token not supported ${fromTokenId} or ${toTokenId}` }) dataFetcher.startDataFetching() await dataFetcher.fetchPoolsForToken(fromToken, toToken) const router = new Router( dataFetcher, fromToken, BigNumber.from(amount), toToken, gasPrice ?? 30e9, ) router.startRouting(() => { router.stopRouting() dataFetcher.stopDataFetching() }) const bestRoute = router.getBestRoute() if (!bestRoute) return response.status(400).json({ message: 'Cannot find route, please try again.' }) const poolCodesMap = dataFetcher.getCurrentPoolCodeMap() return response.status(200).json({ routeHumanString: Router.routeToHumanString(dataFetcher, bestRoute, fromToken, toToken), bestRoute: { status: bestRoute.status, fromToken: bestRoute.fromToken.address === '' ? Native.onChain(chainId) : bestRoute.fromToken, toToken: bestRoute.toToken.address === '' ? Native.onChain(chainId) : bestRoute.toToken, primaryPrice: bestRoute.primaryPrice, swapPrice: bestRoute.swapPrice, amountIn: bestRoute.amountIn, amountInBN: bestRoute.amountInBN.toString(), amountOut: bestRoute.amountOut, amountOutBN: bestRoute.amountOutBN.toString(), priceImpact: bestRoute.priceImpact, totalAmountOut: bestRoute.totalAmountOut, totalAmountOutBN: bestRoute.totalAmountOutBN.toString(), gasSpent: bestRoute.gasSpent, legs: bestRoute.legs.map(l => ({ ...l, protocol: poolCodesMap.get(l.poolId)?.poolName, })), }, routeParams: to ? V2_CHAINS.includes(chainId) ? Router.routeProcessorParams2( dataFetcher, bestRoute, fromToken, toToken, to, getRouteProcessor2AddressForChainId(chainId), getFeeSettlementAddressForChainId(chainId), priceImpact, ) : Router.routeProcessorParams( dataFetcher, bestRoute, fromToken, toToken, to, getRouteProcessorAddressForChainId(chainId), getFeeSettlementAddressForChainId(chainId), priceImpact, ) : undefined, }) }