From 43f7de08f710245df30b6ea81c8f91a4e32fa50f Mon Sep 17 00:00:00 2001 From: chopan123 Date: Sun, 17 Nov 2024 16:28:20 -0300 Subject: [PATCH] direct path working --- src/components/Swap/SwapComponent.tsx | 19 +++++----- src/functions/generateRoute.ts | 53 ++++++++++++++++++++++++++- src/hooks/useBestTrade.ts | 19 +++------- 3 files changed, 66 insertions(+), 25 deletions(-) diff --git a/src/components/Swap/SwapComponent.tsx b/src/components/Swap/SwapComponent.tsx index 14be04d9..e48d1189 100644 --- a/src/components/Swap/SwapComponent.tsx +++ b/src/components/Swap/SwapComponent.tsx @@ -153,7 +153,6 @@ export function SwapComponent({ currencies, inputError: swapInputError, } = useDerivedSwapInfo(state); - useEffect(() => { if ( typeof currencyBalances[Field.OUTPUT] != 'string' && @@ -189,8 +188,8 @@ export function SwapComponent({ const userHasSpecifiedInputOutput = Boolean( currencies[Field.INPUT] && - currencies[Field.OUTPUT] && - Number(parsedAmounts[independentField]?.value) > 0, + currencies[Field.OUTPUT] && + Number(parsedAmounts[independentField]?.value) > 0, ); const fiatValueInput = { data: 0, isLoading: true }; //useUSDPrice(parsedAmounts[Field.INPUT]) //TODO: create USDPrice function when available method to get this, for now it will be shown as loading @@ -209,9 +208,9 @@ export function SwapComponent({ onCurrencySelection(Field.INPUT, inputCurrency); setPrefilledState ? setPrefilledState({ - [Field.INPUT]: { currencyId: inputCurrency.contract }, - [Field.OUTPUT]: { currencyId: prefilledState.OUTPUT?.currencyId }, - }) + [Field.INPUT]: { currencyId: inputCurrency.contract }, + [Field.OUTPUT]: { currencyId: prefilledState.OUTPUT?.currencyId }, + }) : null; }, [onCurrencySelection], @@ -222,9 +221,9 @@ export function SwapComponent({ onCurrencySelection(Field.OUTPUT, outputCurrency); setPrefilledState ? setPrefilledState({ - [Field.INPUT]: { currencyId: prefilledState.OUTPUT?.currencyId }, - [Field.OUTPUT]: { currencyId: outputCurrency.contract }, - }) + [Field.INPUT]: { currencyId: prefilledState.OUTPUT?.currencyId }, + [Field.OUTPUT]: { currencyId: outputCurrency.contract }, + }) : null; }, [onCurrencySelection], @@ -506,7 +505,7 @@ export function SwapComponent({ } showMaxButton={false} hideBalance={false} - onMax={() => {}} + onMax={() => { }} fiatValue={showFiatValueOutput ? fiatValueOutput : undefined} //priceImpact={stablecoinPriceImpact} currency={currencies[Field.OUTPUT] ?? null} diff --git a/src/functions/generateRoute.ts b/src/functions/generateRoute.ts index 938c0beb..4c3f610f 100644 --- a/src/functions/generateRoute.ts +++ b/src/functions/generateRoute.ts @@ -20,6 +20,12 @@ import { getBestPath, getHorizonBestPath } from 'helpers/horizon/getHorizonPath' import { PlatformType } from 'state/routing/types'; import { CurrencyAmount as AmountAsset } from 'interfaces'; import { DexDistribution } from 'helpers/aggregator'; +import { fetchFactory } from 'services/factory'; +import { contractInvoke } from '@soroban-react/contracts'; +import { reservesBNWithTokens } from 'hooks/useReserves'; +import { getPairAddress } from './getPairAddress'; +import BigNumber from 'bignumber.js'; +import { getExpectedAmount } from './getExpectedAmount'; export interface BuildTradeRoute { amountCurrency: AmountAsset | CurrencyAmount; @@ -51,6 +57,7 @@ const queryNetworkDict: { [x: string]: 'MAINNET' | 'TESTNET' } = { }; const shouldUseBackend = process.env.NEXT_PUBLIC_SOROSWAP_BACKEND_ENABLED === 'true'; +const shouldUseDirectPath = process.env.NEXT_PUBLIC_DIRECT_PATH_ENABLED === 'true'; export const useRouterSDK = () => { const sorobanContext = useSorobanReact(); @@ -74,7 +81,6 @@ export const useRouterSDK = () => { routerProtocols.push({ protocol: Protocol.PHOENIX, fn: async () => fetchAllPhoenixPairs(network) }); } } - console.log('routerProtocols:', routerProtocols); return routerProtocols; }, [network, protocolsStatus]); @@ -118,6 +124,51 @@ export const useRouterSDK = () => { tradeType, currentProtocolsStatus, }: GenerateRouteProps) => { + if (shouldUseDirectPath) { + try { + // get pair address from factory + const pairAddress = await getPairAddress(amountAsset.currency.contract, quoteAsset.contract, sorobanContext); + + // Get reserves from pair + const reserves = await reservesBNWithTokens(pairAddress, sorobanContext); + if (!reserves?.reserve0 || !reserves?.reserve1) { + throw new Error('Reserves not found'); + } + + // Get amountOut or amountIn from reserves and tradeType + let outputAmount = await getExpectedAmount( + amountAsset.currency, + quoteAsset, + new BigNumber(amount), + sorobanContext, + tradeType + ); + + // Convert from lumens to stroops (multiply by 10^7) + outputAmount = outputAmount.integerValue(); + + const quoteCurrencyAmount = CurrencyAmount.fromRawAmount(fromAddressToToken(quoteAsset.contract), outputAmount.toString()); + + return { + amountCurrency: amountAsset, + quoteCurrency: CurrencyAmount.fromRawAmount(fromAddressToToken(quoteAsset.contract), outputAmount.toString()), + tradeType, + trade: { + amountIn: tradeType === TradeType.EXACT_INPUT ? amount : outputAmount.toString(), + amountInMax: tradeType === TradeType.EXACT_OUTPUT ? outputAmount.toString() : undefined, + amountOut: tradeType === TradeType.EXACT_INPUT ? outputAmount.toString() : amount, + amountOutMin: tradeType === TradeType.EXACT_INPUT ? outputAmount.toString() : undefined, + path: [amountAsset.currency.contract, quoteAsset.contract], + }, + priceImpact: new Percent('0'), + platform: PlatformType.ROUTER, + } as BuildTradeRoute; + } catch (error) { + console.error('Error generating direct path:', error); + throw error; + } + } + if (!factory) throw new Error('Factory address not found'); const currencyAmount = fromAddressAndAmountToCurrencyAmount( amountAsset.currency.contract, diff --git a/src/hooks/useBestTrade.ts b/src/hooks/useBestTrade.ts index 33a5e459..4433e621 100644 --- a/src/hooks/useBestTrade.ts +++ b/src/hooks/useBestTrade.ts @@ -30,7 +30,7 @@ export function useBestTrade( resetRouterSdkCache: () => void; } { const { generateRoute, resetRouterSdkCache, maxHops } = useRouterSDK(); - const {protocolsStatus} = useContext(AppContext).Settings; + const { protocolsStatus } = useContext(AppContext).Settings; /** * Custom hook that fetches the best trade based on the specified amount and trade type. * @@ -82,7 +82,6 @@ export function useBestTrade( useEffect(() => { if (!data || !currencyIn || !currencyOut) return; - if (tradeType === TradeType.EXACT_INPUT) { const result = data.trade as { amountIn: string; @@ -126,6 +125,7 @@ export function useBestTrade( // Create the trade object const trade: InterfaceTrade = useMemo(() => { + const baseTrade = { inputAmount, outputAmount, @@ -146,7 +146,7 @@ export function useBestTrade( } return baseTrade; - }, [expectedAmount, inputAmount, outputAmount, tradeType, data, protocolsStatus]); + }, [expectedAmount, inputAmount, outputAmount, tradeType, data]); /* If the pairAddress or the trades chenges, we upgrade the tradeResult @@ -158,7 +158,7 @@ export function useBestTrade( const myTradeResult = { state: state, trade: trade }; return myTradeResult; - }, [data, trade, protocolsStatus]); //should get the pair address and quotes + }, [data, trade]); //should get the pair address and quotes const skipFetch: boolean = false; @@ -191,16 +191,7 @@ export function useBestTrade( resetRouterSdkCache, }; } - }, [ - skipFetch, - amountSpecified, - otherCurrency, - tradeResult, - trade, - isLoading, - resetRouterSdkCache, - protocolsStatus - ]); + }, [skipFetch, amountSpecified, otherCurrency, tradeResult, trade, isLoading, resetRouterSdkCache]); return bestTrade; }