From 5f663a84fdabfb68bb2712d09570da304aa1c3e8 Mon Sep 17 00:00:00 2001
From: DMY <147dmy@gmail.com>
Date: Fri, 2 Aug 2024 15:55:36 +0800
Subject: [PATCH] fix
---
.../src/assets/icons/swap/max-button.svg | 12 +-
.../SelectSortedChain/ChainItem.tsx | 82 ++--
.../Bridge/components/BridgeContent.tsx | 45 +--
.../Bridge/components/BridgeHistory.tsx | 16 +-
.../Bridge/components/BridgeQuoteItem.tsx | 18 +-
.../Bridge/components/BridgeQuotes.tsx | 10 +-
.../Bridge/components/BridgeReceiveDetail.tsx | 13 +-
.../Bridge/components/BridgeTokenPair.tsx | 14 +-
.../src/screens/Bridge/components/loading.tsx | 9 +-
.../mobile/src/screens/Bridge/hooks/token.tsx | 363 ++++++++++--------
10 files changed, 312 insertions(+), 270 deletions(-)
diff --git a/apps/mobile/src/assets/icons/swap/max-button.svg b/apps/mobile/src/assets/icons/swap/max-button.svg
index 8914329a4..12f886656 100644
--- a/apps/mobile/src/assets/icons/swap/max-button.svg
+++ b/apps/mobile/src/assets/icons/swap/max-button.svg
@@ -1,12 +1,12 @@
-
\ No newline at end of file
diff --git a/apps/mobile/src/components/SelectSortedChain/ChainItem.tsx b/apps/mobile/src/components/SelectSortedChain/ChainItem.tsx
index 26ef5e839..e57d83013 100644
--- a/apps/mobile/src/components/SelectSortedChain/ChainItem.tsx
+++ b/apps/mobile/src/components/SelectSortedChain/ChainItem.tsx
@@ -1,4 +1,4 @@
-import { useMemo } from 'react';
+import { useMemo, useState } from 'react';
import { Image, Text, View } from 'react-native';
import { CHAINS_ENUM, Chain } from '@/constant/chains';
@@ -14,6 +14,7 @@ import { RcWalletCC } from '@/assets/icons/common';
import { formatUsdValue } from '@/utils/number';
import { toast } from '../Toast';
import { TestnetChainLogo } from '../Chain/TestnetChainLogo';
+import { Tip } from '../Tip';
export default function ChainItem({
data,
@@ -48,44 +49,51 @@ export default function ChainItem({
return disabledTips;
}, [data, disabledTips]);
+ const [tipsVisible, setTipsVisible] = useState(false);
+
return (
- {
- if (disabled) {
- finalDisabledTips && toast.info(finalDisabledTips);
- return;
- }
- onPress?.(data?.enum);
- }}>
- {data.isTestnet ? (
-
- ) : (
-
- )}
-
-
- {data?.name}
- {!!chainBalanceItem?.usd_value && (
-
-
-
- {formatUsdValue(chainBalanceItem?.usd_value || 0)}
-
-
- )}
-
-
- {value && value === data?.enum ? : null}
+ setTipsVisible(false)}>
+ {
+ if (disabled) {
+ finalDisabledTips && setTipsVisible(true); // toast.info(finalDisabledTips);
+ return;
+ }
+ onPress?.(data?.enum);
+ }}>
+ {data.isTestnet ? (
+
+ ) : (
+
+ )}
+
+
+ {data?.name}
+ {!!chainBalanceItem?.usd_value && (
+
+
+
+ {formatUsdValue(chainBalanceItem?.usd_value || 0)}
+
+
+ )}
+
+
+ {value && value === data?.enum ? : null}
+
-
-
+
+
);
}
diff --git a/apps/mobile/src/screens/Bridge/components/BridgeContent.tsx b/apps/mobile/src/screens/Bridge/components/BridgeContent.tsx
index 5b0dd7c53..bd2347915 100644
--- a/apps/mobile/src/screens/Bridge/components/BridgeContent.tsx
+++ b/apps/mobile/src/screens/Bridge/components/BridgeContent.tsx
@@ -16,8 +16,6 @@ import {
useQuoteVisible,
useSetQuoteVisible,
useSetRefreshId,
- useSetSettingVisible,
- useSettingVisible,
useTokenPair,
} from '../hooks';
import { useCurrentAccount } from '@/hooks/account';
@@ -100,7 +98,7 @@ const getStyles = createGetStyles(colors => ({
flexDirection: 'row',
height: 52,
borderRadius: 4,
- borderWidth: StyleSheet.hairlineWidth,
+ borderWidth: 1,
borderColor: colors['neutral-line'],
paddingHorizontal: 12,
alignItems: 'center',
@@ -188,15 +186,15 @@ export const BridgeContent = () => {
handleAmountChange,
handleBalance,
- inputAmount,
- debouncePayAmount,
+ payAmount,
inSufficient,
openQuotesList,
quoteLoading,
quoteList,
- notAvailableQuote,
+ noBestQuote,
+
bestQuoteId,
selectedBridgeQuote,
@@ -243,7 +241,7 @@ export const BridgeContent = () => {
from_token_id: payToken.id,
user_addr: currentAccount?.address,
from_chain_id: payToken.chain,
- from_token_raw_amount: new BigNumber(debouncePayAmount)
+ from_token_raw_amount: new BigNumber(payAmount)
.times(10 ** payToken.decimals)
.toFixed(0, 1)
.toString(),
@@ -260,14 +258,14 @@ export const BridgeContent = () => {
toTokenId: receiveToken.id,
toChainId: receiveToken.chain,
status: tx ? 'success' : 'fail',
- payAmount: debouncePayAmount,
+ payAmount: payAmount,
});
bridgeToken(
{
to: tx.to,
value: tx.value,
data: tx.data,
- payTokenRawAmount: new BigNumber(debouncePayAmount)
+ payTokenRawAmount: new BigNumber(payAmount)
.times(10 ** payToken.decimals)
.toFixed(0, 1)
.toString(),
@@ -281,7 +279,7 @@ export const BridgeContent = () => {
bridge_id: selectedBridgeQuote.bridge_id,
from_chain_id: payToken.chain,
from_token_id: payToken.id,
- from_token_amount: debouncePayAmount,
+ from_token_amount: payAmount,
to_chain_id: receiveToken.chain,
to_token_id: receiveToken.id,
to_token_amount: selectedBridgeQuote.to_token_amount,
@@ -307,7 +305,7 @@ export const BridgeContent = () => {
toTokenId: receiveToken.id,
toChainId: receiveToken.chain,
status: 'fail',
- payAmount: debouncePayAmount,
+ payAmount: payAmount,
});
console.error(error);
} finally {
@@ -377,14 +375,14 @@ export const BridgeContent = () => {
-
+
{
placeholderTextColor={colors['neutral-foot']}
/>
- {inputAmount
+ {payAmount
? `≈ ${formatUsdValue(
- new BigNumber(inputAmount)
+ new BigNumber(payAmount)
.times(payToken?.price || 0)
.toString(10),
)}`
@@ -405,24 +403,23 @@ export const BridgeContent = () => {
{quoteLoading &&
- Number(debouncePayAmount) > 0 &&
+ Number(payAmount) > 0 &&
!inSufficient &&
!selectedBridgeQuote?.manualClick && }
{payToken &&
!inSufficient &&
receiveToken &&
- Number(debouncePayAmount) > 0 &&
- (!quoteLoading ||
- (selectedBridgeQuote && selectedBridgeQuote?.manualClick)) && (
+ Number(payAmount) > 0 &&
+ (!quoteLoading || selectedBridgeQuote?.manualClick) && (
)}
@@ -467,7 +464,7 @@ export const BridgeContent = () => {
disabled={
!payToken ||
!receiveToken ||
- !debouncePayAmount ||
+ Number(payAmount) > 0 ||
inSufficient ||
!selectedBridgeQuote
}
@@ -482,7 +479,7 @@ export const BridgeContent = () => {
onConfirm={gotoBridge}
/>
- {payToken && receiveToken && Number(debouncePayAmount) > 0 && chain ? (
+ {payToken && receiveToken && Number(payAmount) > 0 && chain ? (
{
userAddress={currentAccount?.address || ''}
chain={chain}
payToken={payToken}
- payAmount={debouncePayAmount}
+ payAmount={payAmount}
receiveToken={receiveToken}
inSufficient={inSufficient}
setSelectedBridgeQuote={setSelectedBridgeQuote}
diff --git a/apps/mobile/src/screens/Bridge/components/BridgeHistory.tsx b/apps/mobile/src/screens/Bridge/components/BridgeHistory.tsx
index c58ee5758..53c890804 100644
--- a/apps/mobile/src/screens/Bridge/components/BridgeHistory.tsx
+++ b/apps/mobile/src/screens/Bridge/components/BridgeHistory.tsx
@@ -197,14 +197,14 @@ const Transaction = forwardRef(
-
+
{t('page.bridge.detail-tx')}:{' '}
{txId ? ellipsis(txId) : ''}
-
+
{!loading
? t('page.bridge.gas-fee', { gasUsed })
: t('page.bridge.gas-x-price', {
@@ -440,6 +440,7 @@ const getStyles = createGetStyles(colors => ({
paddingTop: 10,
borderTopWidth: 0.5,
borderColor: colors['neutral-line'],
+ gap: 4,
},
transactionDetail: {
fontSize: 13,
@@ -449,9 +450,12 @@ const getStyles = createGetStyles(colors => ({
textDecorationLine: 'underline',
},
gasFee: {
+ textAlign: 'right',
marginLeft: 'auto',
fontSize: 13,
color: colors['neutral-foot'],
+ flex: 1,
+ flexWrap: 'wrap',
},
emptyContainer: {
width: '100%',
@@ -466,7 +470,7 @@ const getStyles = createGetStyles(colors => ({
emptyText: {
textAlign: 'center',
fontSize: 14,
- color: 'rgba(62, 73, 94, 1)', // Update as needed
+ color: colors['neutral-foot'],
},
historyList: {
maxHeight: 434,
@@ -493,7 +497,7 @@ const getStyles = createGetStyles(colors => ({
borderRadius: 6,
},
emptyView: {
- marginTop: 100,
+ marginTop: '50%',
flex: 1,
alignItems: 'center',
justifyContent: 'center',
@@ -503,8 +507,8 @@ const getStyles = createGetStyles(colors => ({
fontSize: 20,
fontWeight: '500',
textAlign: 'center',
- paddingTop: 20,
- paddingBottom: 16,
+ paddingTop: 16,
+ paddingBottom: 4,
backgroundColor: colors['neutral-bg-2'],
color: colors['neutral-title-1'],
},
diff --git a/apps/mobile/src/screens/Bridge/components/BridgeQuoteItem.tsx b/apps/mobile/src/screens/Bridge/components/BridgeQuoteItem.tsx
index 73c17ef6e..bbb936bab 100644
--- a/apps/mobile/src/screens/Bridge/components/BridgeQuoteItem.tsx
+++ b/apps/mobile/src/screens/Bridge/components/BridgeQuoteItem.tsx
@@ -152,7 +152,7 @@ export const BridgeQuoteItem: React.FC = props => {
true}>
-
+
{t('page.bridge.estimated-value', {
value: formatUsdValue(
new BigNumber(props.to_token_amount)
@@ -180,7 +180,10 @@ export const BridgeQuoteItem: React.FC = props => {
styles.badge,
props.isBestQuote ? styles.bestBadge : styles.diffBadge,
]}>
-
+
{props.isBestQuote ? t('page.bridge.best') : diffPercent}
@@ -229,8 +232,8 @@ const getStyles = createGetStyles(colors => ({
flexDirection: 'row',
alignItems: 'center',
gap: 8,
- flex: 1,
justifyContent: 'flex-end',
+ flexShrink: 1,
},
aggregatorName: {
fontSize: 16,
@@ -273,6 +276,7 @@ const getStyles = createGetStyles(colors => ({
flexDirection: 'row',
alignItems: 'center',
gap: 6,
+ flex: 1,
},
estimatedValueText: {
fontSize: 13,
@@ -298,9 +302,15 @@ const getStyles = createGetStyles(colors => ({
diffBadge: {
backgroundColor: colors['red-light'],
},
- badgeText: {
+
+ bestQuoteText: {
fontSize: 12,
fontWeight: '500',
color: colors['green-default'],
},
+ otherQuoteText: {
+ fontSize: 12,
+ fontWeight: '500',
+ color: colors['red-default'],
+ },
}));
diff --git a/apps/mobile/src/screens/Bridge/components/BridgeQuotes.tsx b/apps/mobile/src/screens/Bridge/components/BridgeQuotes.tsx
index 6b60edf4d..0ed4c5b0d 100644
--- a/apps/mobile/src/screens/Bridge/components/BridgeQuotes.tsx
+++ b/apps/mobile/src/screens/Bridge/components/BridgeQuotes.tsx
@@ -24,7 +24,7 @@ const getStyles = createGetStyles(colors => ({
headerContainer: {
flexDirection: 'row',
alignItems: 'center',
- paddingVertical: 20,
+ paddingTop: 20,
paddingLeft: 20,
alignSelf: 'stretch',
gap: 3,
@@ -39,6 +39,7 @@ const getStyles = createGetStyles(colors => ({
fontSize: 12,
fontWeight: '500',
color: colors['neutral-body'],
+ marginLeft: 4,
},
radioContainer: {
@@ -63,6 +64,7 @@ const getStyles = createGetStyles(colors => ({
gap: 12,
marginBottom: 20,
height: '100%',
+ marginTop: 120,
},
emptyText: {
fontSize: 14,
@@ -222,7 +224,11 @@ export const QuoteList = (props: Omit) => {
containerStyle={styles.radioContainer}
/>
-
+
);
diff --git a/apps/mobile/src/screens/Bridge/components/BridgeReceiveDetail.tsx b/apps/mobile/src/screens/Bridge/components/BridgeReceiveDetail.tsx
index cb0f2b599..f34874a1a 100644
--- a/apps/mobile/src/screens/Bridge/components/BridgeReceiveDetail.tsx
+++ b/apps/mobile/src/screens/Bridge/components/BridgeReceiveDetail.tsx
@@ -75,17 +75,12 @@ interface ReceiveDetailsProps {
aggregatorId: string;
};
openQuotesList: () => void;
- isEmptyQuote?: boolean;
+ noBestQuote?: boolean;
}
export const BridgeReceiveDetails = (props: ReceiveDetailsProps) => {
const { t } = useTranslation();
- const {
- activeProvider,
- bestQuoteId,
- openQuotesList,
- isEmptyQuote,
- ...other
- } = props;
+ const { activeProvider, bestQuoteId, openQuotesList, noBestQuote, ...other } =
+ props;
const colors = useThemeColors();
const styles = React.useMemo(() => getStyles(colors), [colors]);
@@ -99,7 +94,7 @@ export const BridgeReceiveDetails = (props: ReceiveDetailsProps) => {
);
if (!activeProvider) {
- if (!isEmptyQuote) {
+ if (!noBestQuote) {
return null;
}
return (
diff --git a/apps/mobile/src/screens/Bridge/components/BridgeTokenPair.tsx b/apps/mobile/src/screens/Bridge/components/BridgeTokenPair.tsx
index ec0a8e107..dbe4bff3d 100644
--- a/apps/mobile/src/screens/Bridge/components/BridgeTokenPair.tsx
+++ b/apps/mobile/src/screens/Bridge/components/BridgeTokenPair.tsx
@@ -139,7 +139,6 @@ const getStyles = createGetStyles(colors => {
alignItems: 'center',
},
tokenText: {
- marginLeft: 12,
fontSize: 16,
fontWeight: '500',
color: colors['neutral-title1'],
@@ -203,16 +202,7 @@ const TokenPairItem = (props: {
setTipVisible(false)}
- content={
-
- {t('page.gasTopUp.InsufficientBalanceTips')}
-
- }>
+ content={t('page.gasTopUp.InsufficientBalanceTips')}>
-
+
{getTokenSymbol(tokenPair.from_token)}
→
diff --git a/apps/mobile/src/screens/Bridge/components/loading.tsx b/apps/mobile/src/screens/Bridge/components/loading.tsx
index 34452fd0f..6c9d0b0fe 100644
--- a/apps/mobile/src/screens/Bridge/components/loading.tsx
+++ b/apps/mobile/src/screens/Bridge/components/loading.tsx
@@ -87,7 +87,6 @@ const SvgComponent = ({ ...props }) => (
);
export const BestQuoteLoading = () => {
- const { t } = useTranslation();
const [animation] = React.useState(new Animated.Value(0));
const colors = useThemeColors();
const styles = React.useMemo(() => getStyles(colors), [colors]);
@@ -96,7 +95,7 @@ export const BestQuoteLoading = () => {
Animated.loop(
Animated.timing(animation, {
toValue: 1,
- duration: 2000,
+ duration: 3000,
useNativeDriver: true,
isInteraction: false,
delay: 0,
@@ -114,7 +113,7 @@ export const BestQuoteLoading = () => {
? [2, 2, 1, 1, 1, 1, 2, 2]
: index === 1
? [1, 1, 1, 1, 2, 2, 1, 1]
- : [1, 1, 2, 2, 1, 1, 1, 1],
+ : [1, 1, 2, 2, 1, 1, 0, 0],
}),
transform: [
@@ -253,8 +252,8 @@ const getStyles = createGetStyles(colors => ({
flexDirection: 'row',
marginLeft: 16,
position: 'relative',
- top: -4,
- left: -2,
+ top: -6,
+ left: -10,
},
dot: {
fontSize: 24,
diff --git a/apps/mobile/src/screens/Bridge/hooks/token.tsx b/apps/mobile/src/screens/Bridge/hooks/token.tsx
index 380d58ca3..2db2eb45d 100644
--- a/apps/mobile/src/screens/Bridge/hooks/token.tsx
+++ b/apps/mobile/src/screens/Bridge/hooks/token.tsx
@@ -10,9 +10,8 @@ import {
} from './context';
import { findChain } from '@/utils/chain';
-import { CHAINS_ENUM } from '@debank/common';
+import { CHAINS, CHAINS_ENUM } from '@debank/common';
import { openapi } from '@/core/request';
-import { CHAINS } from '@/constant/chains';
import { bridgeService } from '@/core/services';
import { useAsyncInitializeChainList } from '@/hooks/useChain';
import { useAggregatorsList, useBridgeSupportedChains } from './atom';
@@ -23,7 +22,7 @@ import { addressUtils } from '@rabby-wallet/base-utils';
import { ETH_USDT_CONTRACT } from '@/constant/swap';
import useAsync from 'react-use/lib/useAsync';
import useDebounce from 'react-use/lib/useDebounce';
-import useDebounceValue from '@/hooks/common/useDebounceValue';
+import useAsyncFn from 'react-use/lib/useAsyncFn';
const { isSameAddress } = addressUtils;
@@ -165,9 +164,7 @@ export const useTokenPair = (userAddress: string) => {
bridgeService.setSelectedToToken(receiveToken);
}, [receiveToken]);
- const [inputAmount, setPayAmount] = useState('');
-
- const debouncePayAmount = useDebounceValue(inputAmount, 300);
+ const [payAmount, setPayAmount] = useState('');
const [selectedBridgeQuote, setOriSelectedBridgeQuote] = useState<
SelectedBridgeQuote | undefined
@@ -193,9 +190,9 @@ export const useTokenPair = (userAddress: string) => {
const inSufficient = useMemo(
() =>
payToken
- ? tokenAmountBn(payToken).lt(debouncePayAmount)
- : new BigNumber(0).lt(debouncePayAmount),
- [payToken, debouncePayAmount],
+ ? tokenAmountBn(payToken).lt(payAmount)
+ : new BigNumber(0).lt(payAmount),
+ [payToken, payAmount],
);
const [quoteList, setQuotesList] = useState([]);
@@ -204,7 +201,7 @@ export const useTokenPair = (userAddress: string) => {
setQuotesList([]);
setSelectedBridgeQuote(undefined);
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [payToken?.id, receiveToken?.id, chain, debouncePayAmount, inSufficient]);
+ }, [payToken?.id, receiveToken?.id, chain, payAmount, inSufficient]);
const visible = useQuoteVisible();
@@ -218,166 +215,201 @@ export const useTokenPair = (userAddress: string) => {
const aggregatorsList = useAggregatorsList();
+ const [noBestQuote, setNoBestQuote] = useState(false);
+
const fetchIdRef = useRef(0);
- const [isEmptyQuote, setIsEmptyQuote] = useState(false);
+ const inFetching = useRef(false);
- const { loading: quoteLoading, error: quotesError } = useAsync(async () => {
- if (
- !inSufficient &&
- userAddress &&
- payToken?.id &&
- receiveToken?.id &&
- receiveToken &&
- chain &&
- Number(debouncePayAmount) > 0 &&
- aggregatorsList.length > 0
- ) {
- fetchIdRef.current += 1;
- const currentFetchId = fetchIdRef.current;
-
- let preQuotesIsEmpty = false;
- const result: SelectedBridgeQuote[] = [];
- setIsEmptyQuote(false);
+ const [{ loading: quoteLoading, error: quotesError }, callGetQuotes] =
+ useAsyncFn(async () => {
+ if (
+ !inSufficient &&
+ userAddress &&
+ payToken?.id &&
+ receiveToken?.id &&
+ receiveToken &&
+ chain &&
+ Number(payAmount) > 0 &&
+ aggregatorsList.length > 0
+ ) {
+ inFetching.current = true;
- setQuotesList(e => {
- if (!e.length) {
- preQuotesIsEmpty = true;
- }
- return e?.map(e => ({ ...e, loading: true }));
- });
+ fetchIdRef.current += 1;
+ const currentFetchId = fetchIdRef.current;
- setSelectedBridgeQuote(undefined);
+ let preQuotesIsEmpty = false;
+ const result: SelectedBridgeQuote[] = [];
- const originData = await openapi
- .getBridgeQuoteList({
- aggregator_ids: aggregatorsList.map(e => e.id).join(','),
- from_token_id: payToken.id,
- user_addr: userAddress,
- from_chain_id: payToken.chain,
- from_token_raw_amount: new BigNumber(debouncePayAmount)
- .times(10 ** payToken.decimals)
- .toFixed(0, 1)
- .toString(),
- to_chain_id: receiveToken.chain,
- to_token_id: receiveToken.id,
- })
- .catch(err => {
- console.log('err', err);
- setIsEmptyQuote(true);
- if (currentFetchId === fetchIdRef.current) {
- stats.report('bridgeQuoteResult', {
- aggregatorIds: aggregatorsList.map(e => e.id).join(','),
- fromChainId: payToken.chain,
- fromTokenId: payToken.id,
- toTokenId: receiveToken.id,
- toChainId: receiveToken.chain,
- status: 'fail',
- amount: debouncePayAmount,
- });
+ setQuotesList(e => {
+ if (!e.length) {
+ preQuotesIsEmpty = true;
}
- })
- .finally(() => {});
-
- const data = originData?.filter(
- quote =>
- !!quote?.bridge &&
- !!quote?.bridge?.id &&
- !!quote?.bridge?.logo_url &&
- !!quote.bridge.name,
- );
-
- if (currentFetchId === fetchIdRef.current) {
- stats.report('bridgeQuoteResult', {
- aggregatorIds: aggregatorsList.map(e => e.id).join(','),
- fromChainId: payToken.chain,
- fromTokenId: payToken.id,
- toTokenId: receiveToken.id,
- toChainId: receiveToken.chain,
- status: data ? (data?.length === 0 ? 'none' : 'success') : 'fail',
+ return e?.map(e => ({ ...e, loading: true }));
});
- }
- if (data && currentFetchId === fetchIdRef.current) {
- if (!preQuotesIsEmpty) {
- setQuotesList(data.map(e => ({ ...e, loading: true })));
+ setSelectedBridgeQuote(undefined);
+
+ const originData = await openapi
+ .getBridgeQuoteList({
+ aggregator_ids: aggregatorsList.map(e => e.id).join(','),
+ from_token_id: payToken.id,
+ user_addr: userAddress,
+ from_chain_id: payToken.chain,
+ from_token_raw_amount: new BigNumber(payAmount)
+ .times(10 ** payToken.decimals)
+ .toFixed(0, 1)
+ .toString(),
+ to_chain_id: receiveToken.chain,
+ to_token_id: receiveToken.id,
+ })
+ .catch(err => {
+ console.log('err', err);
+ if (currentFetchId === fetchIdRef.current) {
+ stats.report('bridgeQuoteResult', {
+ aggregatorIds: aggregatorsList.map(e => e.id).join(','),
+ fromChainId: payToken.chain,
+ fromTokenId: payToken.id,
+ toTokenId: receiveToken.id,
+ toChainId: receiveToken.chain,
+ status: 'fail',
+ amount: payAmount,
+ });
+ }
+ })
+ .finally(() => {});
+
+ const data = originData?.filter(
+ quote =>
+ !!quote?.bridge &&
+ !!quote?.bridge?.id &&
+ !!quote?.bridge?.logo_url &&
+ !!quote.bridge.name,
+ );
+
+ if (currentFetchId === fetchIdRef.current) {
+ stats.report('bridgeQuoteResult', {
+ aggregatorIds: aggregatorsList.map(e => e.id).join(','),
+ fromChainId: payToken.chain,
+ fromTokenId: payToken.id,
+ toTokenId: receiveToken.id,
+ toChainId: receiveToken.chain,
+ status: data ? (data?.length === 0 ? 'none' : 'success') : 'fail',
+ });
}
- await Promise.allSettled(
- data.map(async quote => {
- if (currentFetchId !== fetchIdRef.current) {
- return;
- }
- let tokenApproved = false;
- let allowance = '0';
- const fromChain = findChain({ serverId: payToken?.chain });
- if (payToken?.id === fromChain?.nativeTokenAddress) {
- tokenApproved = true;
- } else {
- allowance = await getERC20Allowance(
- payToken.chain,
- payToken.id,
- quote.approve_contract_id,
- );
- tokenApproved = new BigNumber(allowance).gte(
- new BigNumber(debouncePayAmount).times(10 ** payToken.decimals),
- );
- }
- let shouldTwoStepApprove = false;
- if (
- fromChain?.enum === CHAINS_ENUM.ETH &&
- isSameAddress(payToken.id, ETH_USDT_CONTRACT) &&
- Number(allowance) !== 0 &&
- !tokenApproved
- ) {
- shouldTwoStepApprove = true;
- }
+ if (data && currentFetchId === fetchIdRef.current) {
+ if (!preQuotesIsEmpty) {
+ setQuotesList(data.map(e => ({ ...e, loading: true })));
+ }
- if (preQuotesIsEmpty) {
- result.push({
- ...quote,
- shouldTwoStepApprove,
- shouldApproveToken: !tokenApproved,
- });
- } else {
- if (currentFetchId === fetchIdRef.current) {
- setQuotesList(e => {
- const filteredArr = e.filter(
- item =>
- item.aggregator.id !== quote.aggregator.id ||
- item.bridge.id !== quote.bridge.id,
- );
- return [
- ...filteredArr,
- {
- ...quote,
- loading: false,
- shouldTwoStepApprove,
- shouldApproveToken: !tokenApproved,
- },
- ];
+ await Promise.allSettled(
+ data.map(async quote => {
+ if (currentFetchId !== fetchIdRef.current) {
+ return;
+ }
+ let tokenApproved = false;
+ let allowance = '0';
+ const fromChain = findChain({ serverId: payToken?.chain });
+ if (payToken?.id === fromChain?.nativeTokenAddress) {
+ tokenApproved = true;
+ } else {
+ allowance = await getERC20Allowance(
+ payToken.chain,
+ payToken.id,
+ quote.approve_contract_id,
+ );
+ tokenApproved = new BigNumber(allowance).gte(
+ new BigNumber(payAmount).times(10 ** payToken.decimals),
+ );
+ }
+ let shouldTwoStepApprove = false;
+ if (
+ fromChain?.enum === CHAINS_ENUM.ETH &&
+ isSameAddress(payToken.id, ETH_USDT_CONTRACT) &&
+ Number(allowance) !== 0 &&
+ !tokenApproved
+ ) {
+ shouldTwoStepApprove = true;
+ }
+
+ if (preQuotesIsEmpty) {
+ result.push({
+ ...quote,
+ shouldTwoStepApprove,
+ shouldApproveToken: !tokenApproved,
});
+ } else {
+ if (currentFetchId === fetchIdRef.current) {
+ setQuotesList(e => {
+ const filteredArr = e.filter(
+ item =>
+ item.aggregator.id !== quote.aggregator.id ||
+ item.bridge.id !== quote.bridge.id,
+ );
+ return [
+ ...filteredArr,
+ {
+ ...quote,
+ loading: false,
+ shouldTwoStepApprove,
+ shouldApproveToken: !tokenApproved,
+ },
+ ];
+ });
+ }
}
- }
- }),
- );
+ }),
+ );
- if (preQuotesIsEmpty && currentFetchId === fetchIdRef.current) {
- setQuotesList(result);
+ if (preQuotesIsEmpty && currentFetchId === fetchIdRef.current) {
+ setQuotesList(result);
+ }
}
}
+ }, [
+ inSufficient,
+ aggregatorsList,
+ refreshId,
+ userAddress,
+ payToken?.id,
+ receiveToken?.id,
+ chain,
+ payAmount,
+ ]);
+
+ const [stateChangeLoading, setStateChangeLoading] = useState(false);
+
+ useEffect(() => {
+ if (
+ !inSufficient &&
+ userAddress &&
+ payToken?.id &&
+ receiveToken?.id &&
+ chain &&
+ Number(payAmount) > 0 &&
+ aggregatorsList.length > 0
+ ) {
+ setStateChangeLoading(true);
}
}, [
+ aggregatorsList.length,
+ chain,
inSufficient,
- aggregatorsList,
- refreshId,
- userAddress,
+ payAmount,
payToken?.id,
- receiveToken?.id,
- chain,
- debouncePayAmount,
+ receiveToken,
+ userAddress,
]);
+ useDebounce(
+ () => {
+ callGetQuotes();
+ },
+ 300,
+ [callGetQuotes],
+ );
+
const [bestQuoteId, setBestQuoteId] = useState<
| {
bridgeId: string;
@@ -394,21 +426,13 @@ export const useTokenPair = (userAddress: string) => {
openQuote(true);
}, [openQuote, setRefreshId]);
- const notAvailableQuote = useMemo(
- () =>
- !quoteLoading &&
- !!receiveToken &&
- Number(debouncePayAmount) > 0 &&
- (!quoteList || !quoteList.length),
- [debouncePayAmount, quoteList, quoteLoading, receiveToken],
- );
-
useEffect(() => {
if (
!quoteLoading &&
receiveToken &&
- Number(debouncePayAmount) > 0 &&
- quoteList.every(e => !e.loading)
+ Number(payAmount) > 0 &&
+ quoteList.every(e => !e.loading) &&
+ inFetching.current
) {
const sortedList = quoteList?.sort((b, a) => {
return new BigNumber(a.to_token_amount)
@@ -426,6 +450,8 @@ export const useTokenPair = (userAddress: string) => {
sortedList[0]?.bridge_id &&
sortedList[0]?.aggregator?.id
) {
+ setNoBestQuote(false);
+
setBestQuoteId({
bridgeId: sortedList[0]?.bridge_id,
aggregatorId: sortedList[0]?.aggregator?.id,
@@ -434,14 +460,23 @@ export const useTokenPair = (userAddress: string) => {
setSelectedBridgeQuote(preItem =>
preItem?.manualClick ? preItem : sortedList[0],
);
+ } else {
+ setNoBestQuote(true);
}
+
+ inFetching.current = false;
+ setStateChangeLoading(false);
+
+ return () => {
+ setNoBestQuote(false);
+ };
}
}, [
quoteList,
quoteLoading,
receiveToken,
setSelectedBridgeQuote,
- debouncePayAmount,
+ payAmount,
]);
if (quotesError) {
@@ -452,7 +487,7 @@ export const useTokenPair = (userAddress: string) => {
setExpired(false);
setSelectedBridgeQuote(undefined);
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [payToken?.id, receiveToken?.id, chain, debouncePayAmount, inSufficient]);
+ }, [payToken?.id, receiveToken?.id, chain, payAmount, inSufficient]);
return {
chain,
@@ -465,20 +500,18 @@ export const useTokenPair = (userAddress: string) => {
handleAmountChange,
handleBalance,
- inputAmount,
- debouncePayAmount,
+ payAmount,
inSufficient,
+ noBestQuote: noBestQuote,
- quoteLoading,
+ quoteLoading: stateChangeLoading,
quoteList,
selectedBridgeQuote,
setSelectedBridgeQuote,
openQuotesList,
bestQuoteId,
-
- notAvailableQuote,
expired,
};
};