diff --git a/src/helpers/horizon/getHorizonPath.ts b/src/helpers/horizon/getHorizonPath.ts new file mode 100644 index 00000000..d13551af --- /dev/null +++ b/src/helpers/horizon/getHorizonPath.ts @@ -0,0 +1,128 @@ +import { ServerApi } from '@stellar/stellar-sdk/lib/horizon'; +import { Asset } from '@stellar/stellar-sdk' +import { SorobanContextType } from '@soroban-react/core'; +import BigNumber from 'bignumber.js'; +import { CurrencyAmount, TokenType } from 'interfaces'; +import { InterfaceTrade, PlatformType, QuoteState, TradeState, TradeType } from 'state/routing/types'; + +const getClassicAsset = (currency: TokenType) => { + if (!currency) return + if (currency?.code === 'XLM') { + const nativeAsset = Asset.native() + return nativeAsset + } + if (!currency.issuer) { + throw new Error(`Can't convert ${currency.code} to stellar classic asset`) + } + const asset = new Asset(currency.code, currency.issuer) + return asset +} + +const getAmount = (amount: string) => { + return new BigNumber(amount).dividedBy(10000000).toString() +} + +const parseHorizonResult = (payload: ServerApi.PaymentPathRecord, tradeType: TradeType) =>{ + const currecnyIn: TokenType = payload.source_asset_type == 'native' ? { + code: 'XLM', + contract: '', + } : { + code: payload.source_asset_code, + issuer: payload.source_asset_issuer, + contract: `${payload.source_asset_code}:${payload.source_asset_issuer}` + } + const currencyOut: TokenType = payload.destination_asset_type == 'native' ? { + code: 'XLM', + contract: '', + } : { + code: payload.destination_asset_code, + issuer: payload.destination_asset_issuer, + contract: `${payload.destination_asset_code}:${payload.destination_asset_issuer}` + } + const inputAmount: CurrencyAmount = { + currency: currecnyIn, + value: new BigNumber(payload.source_amount).multipliedBy(10000000).toString() + } + const outputAmount: CurrencyAmount = { + currency: currencyOut, + value: new BigNumber(payload.destination_amount).multipliedBy(10000000).toString() + } + const path = [currecnyIn, ...payload.path, currencyOut] + const parsedResult = { + inputAmount: inputAmount, + outputAmount: outputAmount, + tradeType: tradeType, + path: path, + priceImpact: undefined, + platform: PlatformType.STELLAR_CLASSIC, + } + return parsedResult +} + +function getHorizonBestPath( + payload: any, + sorobanContext: SorobanContextType +) { + if (!payload.assetFrom || !payload.assetTo || !payload.amount || !sorobanContext) { + return; + } + + const { serverHorizon, activeChain } = sorobanContext; + if (!serverHorizon || !activeChain) { + console.log('no serverHorizon or activeChain'); + } + + const args = { + assetFrom: getClassicAsset(payload.assetFrom), + assetTo: getClassicAsset(payload.assetTo), + amount: getAmount(payload.amount) + }; + + if (payload.tradeType === TradeType.EXACT_INPUT) { + try { + const send = serverHorizon?.strictSendPaths( + args.assetFrom!, + args?.amount, + [args.assetTo!] + ).call().then((res) => { + return res.records; + }); + return send?.then(res => { + return res.reduce((maxObj, obj) => { + console.log(maxObj) + if (obj.destination_amount > maxObj.destination_amount) { + return obj; + } else { + return maxObj; + } + }); + }); + } catch (error) { + console.log(error); + } + } + + if (payload.tradeType === TradeType.EXACT_OUTPUT) { + try { + const receive = serverHorizon?.strictReceivePaths( + [args.assetFrom!], + args.assetTo!, + args?.amount, + ).call().then((res) => { + return res.records; + }); + + return receive?.then(res => { + return res.reduce((maxObj, obj) => { + if (obj.destination_amount > maxObj.destination_amount) { + return obj; + } else { + return maxObj; + } + }); + }); + } catch (error) { + console.log(error); + } + } +} \ No newline at end of file diff --git a/src/hooks/useBestTrade.ts b/src/hooks/useBestTrade.ts index 5c6e466c..6107a5c9 100644 --- a/src/hooks/useBestTrade.ts +++ b/src/hooks/useBestTrade.ts @@ -2,12 +2,9 @@ import { useRouterSDK } from 'functions/generateRoute'; import { CurrencyAmount, TokenType } from 'interfaces'; import { useEffect, useMemo, useState } from 'react'; import { TradeType as SdkTradeType } from 'soroswap-router-sdk'; -import { InterfaceTrade, QuoteState, TradeState, TradeType, TransactionType } from 'state/routing/types'; +import { InterfaceTrade, PlatformType, QuoteState, TradeState, TradeType } from 'state/routing/types'; import useSWR from 'swr'; -import {Asset} from '@stellar/stellar-sdk' import { SorobanContextType } from '@soroban-react/core'; -import BigNumber from 'bignumber.js'; -import { ServerApi } from '@stellar/stellar-sdk/lib/horizon'; const TRADE_NOT_FOUND = { state: TradeState.NO_ROUTE_FOUND, @@ -15,129 +12,6 @@ const TRADE_NOT_FOUND = { } as const; const TRADE_LOADING = { state: TradeState.LOADING, trade: undefined } as const; -const getClassicAsset = (currency: TokenType) => { - if (!currency) return - if (currency?.code === 'XLM') { - const nativeAsset = Asset.native() - return nativeAsset - } - if (!currency.issuer) { - throw new Error(`Can't convert ${currency.code} to stellar classic asset`) - } - const asset = new Asset(currency.code, currency.issuer) - return asset -} - -const getAmount = (amount: string) => { - return new BigNumber(amount).dividedBy(10000000).toString() -} - -const parseHorizonResult = (payload: ServerApi.PaymentPathRecord, tradeType: TradeType) =>{ - console.log('🔴🔴Object', payload) - const currecnyIn: TokenType = payload.source_asset_type == 'native' ? { - code: 'XLM', - contract: '', - } : { - code: payload.source_asset_code, - issuer: payload.source_asset_issuer, - contract: `${payload.source_asset_code}:${payload.source_asset_issuer}` - } - const currencyOut: TokenType = payload.destination_asset_type == 'native' ? { - code: 'XLM', - contract: '', - } : { - code: payload.destination_asset_code, - issuer: payload.destination_asset_issuer, - contract: `${payload.destination_asset_code}:${payload.destination_asset_issuer}` - } - const inputAmount: CurrencyAmount = { - currency: currecnyIn, - value: new BigNumber(payload.source_amount).multipliedBy(10000000).toString() - } - const outputAmount: CurrencyAmount = { - currency: currencyOut, - value: new BigNumber(payload.destination_amount).multipliedBy(10000000).toString() - } - const path = [currecnyIn, ...payload.path, currencyOut] - const parsedResult = { - inputAmount: inputAmount, - outputAmount: outputAmount, - tradeType: tradeType, - path: path, - priceImpact: undefined, - transctionType: TransactionType.STELLAR_CLASSIC, - } - return parsedResult -} - -function getHorizonBestPath( - payload: any, - sorobanContext: SorobanContextType -) { - if (!payload.assetFrom || !payload.assetTo || !payload.amount || !sorobanContext) { - return; - } - - const { serverHorizon, activeChain } = sorobanContext; - if (!serverHorizon || !activeChain) { - console.log('no serverHorizon or activeChain'); - } - - const args = { - assetFrom: getClassicAsset(payload.assetFrom), - assetTo: getClassicAsset(payload.assetTo), - amount: getAmount(payload.amount) - }; - - if (payload.tradeType === TradeType.EXACT_INPUT) { - try { - const send = serverHorizon?.strictSendPaths( - args.assetFrom!, - args?.amount, - [args.assetTo!] - ).call().then((res) => { - return res.records; - }); - return send?.then(res => { - return res.reduce((maxObj, obj) => { - console.log(maxObj) - if (obj.destination_amount > maxObj.destination_amount) { - return obj; - } else { - return maxObj; - } - }); - }); - } catch (error) { - console.log(error); - } - } - - if (payload.tradeType === TradeType.EXACT_OUTPUT) { - try { - const receive = serverHorizon?.strictReceivePaths( - [args.assetFrom!], - args.assetTo!, - args?.amount, - ).call().then((res) => { - return res.records; - }); - - return receive?.then(res => { - return res.reduce((maxObj, obj) => { - if (obj.destination_amount > maxObj.destination_amount) { - return obj; - } else { - return maxObj; - } - }); - }); - } catch (error) { - console.log(error); - } - } -} - /** * Returns the best v2+v3 trade for a desired swap. * @param tradeType whether the swap is an exact in/out @@ -164,55 +38,6 @@ export function useBestTrade( * @param {number} maxHops - The maximum number of hops allowed for the trade. * @returns {object} - The data, isLoading, and isValidating values from the SWR hook. */ - const payload = { - assetFrom: amountSpecified?.currency, - assetTo: otherCurrency, - amount: amountSpecified?.value, - tradeType: tradeType, - } - const [horizonPath, setHorizonPath] = useState('') - const [soroswapPath, setSoroswapPath] = useState('') - - const calculatePaths = async () => { - if(!amountSpecified || !otherCurrency) return; - await getHorizonBestPath(payload, sorobanContext)?.then(res=>{ - const parsedResult = parseHorizonResult(res, tradeType) - setHorizonPath(parsedResult); - }) - await generateRoute({ - amountTokenAddress: amountSpecified?.currency?.contract!, - quoteTokenAddress: otherCurrency?.contract!, - amount: amountSpecified?.value!, - tradeType: tradeType === TradeType.EXACT_INPUT ? SdkTradeType.EXACT_INPUT : SdkTradeType.EXACT_OUTPUT })?.then(res=>{ - const updatedResult = { - ...res, - transactionType: TransactionType.SOROBAN - }; - setSoroswapPath(updatedResult); - }) - } - - const chooseBestPath = () => { - if(!horizonPath || !soroswapPath) return; - if(horizonPath.destination_amount > soroswapPath.trade.amountOutMin) { - return horizonPath - } else { - return soroswapPath - } - } - - useEffect(() => { - calculatePaths() - }, [amountSpecified, otherCurrency, tradeType]) - - useEffect(() => { - if(!amountSpecified || !otherCurrency) return; - const bestPath = chooseBestPath() - console.log(bestPath) - console.log('🔵', horizonPath) - }, [horizonPath, soroswapPath]) - - // Fetch or save the route in cache const { data, @@ -313,7 +138,7 @@ export function useBestTrade( tradeType: tradeType, rawRoute: data, priceImpact: data?.priceImpact, - transctionType: TransactionType.SOROBAN, + platform: PlatformType.SOROBAN, }; }, [expectedAmount, inputAmount, outputAmount, tradeType, data]);