Skip to content

Commit

Permalink
chore: wip sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
micaelae committed Oct 9, 2024
1 parent 902b173 commit 8b9b803
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 141 deletions.
174 changes: 78 additions & 96 deletions ui/hooks/bridge/useBridgeAmounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,16 @@ import {
getToChain,
getToToken,
} from '../../ducks/bridge/selectors';
import { useEffect, useMemo, useState } from 'react';
import { useMemo } from 'react';
import { calcTokenAmount } from '../../../shared/lib/transactions-controller-utils';
import { fetchTokenExchangeRates } from '../../helpers/utils/util';
import {
CHAIN_ID_TO_CURRENCY_SYMBOL_MAP,
CHAIN_IDS,
} from '../../../shared/constants/network';
import { CHAIN_ID_TO_CURRENCY_SYMBOL_MAP } from '../../../shared/constants/network';
import { zeroAddress } from '../../__mocks__/ethereumjs-util';
import BigNumber from 'bignumber.js';
import { getConversionRate } from '../../ducks/metamask/metamask';
import { getTokenExchangeRates } from '../../selectors';
import { getRelayerFee, getTotalGasFee } from '../../pages/bridge/utils/quote';
import { RequestStatus } from '../../../app/scripts/controllers/bridge/constants';
import { toChecksumAddress } from 'ethereumjs-util';
import { deepEqual } from 'assert';
import { isEqual } from 'lodash';
import { useAsyncResult } from '../useAsyncResult';

Expand All @@ -37,123 +32,110 @@ const useBridgeAmounts = () => {
getTokenExchangeRates,
shallowEqual,
);

const fromNativeExchangeRate = useSelector(getConversionRate);

// Contains toToken to dest native asset exchange rate
const [toTokenExchangeRate, setToTokenExchangeRate] = useState<
number | undefined
>();
const [toNativeExchangeRate, setToNativeExchangeRate] = useState<number>(1);

const { pending: isToTokenExchangeRateLoading, value: exchangeRates } =
useAsyncResult(async () => {
if (toChain?.chainId && toToken?.address) {
return await fetchTokenExchangeRates(
CHAIN_ID_TO_CURRENCY_SYMBOL_MAP[
toChain.chainId as keyof typeof CHAIN_ID_TO_CURRENCY_SYMBOL_MAP
],
[toToken.address],
toChain.chainId,
);
}
}, [toChain, toToken]);

useEffect(() => {
if (
toChain?.chainId &&
toToken?.address &&
exchangeRates &&
!isToTokenExchangeRateLoading
) {
setToNativeExchangeRate(exchangeRates[zeroAddress()] ?? 1);
if (toToken.address !== zeroAddress()) {
setToTokenExchangeRate(
exchangeRates[toChecksumAddress(toToken.address)],
);
} else {
setToTokenExchangeRate(1);
}
// TODO move this elsewhere to avoid duplicate spot-prices calls
// Fetch toToken to dest native asset exchange rates
const { value } = useAsyncResult<{
toTokenExchangeRate: number | undefined;
toNativeExchangeRate: number;
}>(async () => {
if (toChain?.chainId && toToken?.address) {
return await fetchTokenExchangeRates(
CHAIN_ID_TO_CURRENCY_SYMBOL_MAP[
toChain.chainId as keyof typeof CHAIN_ID_TO_CURRENCY_SYMBOL_MAP
],
[toToken.address],
toChain.chainId,
).then((exchangeRates) => {
return {
toTokenExchangeRate:
toToken.address !== zeroAddress()
? exchangeRates?.[toChecksumAddress(toToken.address)]
: 1,
toNativeExchangeRate: exchangeRates?.[zeroAddress()] ?? 1,
};
});
}
}, [toChain, toToken, exchangeRates]);

return await { toTokenExchangeRate: undefined, toNativeExchangeRate: 1 };
}, [toChain, toToken]);
const { toTokenExchangeRate, toNativeExchangeRate } = value ?? {};

const toAmounts: Record<string, BridgeQuoteAmount> = useMemo(() => {
return Object.fromEntries(
quotes.map((quote) => {
const normalizedDestAmount = calcTokenAmount(
quote.quote.destTokenAmount,
quote.quote.destAsset.decimals,
);
return [
quote.quote.requestId,
{
raw: normalizedDestAmount,
fiat:
toTokenExchangeRate && toNativeExchangeRate
? normalizedDestAmount
.mul(toTokenExchangeRate.toString())
.mul(toNativeExchangeRate.toString())
: null,
},
];
}),
);
return quotes.reduce((acc, quote) => {
const normalizedDestAmount = calcTokenAmount(
quote.quote.destTokenAmount,
quote.quote.destAsset.decimals,
);
acc[quote.quote.requestId] = {
raw: normalizedDestAmount,
fiat:
toTokenExchangeRate && toNativeExchangeRate
? normalizedDestAmount
.mul(toTokenExchangeRate.toString())
.mul(toNativeExchangeRate.toString())
: null,
};
return acc;
}, {} as Record<string, BridgeQuoteAmount>);
}, [toTokenExchangeRate, toNativeExchangeRate, quotes]);

const fromAmounts: Record<string, BridgeQuoteAmount> = useMemo(() => {
return Object.fromEntries(
quotes.map(({ quote: { requestId, srcTokenAmount, srcAsset } }) => {
return quotes.reduce(
(acc, { quote: { requestId, srcTokenAmount, srcAsset } }) => {
const normalizedTokenAmount = calcTokenAmount(
srcTokenAmount,
srcAsset.decimals,
);
return [
requestId,
{
raw: normalizedTokenAmount,
fiat:
fromTokenExchangeRates?.[srcAsset.symbol] &&
fromNativeExchangeRate
? normalizedTokenAmount
.mul(fromTokenExchangeRates[srcAsset.address].toString())
.mul(fromNativeExchangeRate.toString())
: null,
},
];
}),
acc[requestId] = {
raw: normalizedTokenAmount,
fiat:
fromTokenExchangeRates?.[srcAsset.symbol] && fromNativeExchangeRate
? normalizedTokenAmount
.mul(fromTokenExchangeRates[srcAsset.address].toString())
.mul(fromNativeExchangeRate.toString())
: null,
};
return acc;
},
{} as Record<string, BridgeQuoteAmount>,
);
}, [fromTokenExchangeRates, fromNativeExchangeRate, quotes]);

const gasFees: Record<string, BridgeQuoteAmount> = useMemo(() => {
return Object.fromEntries(
quotes.map((quote) => {
return getTotalGasFee(quote, fromNativeExchangeRate);
}),
);
return quotes.reduce((acc, quote) => {
const gasFee = getTotalGasFee(quote, fromNativeExchangeRate);
acc[quote.quote.requestId] = gasFee;
return acc;
}, {} as Record<string, BridgeQuoteAmount>);
}, [quotes, fromNativeExchangeRate]);

const relayerFees: Record<string, BridgeQuoteAmount> = useMemo(() => {
return Object.fromEntries(
quotes.map((quote) => getRelayerFee(quote, fromNativeExchangeRate)),
);
return quotes.reduce((acc, quote) => {
const relayerFee = getRelayerFee(quote, fromNativeExchangeRate);
acc[quote.quote.requestId] = relayerFee;
return acc;
}, {} as Record<string, BridgeQuoteAmount>);
}, [quotes, fromNativeExchangeRate]);

const swapRate = useMemo(() => {
return Object.fromEntries(
quotes.map(({ quote: { requestId, srcAsset, destAsset } }) => [
requestId,
`1 ${srcAsset.symbol} = ${toAmounts[requestId].raw.div(
fromAmounts[requestId].raw,
)} ${destAsset.symbol}`,
]),
const swapRates = useMemo(() => {
return quotes.reduce(
(acc, { quote: { requestId, srcAsset, destAsset } }) => {
acc[requestId] = `1 ${srcAsset.symbol} = ${toAmounts[requestId].raw
.div(fromAmounts[requestId].raw)
.toFixed(4)} ${destAsset.symbol}`;
return acc;
},
{} as Record<string, string>,
);
}, [fromAmounts, toAmounts]);

return {
toAmounts,
gasFees,
relayerFees,
swapRate,
swapRates,
};
};

Expand Down
7 changes: 4 additions & 3 deletions ui/hooks/bridge/useBridgeQuotes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ enum SortOrder {
}

const MAXIMUM_ETA_SECONDS = 60 * 60; // 1 hour
const MAXIMUM_RETURN_VALUE_DIFFERENCE_PERCENTAGE = 0.8; // if a quote returns in x less return than the best quote, ignore it
const MAXIMUM_RETURN_VALUE_DIFFERENCE_PERCENTAGE = 0.8; // if a quote returns in x times less return than the best quote, ignore it

const useBridgeQuotes = () => {
const { quotes } = useSelector(getBridgeQuotes);
Expand All @@ -27,7 +27,7 @@ const useBridgeQuotes = () => {
);
}, [quotes]);

const { toAmounts, gasFees, relayerFees } = useBridgeAmounts();
const { toAmounts, gasFees, relayerFees, swapRates } = useBridgeAmounts();

// Returns {[requestId]: toAmount - gasFees - relayerFees } in fiat
const adjustedReturnByRequestId = useMemo(() => {
Expand Down Expand Up @@ -108,11 +108,12 @@ const useBridgeQuotes = () => {

return {
recommendedQuote,
toAmount: toAmount,
toAmount,
sortedQuotes: sortedRequestIds.map(
(requestId) => quotesByRequestId[requestId],
),
setSortOrder,
quoteMetadata: { toAmounts, gasFees, relayerFees, swapRates },
};
};

Expand Down
33 changes: 28 additions & 5 deletions ui/pages/bridge/quotes/bridge-quote-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,35 @@ import MascotBackgroundAnimation from '../../swaps/mascot-background-animation/m
import { QuoteInfoRow } from './quote-info-row';
import { BridgeQuotesModal } from './bridge-quotes-modal';
import useBridgeQuotes from '../../../hooks/bridge/useBridgeQuotes';
import { getCurrentCurrency } from '../../../selectors';
import { getNativeCurrency } from '../../../ducks/metamask/metamask';

export const BridgeQuoteCard = () => {
const t = useI18nContext();
const { recommendedQuote } = useBridgeQuotes();
const {
recommendedQuote,
quoteMetadata: { gasFees, relayerFees, swapRates },
} = useBridgeQuotes();

const { isLoading } = useSelector(getBridgeQuotes);

const { etaInMinutes, totalFees, quoteRate } =
getQuoteDisplayData(recommendedQuote);
const currency = useSelector(getCurrentCurrency);
const ticker = useSelector(getNativeCurrency);

const recommendedSwapRate = recommendedQuote?.quote.requestId
? swapRates[recommendedQuote.quote.requestId]
: undefined;
const { etaInMinutes, totalFees } = getQuoteDisplayData(
ticker,
currency,
recommendedQuote,
recommendedQuote?.quote.requestId
? gasFees[recommendedQuote.quote.requestId]
: undefined,
recommendedQuote?.quote.requestId
? relayerFees[recommendedQuote.quote.requestId]
: undefined,
);

const secondsUntilNextRefresh = useCountdownTimer();

Expand All @@ -36,7 +56,7 @@ export const BridgeQuoteCard = () => {
);
}

return etaInMinutes && totalFees && quoteRate ? (
return etaInMinutes && totalFees && recommendedSwapRate ? (
<Box className="quote-card">
<BridgeQuotesModal
isOpen={showAllQuotes}
Expand All @@ -52,7 +72,10 @@ export const BridgeQuoteCard = () => {
tooltipText={t('bridgeTimingTooltipText')}
description={t('bridgeTimingMinutes', [etaInMinutes])}
/>
<QuoteInfoRow label={t('quoteRate')} description={quoteRate} />
<QuoteInfoRow
label={t('quoteRate')}
description={recommendedSwapRate}
/>
<QuoteInfoRow
label={t('totalFees')}
tooltipText={t('bridgeTotalFeesTooltipText')}
Expand Down
Loading

0 comments on commit 8b9b803

Please sign in to comment.