From 804c821aedab9ab1f595d8fc5c9d81bc902127f6 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Fri, 13 Dec 2024 11:41:02 +0800 Subject: [PATCH] fix: li.fi unstable quotes use original rate (#8350) --- .../getCowSwapTradeQuote.test.ts | 8 ++- .../JupiterSwapper/swapperApi/getTradeRate.ts | 2 +- .../src/swappers/LifiSwapper/endpoints.ts | 8 ++- .../getTradeQuote/getTradeQuote.ts | 20 ++++-- .../ThorchainSwapper/utils/getL1Rate.ts | 9 +-- .../src/swappers/ZrxSwapper/endpoints.ts | 4 +- .../utils/test-data/setupSwapQuote.ts | 3 +- packages/swapper/src/types.ts | 20 +++--- ...teInput.ts => getTradeQuoteOrRateInput.ts} | 63 ++++++++++++------- .../hooks/useGetSwapperTradeQuoteOrRate.tsx | 6 +- .../useGetTradeQuotes/useGetTradeQuotes.tsx | 52 ++++++++------- .../useGetTradeQuotes/useGetTradeRates.tsx | 6 +- src/components/MultiHopTrade/types.ts | 2 +- .../Stake/Bridge/hooks/useRfoxBridge.ts | 3 +- src/state/apis/swapper/selectors.ts | 5 +- src/state/apis/swapper/swapperApi.ts | 6 +- src/state/apis/swapper/types.ts | 6 +- 17 files changed, 136 insertions(+), 87 deletions(-) rename src/components/MultiHopTrade/hooks/useGetTradeQuotes/{getTradeQuoteInput.ts => getTradeQuoteOrRateInput.ts} (79%) diff --git a/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts b/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts index f50125e5b7b..e87fa85ff56 100644 --- a/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts +++ b/packages/swapper/src/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts @@ -8,7 +8,7 @@ import { COW_SWAP_NATIVE_ASSET_MARKER_ADDRESS, DEFAULT_ADDRESS, } from '../../../cowswap-utils/constants' -import type { GetTradeQuoteInput, SwapperConfig, TradeQuote } from '../../../types' +import type { GetTradeQuoteInput, SwapperConfig, TradeQuote, TradeRate } from '../../../types' import { SwapperName, TradeQuoteError } from '../../../types' import { ETH, @@ -382,6 +382,7 @@ describe('getCowSwapTradeQuote', () => { allowMultiHop: false, slippageTolerancePercentageDecimal: '0.005', // 0.5% quoteOrRate: 'quote', + originalRate: {} as TradeRate, } const maybeTradeQuote = await getCowSwapTradeQuote(input, MOCK_COWSWAP_CONFIG) @@ -409,6 +410,7 @@ describe('getCowSwapTradeQuote', () => { allowMultiHop: false, slippageTolerancePercentageDecimal: '0.005', // 0.5% quoteOrRate: 'quote', + originalRate: {} as TradeRate, } mockedCowService.post.mockReturnValue( @@ -454,6 +456,7 @@ describe('getCowSwapTradeQuote', () => { allowMultiHop: false, slippageTolerancePercentageDecimal: '0.005', // 0.5% quoteOrRate: 'quote', + originalRate: {} as TradeRate, } mockedCowService.post.mockReturnValue( @@ -499,6 +502,7 @@ describe('getCowSwapTradeQuote', () => { allowMultiHop: false, slippageTolerancePercentageDecimal: '0.005', // 0.5% quoteOrRate: 'quote', + originalRate: {} as TradeRate, } mockedCowService.post.mockReturnValue( @@ -544,6 +548,7 @@ describe('getCowSwapTradeQuote', () => { allowMultiHop: false, slippageTolerancePercentageDecimal: '0.005', // 0.5% quoteOrRate: 'quote', + originalRate: {} as TradeRate, } mockedCowService.post.mockReturnValue( @@ -589,6 +594,7 @@ describe('getCowSwapTradeQuote', () => { allowMultiHop: false, slippageTolerancePercentageDecimal: '0.005', // 0.5% quoteOrRate: 'quote', + originalRate: {} as TradeRate, } mockedCowService.post.mockReturnValue( diff --git a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts index c11af9a6196..886ff7cc8cc 100644 --- a/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts +++ b/packages/swapper/src/swappers/JupiterSwapper/swapperApi/getTradeRate.ts @@ -200,7 +200,7 @@ export const getTradeRate = async ( id: uuid(), quoteOrRate: 'rate', rate: inputOutputRate, - receiveAddress: undefined, + receiveAddress, potentialAffiliateBps: affiliateBps, affiliateBps, slippageTolerancePercentageDecimal, diff --git a/packages/swapper/src/swappers/LifiSwapper/endpoints.ts b/packages/swapper/src/swappers/LifiSwapper/endpoints.ts index b1dd5ca4e2f..e03e7cf85a4 100644 --- a/packages/swapper/src/swappers/LifiSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/LifiSwapper/endpoints.ts @@ -64,7 +64,9 @@ export const lifiApi: SwapperApi = { ) return tradeQuoteResult.map(quote => - quote.map(({ selectedLifiRoute, ...tradeQuote }) => { + quote.map(tradeQuote => { + const { selectedLifiRoute } = tradeQuote + // TODO: quotes below the minimum aren't valid and should not be processed as such // selectedLifiRoute will be missing for quotes below the minimum if (!selectedLifiRoute) throw Error('missing selectedLifiRoute') @@ -98,7 +100,9 @@ export const lifiApi: SwapperApi = { const tradeRateResult = await getTradeRate(input as GetEvmTradeRateInput, deps, lifiChainMap) return tradeRateResult.map(quote => - quote.map(({ selectedLifiRoute, ...tradeQuote }) => { + quote.map(tradeQuote => { + const { selectedLifiRoute } = tradeQuote + // TODO: quotes below the minimum aren't valid and should not be processed as such // selectedLifiRoute will be missing for quotes below the minimum if (!selectedLifiRoute) throw Error('missing selectedLifiRoute') diff --git a/packages/swapper/src/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts b/packages/swapper/src/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts index 411e22cb8e6..6ecc147a2a3 100644 --- a/packages/swapper/src/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts +++ b/packages/swapper/src/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts @@ -17,6 +17,7 @@ import { getDefaultSlippageDecimalPercentageForSwapper } from '../../../constant import type { GetEvmTradeQuoteInput, GetEvmTradeQuoteInputBase, + GetEvmTradeRateInput, MultiHopTradeQuoteSteps, SingleHopTradeQuoteSteps, SwapErrorRight, @@ -40,7 +41,7 @@ export async function getTrade({ deps, lifiChainMap, }: { - input: GetEvmTradeQuoteInput & { lifiAllowedTools?: string[] | undefined } + input: GetEvmTradeQuoteInput | GetEvmTradeRateInput deps: SwapperDeps lifiChainMap: Map }): Promise> { @@ -54,7 +55,6 @@ export async function getTrade({ supportsEIP1559, affiliateBps, potentialAffiliateBps, - lifiAllowedTools, quoteOrRate, } = input @@ -104,9 +104,10 @@ export async function getTrade({ // reverts, partial swaps, wrong received tokens (due to out-of-gas mid-trade), etc. For now, // these bridges are disabled. bridges: { deny: ['stargate', 'stargateV2', 'stargateV2Bus', 'amarok', 'arbitrum'] }, - ...(lifiAllowedTools && { - exchanges: { allow: lifiAllowedTools }, - }), + ...(quoteOrRate === 'quote' && + (input.originalRate as LifiTradeRate).lifiTools && { + exchanges: { allow: (input.originalRate as LifiTradeRate).lifiTools }, + }), allowSwitchChain: true, fee: affiliateBpsDecimalPercentage.isZero() ? undefined @@ -147,6 +148,13 @@ export async function getTrade({ const { routes } = routesResponse.unwrap() if (routes.length === 0) { + if (quoteOrRate === 'quote') + return Ok([ + { + ...input.originalRate, + quoteOrRate: 'quote', + } as LifiTradeQuote, + ]) return Err( makeSwapErrorRight({ message: 'no route found', @@ -302,7 +310,7 @@ export async function getTrade({ } export const getTradeQuote = async ( - input: GetEvmTradeQuoteInputBase & { lifiAllowedTools?: string[] | undefined }, + input: GetEvmTradeQuoteInputBase, deps: SwapperDeps, lifiChainMap: Map, ): Promise> => { diff --git a/packages/swapper/src/swappers/ThorchainSwapper/utils/getL1Rate.ts b/packages/swapper/src/swappers/ThorchainSwapper/utils/getL1Rate.ts index b0bfe7d47fe..54eddd355bf 100644 --- a/packages/swapper/src/swappers/ThorchainSwapper/utils/getL1Rate.ts +++ b/packages/swapper/src/swappers/ThorchainSwapper/utils/getL1Rate.ts @@ -17,9 +17,10 @@ import { v4 as uuid } from 'uuid' import { getDefaultSlippageDecimalPercentageForSwapper } from '../../..' import type { - GetEvmTradeQuoteInput, + GetEvmTradeRateInput, GetTradeRateInput, GetUtxoTradeQuoteInput, + GetUtxoTradeRateInput, ProtocolFee, SwapErrorRight, SwapperDeps, @@ -216,7 +217,7 @@ export const getL1Rate = async ( const sellAdapter = deps.assertGetEvmChainAdapter(sellAsset.chainId) const { networkFeeCryptoBaseUnit } = await getEvmTxFees({ adapter: sellAdapter, - supportsEIP1559: Boolean((input as GetEvmTradeQuoteInput).supportsEIP1559), + supportsEIP1559: Boolean((input as GetEvmTradeRateInput).supportsEIP1559), }) const maybeRoutes = await Promise.allSettled( @@ -327,7 +328,7 @@ export const getL1Rate = async ( const feeData = await (async () => { // This is a rate without a wallet connected, so we can't get fees - if (!(input as GetUtxoTradeQuoteInput).xpub) + if (!(input as GetUtxoTradeRateInput).xpub) return { networkFeeCryptoBaseUnit: undefined, protocolFees: getProtocolFees(quote), @@ -340,7 +341,7 @@ export const getL1Rate = async ( const { vault, opReturnData, pubkey } = await getUtxoThorTxInfo({ sellAsset, - xpub: (input as GetUtxoTradeQuoteInput).xpub!, + xpub: (input as unknown as GetUtxoTradeQuoteInput).xpub!, memo, config: deps.config, }) diff --git a/packages/swapper/src/swappers/ZrxSwapper/endpoints.ts b/packages/swapper/src/swappers/ZrxSwapper/endpoints.ts index 9ab8ba9a909..313665bc188 100644 --- a/packages/swapper/src/swappers/ZrxSwapper/endpoints.ts +++ b/packages/swapper/src/swappers/ZrxSwapper/endpoints.ts @@ -10,7 +10,7 @@ import type { EvmTransactionRequest, GetEvmTradeQuoteInputBase, GetEvmTradeRateInput, - GetTradeQuoteInput, + GetTradeRateInput, GetUnsignedEvmTransactionArgs, SwapErrorRight, SwapperApi, @@ -37,7 +37,7 @@ export const zrxApi: SwapperApi = { return tradeQuoteResult.map(tradeQuote => [tradeQuote]) }, getTradeRate: async ( - input: GetTradeQuoteInput, + input: GetTradeRateInput, { assetsById, config }: SwapperDeps, ): Promise> => { const tradeRateResult = await getZrxTradeRate( diff --git a/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts b/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts index 548d848219b..dae83fa6118 100644 --- a/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts +++ b/packages/swapper/src/swappers/utils/test-data/setupSwapQuote.ts @@ -1,7 +1,7 @@ import type { Asset } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' -import type { GetTradeQuoteInput, TradeQuote } from '../../../types' +import type { GetTradeQuoteInput, TradeQuote, TradeRate } from '../../../types' import { SwapperName } from '../../../types' import { DEFAULT_SLIPPAGE } from '../constants' import { FOX_MAINNET, WETH } from './assets' @@ -51,6 +51,7 @@ export const setupQuote = () => { allowMultiHop: false, slippageTolerancePercentageDecimal: DEFAULT_SLIPPAGE, quoteOrRate: 'quote', + originalRate: {} as TradeRate, } return { quoteInput, tradeQuote, buyAsset, sellAsset } diff --git a/packages/swapper/src/types.ts b/packages/swapper/src/types.ts index 9c7426ad601..0da89b9c7d9 100644 --- a/packages/swapper/src/types.ts +++ b/packages/swapper/src/types.ts @@ -157,7 +157,6 @@ type CommonTradeInputBase = { potentialAffiliateBps: string affiliateBps: string allowMultiHop: boolean - lifiAllowedTools?: string[] | undefined slippageTolerancePercentageDecimal?: string } @@ -166,6 +165,7 @@ export type CommonTradeQuoteInput = CommonTradeInputBase & { receiveAddress: string accountNumber: number quoteOrRate: 'quote' + originalRate: TradeRate } type CommonTradeRateInput = CommonTradeInputBase & { @@ -175,7 +175,7 @@ type CommonTradeRateInput = CommonTradeInputBase & { quoteOrRate: 'rate' } -type CommonTradeInput = CommonTradeQuoteInput | CommonTradeRateInput +type CommonTradeInput = CommonTradeQuoteInput export type GetEvmTradeQuoteInputBase = CommonTradeQuoteInput & { chainId: EvmChainId @@ -185,7 +185,7 @@ export type GetEvmTradeRateInput = CommonTradeRateInput & { chainId: EvmChainId supportsEIP1559: false } -export type GetEvmTradeQuoteInput = GetEvmTradeQuoteInputBase | GetEvmTradeRateInput +export type GetEvmTradeQuoteInput = GetEvmTradeQuoteInputBase export type GetCosmosSdkTradeQuoteInputBase = CommonTradeQuoteInput & { chainId: CosmosSdkChainId @@ -206,16 +206,16 @@ type GetUtxoTradeQuoteWithWallet = CommonTradeQuoteInput & { xpub: string } -type GetUtxoTradeRateInput = CommonTradeRateInput & { +export type GetUtxoTradeRateInput = CommonTradeRateInput & { chainId: UtxoChainId - // We need a dummy script type when getting a quote without a wallet - // so we always use SegWit (which works across all UTXO chains) - accountType: UtxoAccountType.P2pkh - accountNumber: undefined - xpub: undefined + accountType: UtxoAccountType + // accountNumber and accountType may be undefined if no wallet is connected + // accountType will default to UtxoAccountType.P2pkh without a wallet connected + accountNumber: number | undefined + xpub: string | undefined } -export type GetUtxoTradeQuoteInput = GetUtxoTradeQuoteWithWallet | GetUtxoTradeRateInput +export type GetUtxoTradeQuoteInput = GetUtxoTradeQuoteWithWallet export type GetTradeQuoteInput = | GetUtxoTradeQuoteInput diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteOrRateInput.ts similarity index 79% rename from src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts rename to src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteOrRateInput.ts index 49113591382..4f061de8a85 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput.ts +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteOrRateInput.ts @@ -1,10 +1,9 @@ import { CHAIN_NAMESPACE, fromChainId } from '@shapeshiftoss/caip' import type { HDWallet } from '@shapeshiftoss/hdwallet-core' import { supportsETH } from '@shapeshiftoss/hdwallet-core' -import type { GetTradeQuoteInput } from '@shapeshiftoss/swapper' +import type { GetTradeQuoteInput, GetTradeRateInput, TradeRate } from '@shapeshiftoss/swapper' import type { Asset, CosmosSdkChainId, EvmChainId, UtxoChainId } from '@shapeshiftoss/types' import { UtxoAccountType } from '@shapeshiftoss/types' -import type { TradeQuoteInputCommonArgs } from 'components/MultiHopTrade/types' import { toBaseUnit } from 'lib/math' import { assertUnreachable } from 'lib/utils' import { assertGetCosmosSdkChainAdapter } from 'lib/utils/cosmosSdk' @@ -12,14 +11,14 @@ import { assertGetEvmChainAdapter } from 'lib/utils/evm' import { assertGetSolanaChainAdapter } from 'lib/utils/solana' import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' -export type GetTradeQuoteInputArgs = { +export type GetTradeQuoteOrRateInputArgs = { sellAsset: Asset buyAsset: Asset sellAccountType: UtxoAccountType | undefined slippageTolerancePercentageDecimal?: string sellAmountBeforeFeesCryptoPrecision: string allowMultiHop: boolean - lifiAllowedTools?: string[] + originalRate?: TradeRate // Potential affiliate bps - may be waved out either entirely or partially with FOX discounts potentialAffiliateBps: string // Actual affiliate bps - if the FOX discounts is off, this will be the same as *affiliateBps* @@ -33,7 +32,7 @@ export type GetTradeQuoteInputArgs = { wallet: HDWallet | undefined } -export const getTradeQuoteInput = async ({ +export const getTradeQuoteOrRateInput = async ({ sellAsset, buyAsset, sellAccountNumber, @@ -43,28 +42,46 @@ export const getTradeQuoteInput = async ({ receiveAddress, sellAmountBeforeFeesCryptoPrecision, allowMultiHop, - lifiAllowedTools, + originalRate, affiliateBps, potentialAffiliateBps, slippageTolerancePercentageDecimal, pubKey, -}: GetTradeQuoteInputArgs): Promise => { - const tradeQuoteInputCommonArgs: TradeQuoteInputCommonArgs = { - sellAmountIncludingProtocolFeesCryptoBaseUnit: toBaseUnit( - sellAmountBeforeFeesCryptoPrecision, - sellAsset.precision, - ), - sellAsset, - buyAsset, - receiveAddress, - accountNumber: sellAccountNumber, - affiliateBps: affiliateBps ?? '0', - potentialAffiliateBps: potentialAffiliateBps ?? '0', - allowMultiHop, - lifiAllowedTools, - slippageTolerancePercentageDecimal, - quoteOrRate, - } +}: GetTradeQuoteOrRateInputArgs): Promise => { + const tradeQuoteInputCommonArgs = + quoteOrRate === 'quote' && receiveAddress && sellAccountNumber !== undefined + ? { + sellAmountIncludingProtocolFeesCryptoBaseUnit: toBaseUnit( + sellAmountBeforeFeesCryptoPrecision, + sellAsset.precision, + ), + sellAsset, + buyAsset, + receiveAddress, + accountNumber: sellAccountNumber, + affiliateBps: affiliateBps ?? '0', + potentialAffiliateBps: potentialAffiliateBps ?? '0', + allowMultiHop, + slippageTolerancePercentageDecimal, + quoteOrRate: 'quote', + originalRate, + } + : { + sellAmountIncludingProtocolFeesCryptoBaseUnit: toBaseUnit( + sellAmountBeforeFeesCryptoPrecision, + sellAsset.precision, + ), + sellAsset, + buyAsset, + receiveAddress, + originalRate, + accountNumber: sellAccountNumber, + affiliateBps: affiliateBps ?? '0', + potentialAffiliateBps: potentialAffiliateBps ?? '0', + allowMultiHop, + slippageTolerancePercentageDecimal, + quoteOrRate: 'rate', + } const { chainNamespace } = fromChainId(sellAsset.chainId) diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useGetSwapperTradeQuoteOrRate.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useGetSwapperTradeQuoteOrRate.tsx index 841e1944e60..3a393cd0244 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useGetSwapperTradeQuoteOrRate.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useGetSwapperTradeQuoteOrRate.tsx @@ -1,5 +1,5 @@ import { skipToken } from '@reduxjs/toolkit/dist/query' -import type { GetTradeQuoteInput, SwapperName } from '@shapeshiftoss/swapper' +import type { GetTradeQuoteInput, GetTradeRateInput, SwapperName } from '@shapeshiftoss/swapper' import { useEffect, useMemo } from 'react' import { swapperApi, useGetTradeQuoteQuery } from 'state/apis/swapper/swapperApi' import { tradeQuoteSlice } from 'state/slices/tradeQuoteSlice/tradeQuoteSlice' @@ -7,14 +7,14 @@ import { useAppDispatch } from 'state/store' export type UseGetSwapperTradeQuoteOrRateArgs = { swapperName: SwapperName | undefined - tradeQuoteInput: GetTradeQuoteInput | typeof skipToken + tradeQuoteOrRateInput: GetTradeQuoteInput | GetTradeRateInput | typeof skipToken skip: boolean pollingInterval: number | undefined } export const useGetSwapperTradeQuoteOrRate = ({ swapperName, - tradeQuoteInput, + tradeQuoteOrRateInput: tradeQuoteInput, pollingInterval, skip, }: UseGetSwapperTradeQuoteOrRateArgs) => { diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx index fce9e1f7772..c580ab3a213 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx @@ -1,7 +1,12 @@ import { skipToken as reduxSkipToken } from '@reduxjs/toolkit/query' import { fromAccountId } from '@shapeshiftoss/caip' import { isLedger } from '@shapeshiftoss/hdwallet-ledger' -import type { GetTradeQuoteInput, TradeQuote, TradeRate } from '@shapeshiftoss/swapper' +import type { + GetTradeQuoteInput, + GetTradeRateInput, + TradeQuote, + TradeRate, +} from '@shapeshiftoss/swapper' import { DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, isExecutableTradeQuote, @@ -13,7 +18,7 @@ import type { LifiTradeRate } from '@shapeshiftoss/swapper/src/swappers/LifiSwap import { skipToken as reactQuerySkipToken, useQuery } from '@tanstack/react-query' import { useCallback, useEffect, useMemo, useRef } from 'react' import { useTradeReceiveAddress } from 'components/MultiHopTrade/components/TradeInput/hooks/useTradeReceiveAddress' -import { getTradeQuoteInput } from 'components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput' +import { getTradeQuoteOrRateInput } from 'components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteOrRateInput' import { useHasFocus } from 'hooks/useHasFocus' import { useWallet } from 'hooks/useWallet/useWallet' import { useWalletSupportsChain } from 'hooks/useWalletSupportsChain/useWalletSupportsChain' @@ -271,26 +276,27 @@ export const useGetTradeQuotes = () => { if (sellAccountNumber === undefined) throw new Error('sellAccountNumber is required') if (!receiveAddress) throw new Error('receiveAddress is required') - const updatedTradeQuoteInput: GetTradeQuoteInput | undefined = await getTradeQuoteInput({ - sellAsset, - sellAccountNumber, - sellAccountType: sellAccountMetadata?.accountType, - buyAsset, - wallet: wallet ?? undefined, - lifiAllowedTools: (activeRateRef?.current as LifiTradeRate)?.lifiTools, - quoteOrRate: 'quote', - receiveAddress, - sellAmountBeforeFeesCryptoPrecision: sellAmountCryptoPrecision, - allowMultiHop: true, - affiliateBps, - potentialAffiliateBps, - // Pass in the user's slippage preference if it's set, else let the swapper use its default - slippageTolerancePercentageDecimal: userSlippageTolerancePercentageDecimal, - pubKey: - wallet && isLedger(wallet) && sellAccountId - ? fromAccountId(sellAccountId).account - : undefined, - }) + const updatedTradeQuoteInput: GetTradeQuoteInput | GetTradeRateInput | undefined = + await getTradeQuoteOrRateInput({ + sellAsset, + sellAccountNumber, + sellAccountType: sellAccountMetadata?.accountType, + buyAsset, + wallet: wallet ?? undefined, + originalRate: activeRateRef?.current as LifiTradeRate, + quoteOrRate: 'quote', + receiveAddress, + sellAmountBeforeFeesCryptoPrecision: sellAmountCryptoPrecision, + allowMultiHop: true, + affiliateBps, + potentialAffiliateBps, + // Pass in the user's slippage preference if it's set, else let the swapper use its default + slippageTolerancePercentageDecimal: userSlippageTolerancePercentageDecimal, + pubKey: + wallet && isLedger(wallet) && sellAccountId + ? fromAccountId(sellAccountId).account + : undefined, + }) return updatedTradeQuoteInput } @@ -341,7 +347,7 @@ export const useGetTradeQuotes = () => { (swapperName: SwapperName | undefined): UseGetSwapperTradeQuoteOrRateArgs => { return { swapperName, - tradeQuoteInput: tradeQuoteInput ?? reduxSkipToken, + tradeQuoteOrRateInput: tradeQuoteInput ?? reduxSkipToken, // Skip trade quotes fetching which aren't for the swapper we have a rate for skip: !swapperName || !shouldFetchTradeQuotes, pollingInterval: diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx index 5e45f5d0e2e..28824e7bdc2 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeRates.tsx @@ -11,7 +11,7 @@ import { isThorTradeRate } from '@shapeshiftoss/swapper/dist/swappers/ThorchainS import { useQuery } from '@tanstack/react-query' import { useCallback, useEffect, useMemo } from 'react' import { useTradeReceiveAddress } from 'components/MultiHopTrade/components/TradeInput/hooks/useTradeReceiveAddress' -import { getTradeQuoteInput } from 'components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteInput' +import { getTradeQuoteOrRateInput } from 'components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteOrRateInput' import { useHasFocus } from 'hooks/useHasFocus' import { useWallet } from 'hooks/useWallet/useWallet' import { useWalletSupportsChain } from 'hooks/useWalletSupportsChain/useWalletSupportsChain' @@ -233,7 +233,7 @@ export const useGetTradeRates = () => { const potentialAffiliateBps = feeBpsBeforeDiscount.toFixed(0) const affiliateBps = feeBps.toFixed(0) - const updatedTradeRateInput = (await getTradeQuoteInput({ + const updatedTradeRateInput = (await getTradeQuoteOrRateInput({ sellAsset, sellAccountNumber, sellAccountType: sellAccountMetadata?.accountType, @@ -261,7 +261,7 @@ export const useGetTradeRates = () => { (swapperName: SwapperName): UseGetSwapperTradeQuoteOrRateArgs => { return { swapperName, - tradeQuoteInput: tradeRateInput ?? skipToken, + tradeQuoteOrRateInput: tradeRateInput ?? skipToken, skip: !shouldRefetchTradeQuotes, pollingInterval: swappers[swapperName]?.pollingInterval ?? DEFAULT_GET_TRADE_QUOTE_POLLING_INTERVAL, diff --git a/src/components/MultiHopTrade/types.ts b/src/components/MultiHopTrade/types.ts index b7517e8aabf..9bf4b88f853 100644 --- a/src/components/MultiHopTrade/types.ts +++ b/src/components/MultiHopTrade/types.ts @@ -32,7 +32,7 @@ export type TradeQuoteInputCommonArgs = Pick< | 'allowMultiHop' | 'slippageTolerancePercentageDecimal' | 'quoteOrRate' - | 'lifiAllowedTools' + | 'originalRate' > export enum TradeInputTab { diff --git a/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts b/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts index 19e25b07f04..57649fc0fc7 100644 --- a/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts +++ b/src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts @@ -3,7 +3,7 @@ import { fromAccountId, fromAssetId } from '@shapeshiftoss/caip' import { CONTRACT_INTERACTION, isEvmChainId } from '@shapeshiftoss/chain-adapters' import { getEthersV5Provider, viemClientByChainId } from '@shapeshiftoss/contracts' import { supportsETH } from '@shapeshiftoss/hdwallet-core' -import type { SwapErrorRight, TradeQuote } from '@shapeshiftoss/swapper' +import type { SwapErrorRight, TradeQuote, TradeRate } from '@shapeshiftoss/swapper' import { arbitrumBridgeApi } from '@shapeshiftoss/swapper/dist/swappers/ArbitrumBridgeSwapper/endpoints' import { getTradeQuoteWithWallet } from '@shapeshiftoss/swapper/dist/swappers/ArbitrumBridgeSwapper/getTradeQuote/getTradeQuote' import type { GetEvmTradeQuoteInputWithWallet } from '@shapeshiftoss/swapper/dist/swappers/ArbitrumBridgeSwapper/types' @@ -145,6 +145,7 @@ export const useRfoxBridge = ({ confirmedQuote }: UseRfoxBridgeProps): UseRfoxBr accountNumber: sellAssetAccountNumber, hasWallet: Boolean(walletInfo?.deviceId), quoteOrRate: 'quote' as const, + originalRate: {} as TradeRate, }), [ buyAsset, diff --git a/src/state/apis/swapper/selectors.ts b/src/state/apis/swapper/selectors.ts index 91f1c2db298..b93e5d586d5 100644 --- a/src/state/apis/swapper/selectors.ts +++ b/src/state/apis/swapper/selectors.ts @@ -4,7 +4,7 @@ import type { PartialRecord } from '@shapeshiftoss/types' import type { ReduxState } from 'state/reducer' import { createDeepEqualOutputSelector } from 'state/selector-utils' -import type { TradeQuoteRequest } from './types' +import type { TradeQuoteOrRateRequest } from './types' const selectSwapperApiQueries = (state: ReduxState) => state.swapperApi.queries @@ -17,7 +17,8 @@ export const selectIsTradeQuoteApiQueryPending = createDeepEqualOutputSelector( for (const [queryKey, queryInfo] of Object.entries(queries)) { if (!queryKey.startsWith('getTradeQuote')) continue - const swapperName = (queryInfo?.originalArgs as TradeQuoteRequest | undefined)?.swapperName + const swapperName = (queryInfo?.originalArgs as TradeQuoteOrRateRequest | undefined) + ?.swapperName if (!swapperName) continue diff --git a/src/state/apis/swapper/swapperApi.ts b/src/state/apis/swapper/swapperApi.ts index 0a145472cf4..d0c19a3cef3 100644 --- a/src/state/apis/swapper/swapperApi.ts +++ b/src/state/apis/swapper/swapperApi.ts @@ -23,7 +23,7 @@ import { assertGetSolanaChainAdapter } from 'lib/utils/solana' import { thorchainBlockTimeMs } from 'lib/utils/thorchain/constants' import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' import { getInputOutputRatioFromQuote } from 'state/apis/swapper/helpers/getInputOutputRatioFromQuote' -import type { ApiQuote, TradeQuoteRequest } from 'state/apis/swapper/types' +import type { ApiQuote, TradeQuoteOrRateRequest } from 'state/apis/swapper/types' import { TradeQuoteValidationError } from 'state/apis/swapper/types' import { getEnabledSwappers } from 'state/helpers' import type { ReduxState } from 'state/reducer' @@ -42,8 +42,8 @@ export const swapperApi = createApi({ keepUnusedDataFor: Number.MAX_SAFE_INTEGER, // never clear, we will manage this tagTypes: ['TradeQuote'], endpoints: build => ({ - getTradeQuote: build.query, TradeQuoteRequest>({ - queryFn: async (tradeQuoteInput: TradeQuoteRequest, { dispatch, getState }) => { + getTradeQuote: build.query, TradeQuoteOrRateRequest>({ + queryFn: async (tradeQuoteInput: TradeQuoteOrRateRequest, { dispatch, getState }) => { const state = getState() as ReduxState const { swapperName, diff --git a/src/state/apis/swapper/types.ts b/src/state/apis/swapper/types.ts index 3809a18d0dd..24cb71f933c 100644 --- a/src/state/apis/swapper/types.ts +++ b/src/state/apis/swapper/types.ts @@ -1,5 +1,6 @@ import type { GetTradeQuoteInput, + GetTradeRateInput, SwapperName, TradeQuote, TradeQuoteError as SwapperTradeQuoteError, @@ -53,4 +54,7 @@ export type ApiQuote = { isStale: boolean } -export type TradeQuoteRequest = { swapperName: SwapperName } & GetTradeQuoteInput +export type TradeQuoteOrRateRequest = { swapperName: SwapperName } & ( + | GetTradeQuoteInput + | GetTradeRateInput +)