diff --git a/src/app/common/crypto-assets/stacks-crypto-asset.utils.spec.ts b/src/app/common/crypto-assets/stacks-crypto-asset.utils.spec.ts index ae948f06fa1..2be4498824c 100644 --- a/src/app/common/crypto-assets/stacks-crypto-asset.utils.spec.ts +++ b/src/app/common/crypto-assets/stacks-crypto-asset.utils.spec.ts @@ -1,5 +1,4 @@ import { StacksFungibleTokenAsset } from '@shared/models/crypto-asset.model'; -import { createMoney } from '@shared/models/money.model'; import { isFtNameLikeStx, @@ -32,7 +31,7 @@ describe(isTransferableStacksFungibleTokenAsset.name, () => { canTransfer: true, hasMemo: true, imageCanonicalUri: '', - price: createMoney(0, 'USD'), + price: null, symbol: 'CAT', }; expect(isTransferableStacksFungibleTokenAsset(asset)).toBeTruthy(); @@ -49,7 +48,7 @@ describe(isTransferableStacksFungibleTokenAsset.name, () => { canTransfer: true, hasMemo: true, imageCanonicalUri: '', - price: createMoney(0, 'USD'), + price: null, symbol: 'CAT', }; expect(isTransferableStacksFungibleTokenAsset(asset)).toBeTruthy(); diff --git a/src/app/common/money/calculate-money.ts b/src/app/common/money/calculate-money.ts index bc332c82d70..fc44e6dee9a 100644 --- a/src/app/common/money/calculate-money.ts +++ b/src/app/common/money/calculate-money.ts @@ -6,7 +6,7 @@ import { isNumber } from '@shared/utils'; import { initBigNumber, sumNumbers } from '../math/helpers'; import { formatMoney } from './format-money'; -import { isMoney } from './is-money'; +import { isMoney } from './money.utils'; export function baseCurrencyAmountInQuote(quantity: Money, { pair, price }: MarketData) { if (quantity.symbol.toLowerCase() !== pair.base.toLowerCase()) diff --git a/src/app/common/money/fiat-conversion.ts b/src/app/common/money/fiat-conversion.ts deleted file mode 100644 index 0159e7aeffe..00000000000 --- a/src/app/common/money/fiat-conversion.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { CryptoCurrencies } from '@shared/models/currencies.model'; -import { createMarketData, createMarketPair } from '@shared/models/market.model'; -import { type Money } from '@shared/models/money.model'; - -import { baseCurrencyAmountInQuote } from './calculate-money'; - -export function checkIsMoneyAmountGreaterThanZero(money: Money) { - return !(money.amount.isNaN() || money.amount.isZero()); -} - -export function convertCryptoCurrencyMoneyToFiat( - currency: CryptoCurrencies, - price: Money, - money: Money -) { - const cryptoCurrencyMarketData = createMarketData(createMarketPair(currency, 'USD'), price); - return baseCurrencyAmountInQuote(money, cryptoCurrencyMarketData); -} diff --git a/src/app/common/money/is-money.ts b/src/app/common/money/money.utils.ts similarity index 54% rename from src/app/common/money/is-money.ts rename to src/app/common/money/money.utils.ts index 9afe70b80fd..7a83e86239a 100644 --- a/src/app/common/money/is-money.ts +++ b/src/app/common/money/money.utils.ts @@ -1,3 +1,5 @@ +import BigNumber from 'bignumber.js'; + import { Money } from '@shared/models/money.model'; import { isObject } from '@shared/utils'; @@ -5,3 +7,8 @@ export function isMoney(val: unknown): val is Money { if (!isObject(val)) return false; return 'amount' in val && 'symbol' in val && 'decimals' in val; } + +export function isMoneyGreaterThanZero(money: Money) { + if (!BigNumber.isBigNumber(money.amount)) return; + return !(money.amount.isNaN() || money.amount.isZero()); +} diff --git a/src/app/common/utils/sort-assets-by-symbol.ts b/src/app/common/utils/sort-assets-by-symbol.ts deleted file mode 100644 index 20e1baa3fa4..00000000000 --- a/src/app/common/utils/sort-assets-by-symbol.ts +++ /dev/null @@ -1,23 +0,0 @@ -interface Asset { - name: string; - icon: string; -} - -export function sortAssetsBySymbol(assets: Asset[]) { - return assets - .sort((a, b) => { - if (a.name < b.name) return -1; - if (a.name > b.name) return 1; - return 0; - }) - .sort((a, b) => { - if (a.name === 'STX') return -1; - if (b.name !== 'STX') return 1; - return 0; - }) - .sort((a, b) => { - if (a.name === 'BTC') return -1; - if (b.name !== 'BTC') return 1; - return 0; - }); -} diff --git a/src/app/components/bitcoin-custom-fee/hooks/use-bitcoin-custom-fee.tsx b/src/app/components/bitcoin-custom-fee/hooks/use-bitcoin-custom-fee.tsx index 2d4c757c11e..710f1e4feb3 100644 --- a/src/app/components/bitcoin-custom-fee/hooks/use-bitcoin-custom-fee.tsx +++ b/src/app/components/bitcoin-custom-fee/hooks/use-bitcoin-custom-fee.tsx @@ -67,7 +67,7 @@ export function useBitcoinCustomFeeMultipleRecipients({ }: UseBitcoinCustomFeeArgsMultipleRecipients) { const { balance } = useCurrentNativeSegwitAddressBalance(); const { data: utxos = [] } = useCurrentNativeSegwitUtxos(); - const btcMarketData = useCryptoCurrencyMarketData('BTC'); + const btcMarketData = useCryptoCurrencyMarketDataMeanAverage('BTC'); return useCallback( (feeRate: number) => { diff --git a/src/app/components/bitcoin-fees-list/use-bitcoin-fees-list-multiple-recipients.ts b/src/app/components/bitcoin-fees-list/use-bitcoin-fees-list-multiple-recipients.ts index cab6be7e977..7532c67a224 100644 --- a/src/app/components/bitcoin-fees-list/use-bitcoin-fees-list-multiple-recipients.ts +++ b/src/app/components/bitcoin-fees-list/use-bitcoin-fees-list-multiple-recipients.ts @@ -13,7 +13,7 @@ import { } from '@app/common/transactions/bitcoin/coinselect/local-coin-selection'; import { UtxoResponseItem } from '@app/query/bitcoin/bitcoin-client'; import { useAverageBitcoinFeeRates } from '@app/query/bitcoin/fees/fee-estimates.hooks'; -import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks'; +import { useCryptoCurrencyMarketDataMeanAverage } from '@app/query/common/market-data/market-data.hooks'; import { FeesListItem } from './bitcoin-fees-list'; @@ -41,7 +41,7 @@ export function useBitcoinFeesListMultipleRecipients({ recipients, utxos, }: UseBitcoinFeesListArgs) { - const btcMarketData = useCryptoCurrencyMarketData('BTC'); + const btcMarketData = useCryptoCurrencyMarketDataMeanAverage('BTC'); const { data: feeRates, isLoading } = useAverageBitcoinFeeRates(); const feesList: FeesListItem[] = useMemo(() => { diff --git a/src/app/components/crypto-assets/bitcoin/brc20-token-asset-list/brc20-token-asset-item.layout.tsx b/src/app/components/crypto-assets/bitcoin/brc20-token-asset-list/brc20-token-asset-item.layout.tsx index 0ce58463fb0..5d34221558c 100644 --- a/src/app/components/crypto-assets/bitcoin/brc20-token-asset-list/brc20-token-asset-item.layout.tsx +++ b/src/app/components/crypto-assets/bitcoin/brc20-token-asset-list/brc20-token-asset-item.layout.tsx @@ -3,11 +3,9 @@ import { styled } from 'leather-styles/jsx'; import { createMoney } from '@shared/models/money.model'; import { formatBalance } from '@app/common/format-balance'; -import { - checkIsMoneyAmountGreaterThanZero, - convertCryptoCurrencyMoneyToFiat, -} from '@app/common/money/fiat-conversion'; +import { baseCurrencyAmountInQuote } from '@app/common/money/calculate-money'; import { i18nFormatCurrency } from '@app/common/money/format-money'; +import { isMoneyGreaterThanZero } from '@app/common/money/money.utils'; import { Brc20Token } from '@app/query/bitcoin/bitcoin-client'; import { Brc20AvatarIcon } from '@app/ui/components/avatar/brc20-avatar-icon'; import { ItemLayout } from '@app/ui/components/item-layout/item-layout'; @@ -22,12 +20,9 @@ export function Brc20TokenAssetItemLayout({ onClick, token }: Brc20TokenAssetIte const balanceAsMoney = createMoney(Number(token.overall_balance), token.ticker, token.decimals); const balanceAsString = balanceAsMoney.amount.toString(); const formattedBalance = formatBalance(balanceAsString); - const priceAsMoney = createMoney(token.min_listed_unit_price, 'USD'); - const showFiatBalance = checkIsMoneyAmountGreaterThanZero(priceAsMoney); + const showFiatBalance = isMoneyGreaterThanZero(token.price?.price); const balanceAsFiat = showFiatBalance - ? i18nFormatCurrency( - convertCryptoCurrencyMoneyToFiat(token.ticker, priceAsMoney, balanceAsMoney) - ) + ? i18nFormatCurrency(baseCurrencyAmountInQuote(balanceAsMoney, token.price)) : ''; return ( diff --git a/src/app/components/crypto-assets/stacks/fungible-token-asset/fungible-token-asset.utils.ts b/src/app/components/crypto-assets/stacks/fungible-token-asset/fungible-token-asset.utils.ts index ada3faf3059..e3c80fd4521 100644 --- a/src/app/components/crypto-assets/stacks/fungible-token-asset/fungible-token-asset.utils.ts +++ b/src/app/components/crypto-assets/stacks/fungible-token-asset/fungible-token-asset.utils.ts @@ -4,11 +4,9 @@ import type { StacksFungibleTokenAssetBalance } from '@shared/models/crypto-asse import { getImageCanonicalUri } from '@app/common/crypto-assets/stacks-crypto-asset.utils'; import { formatBalance } from '@app/common/format-balance'; -import { - checkIsMoneyAmountGreaterThanZero, - convertCryptoCurrencyMoneyToFiat, -} from '@app/common/money/fiat-conversion'; +import { baseCurrencyAmountInQuote } from '@app/common/money/calculate-money'; import { i18nFormatCurrency } from '@app/common/money/format-money'; +import { isMoneyGreaterThanZero } from '@app/common/money/money.utils'; import { ftDecimals } from '@app/common/stacks-utils'; import { formatContractId, getTicker } from '@app/common/utils'; import { spamFilter } from '@app/common/utils/spam-filter'; @@ -35,16 +33,10 @@ export function parseStacksFungibleTokenAssetBalance( const title = spamFilter(friendlyName); const showFiatBalance = - assetBalance.asset.price && checkIsMoneyAmountGreaterThanZero(assetBalance.asset.price); + assetBalance.asset.price && isMoneyGreaterThanZero(assetBalance.asset.price.price); const balanceAsFiat = showFiatBalance ? assetBalance.asset.price && - i18nFormatCurrency( - convertCryptoCurrencyMoneyToFiat( - assetBalance.balance.symbol, - assetBalance.asset.price, - assetBalance.balance - ) - ) + i18nFormatCurrency(baseCurrencyAmountInQuote(assetBalance.balance, assetBalance.asset.price)) : ''; return { diff --git a/src/app/pages/receive/components/receive-tokens.tsx b/src/app/pages/receive/components/receive-tokens.tsx index 1c8f47ee75e..62356b724db 100644 --- a/src/app/pages/receive/components/receive-tokens.tsx +++ b/src/app/pages/receive/components/receive-tokens.tsx @@ -4,15 +4,12 @@ import { HomePageSelectors } from '@tests/selectors/home.selectors'; import { css } from 'leather-styles/css'; import { Stack } from 'leather-styles/jsx'; -import { isDefined } from '@shared/utils'; - import { copyToClipboard } from '@app/common/utils/copy-to-clipboard'; -import { sortAssetsBySymbol } from '@app/common/utils/sort-assets-by-symbol'; import { useToast } from '@app/features/toasts/use-toast'; -import { useAlexSdkSwappableCurrencyQuery } from '@app/query/common/alex-sdk/swappable-currency.query'; +import { useAlexSwappableAssets } from '@app/query/common/alex-sdk/alex-sdk.hooks'; import { useConfigRunesEnabled } from '@app/query/common/remote-config/remote-config.query'; import { useCurrentNetwork } from '@app/store/networks/networks.selectors'; -import { Avatar, defaultFallbackDelay, getAvatarFallback } from '@app/ui/components/avatar/avatar'; +import { Avatar, defaultFallbackDelay } from '@app/ui/components/avatar/avatar'; import { Brc20AvatarIcon } from '@app/ui/components/avatar/brc20-avatar-icon'; import { BtcAvatarIcon } from '@app/ui/components/avatar/btc-avatar-icon'; import { RunesAvatarIcon } from '@app/ui/components/avatar/runes-avatar-icon'; @@ -39,20 +36,19 @@ export function ReceiveTokens({ const toast = useToast(); const network = useCurrentNetwork(); const runesEnabled = useConfigRunesEnabled(); - const { data: supportedCurrencies = [] } = useAlexSdkSwappableCurrencyQuery(); + const { data: swapAssets = [] } = useAlexSwappableAssets(); const receivableAssets = useMemo( () => - sortAssetsBySymbol(supportedCurrencies.filter(isDefined)) + swapAssets .filter(asset => asset.name !== 'STX') .map(asset => ({ + ...asset, address: stxAddress, - fallback: getAvatarFallback(asset.name), - icon: asset.icon, - name: asset.name, })), - [stxAddress, supportedCurrencies] + [stxAddress, swapAssets] ); + return ( ); @@ -57,27 +56,18 @@ function AlexSwapContainer() { }); const { - fetchToAmount, - createSwapAssetFromAlexCurrency, + fetchQuoteAmount, isFetchingExchangeRate, onSetIsFetchingExchangeRate, onSetSwapSubmissionData, slippage, - supportedCurrencies, + swapAssets, swapSubmissionData, } = useAlexSwap(); const broadcastAlexSwap = useAlexBroadcastSwap(); const broadcastStacksSwap = useStacksBroadcastSwap(); - const swappableAssets: SwapAsset[] = useMemo( - () => - sortSwappableAssetsBySymbol( - supportedCurrencies.map(createSwapAssetFromAlexCurrency).filter(isDefined) - ), - [createSwapAssetFromAlexCurrency, supportedCurrencies] - ); - async function onSubmitSwapForReview(values: SwapFormValues) { if (isUndefined(values.swapAssetBase) || isUndefined(values.swapAssetQuote)) { logger.error('Error submitting swap for review'); @@ -96,9 +86,7 @@ function AlexSwapContainer() { liquidityFee: new BigNumber(Number(lpFee)).dividedBy(oneHundredMillion).toNumber(), nonce: values.nonce, protocol: 'ALEX', - router: router - .map(x => createSwapAssetFromAlexCurrency(supportedCurrencies.find(y => y.id === x))) - .filter(isDefined), + router: router.map(x => swapAssets.find(asset => asset.currency === x)).filter(isDefined), slippage, sponsored: isSponsoredByAlex, swapAmountBase: values.swapAmountBase, @@ -191,15 +179,15 @@ function AlexSwapContainer() { } const swapContextValue: SwapContext = { - fetchToAmount, + fetchQuoteAmount, isFetchingExchangeRate, isSendingMax, onSetIsFetchingExchangeRate, onSetIsSendingMax: value => setIsSendingMax(value), onSubmitSwapForReview, onSubmitSwap, - swappableAssetsBase: migratePositiveBalancesToTop(swappableAssets), - swappableAssetsQuote: swappableAssets, + swappableAssetsBase: migratePositiveBalancesToTop(swapAssets), + swappableAssetsQuote: swapAssets, swapSubmissionData, }; diff --git a/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-item.tsx b/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-item.tsx index 2b191fd32bf..403ecc74f72 100644 --- a/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-item.tsx +++ b/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-item.tsx @@ -1,11 +1,9 @@ import { SwapSelectors } from '@tests/selectors/swap.selectors'; -import { - checkIsMoneyAmountGreaterThanZero, - convertCryptoCurrencyMoneyToFiat, -} from '@app/common/money/fiat-conversion'; +import { baseCurrencyAmountInQuote } from '@app/common/money/calculate-money'; import { formatMoneyWithoutSymbol, i18nFormatCurrency } from '@app/common/money/format-money'; -import type { SwapAsset } from '@app/pages/swap/hooks/use-swap-form'; +import { isMoneyGreaterThanZero } from '@app/common/money/money.utils'; +import type { SwapAsset } from '@app/query/common/alex-sdk/alex-sdk.hooks'; import { useGetFungibleTokenMetadataQuery } from '@app/query/stacks/tokens/fungible-tokens/fungible-token-metadata.query'; import { isFtAsset } from '@app/query/stacks/tokens/token-metadata.utils'; import { Avatar, defaultFallbackDelay, getAvatarFallback } from '@app/ui/components/avatar/avatar'; @@ -22,11 +20,9 @@ export function SwapAssetItem({ asset, onClick }: SwapAssetItemProps) { const ftMetadataName = ftMetadata && isFtAsset(ftMetadata) ? ftMetadata.name : asset.name; const displayName = asset.displayName ?? ftMetadataName; const fallback = getAvatarFallback(asset.name); - const showFiatBalance = checkIsMoneyAmountGreaterThanZero(asset.price); + const showFiatBalance = isMoneyGreaterThanZero(asset.price.price); const balanceAsFiat = showFiatBalance - ? i18nFormatCurrency( - convertCryptoCurrencyMoneyToFiat(asset.balance.symbol, asset.price, asset.balance) - ) + ? i18nFormatCurrency(baseCurrencyAmountInQuote(asset.balance, asset.price)) : ''; return ( diff --git a/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-list.tsx b/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-list.tsx index 736c2152b17..1c2cf94a93f 100644 --- a/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-list.tsx +++ b/src/app/pages/swap/components/swap-asset-dialog/components/swap-asset-list.tsx @@ -12,8 +12,9 @@ import { isUndefined } from '@shared/utils'; import { convertAmountToFractionalUnit } from '@app/common/money/calculate-money'; import { formatMoneyWithoutSymbol } from '@app/common/money/format-money'; import { useSwapContext } from '@app/pages/swap/swap.context'; +import type { SwapAsset } from '@app/query/common/alex-sdk/alex-sdk.hooks'; -import { SwapAsset, SwapFormValues } from '../../../hooks/use-swap-form'; +import { SwapFormValues } from '../../../hooks/use-swap-form'; import { SwapAssetItem } from './swap-asset-item'; interface SwapAssetList { @@ -21,7 +22,7 @@ interface SwapAssetList { type: string; } export function SwapAssetList({ assets, type }: SwapAssetList) { - const { fetchToAmount } = useSwapContext(); + const { fetchQuoteAmount } = useSwapContext(); const { setFieldError, setFieldValue, values } = useFormikContext(); const navigate = useNavigate(); const { base, quote } = useParams(); @@ -35,33 +36,33 @@ export function SwapAssetList({ assets, type }: SwapAssetList) { ); async function onSelectAsset(asset: SwapAsset) { - let from: SwapAsset | undefined; - let to: SwapAsset | undefined; + let baseAsset: SwapAsset | undefined; + let quoteAsset: SwapAsset | undefined; if (isBaseList) { - from = asset; - to = values.swapAssetQuote; + baseAsset = asset; + quoteAsset = values.swapAssetQuote; await setFieldValue('swapAssetBase', asset); - navigate(RouteUrls.Swap.replace(':base', from.name).replace(':quote', quote ?? '')); + navigate(RouteUrls.Swap.replace(':base', baseAsset.name).replace(':quote', quote ?? '')); } else if (isQuoteList) { - from = values.swapAssetBase; - to = asset; + baseAsset = values.swapAssetBase; + quoteAsset = asset; await setFieldValue('swapAssetQuote', asset); setFieldError('swapAssetQuote', undefined); - navigate(RouteUrls.Swap.replace(':base', base ?? '').replace(':quote', to.name)); + navigate(RouteUrls.Swap.replace(':base', base ?? '').replace(':quote', quoteAsset.name)); } - if (from && to && values.swapAmountBase) { - const toAmount = await fetchToAmount(from, to, values.swapAmountBase); - if (isUndefined(toAmount)) { + if (baseAsset && quoteAsset && values.swapAmountBase) { + const quoteAmount = await fetchQuoteAmount(baseAsset, quoteAsset, values.swapAmountBase); + if (isUndefined(quoteAmount)) { await setFieldValue('swapAmountQuote', ''); return; } - const toAmountAsMoney = createMoney( - convertAmountToFractionalUnit(new BigNumber(toAmount), to?.balance.decimals), - to?.balance.symbol ?? '', - to?.balance.decimals + const quoteAmountAsMoney = createMoney( + convertAmountToFractionalUnit(new BigNumber(quoteAmount), quoteAsset?.balance.decimals), + quoteAsset?.balance.symbol ?? '', + quoteAsset?.balance.decimals ); - await setFieldValue('swapAmountQuote', formatMoneyWithoutSymbol(toAmountAsMoney)); + await setFieldValue('swapAmountQuote', formatMoneyWithoutSymbol(quoteAmountAsMoney)); setFieldError('swapAmountQuote', undefined); } } diff --git a/src/app/pages/swap/components/swap-asset-select/components/swap-amount-field.tsx b/src/app/pages/swap/components/swap-asset-select/components/swap-amount-field.tsx index f3db4fe81d1..e47d3a5df55 100644 --- a/src/app/pages/swap/components/swap-asset-select/components/swap-amount-field.tsx +++ b/src/app/pages/swap/components/swap-asset-select/components/swap-amount-field.tsx @@ -27,7 +27,7 @@ interface SwapAmountFieldProps { name: string; } export function SwapAmountField({ amountAsFiat, isDisabled, name }: SwapAmountFieldProps) { - const { fetchToAmount, isFetchingExchangeRate, onSetIsSendingMax } = useSwapContext(); + const { fetchQuoteAmount, isFetchingExchangeRate, onSetIsSendingMax } = useSwapContext(); const { setFieldError, setFieldValue, values } = useFormikContext(); const [field] = useField(name); const showError = useShowFieldError(name) && name === 'swapAmountBase' && values.swapAssetQuote; @@ -37,7 +37,7 @@ export function SwapAmountField({ amountAsFiat, isDisabled, name }: SwapAmountFi if (isUndefined(swapAssetBase) || isUndefined(swapAssetQuote)) return; onSetIsSendingMax(false); const value = event.currentTarget.value; - const toAmount = await fetchToAmount(swapAssetBase, swapAssetQuote, value); + const toAmount = await fetchQuoteAmount(swapAssetBase, swapAssetQuote, value); if (isUndefined(toAmount)) { await setFieldValue('swapAmountQuote', ''); return; diff --git a/src/app/pages/swap/components/swap-asset-select/components/swap-toggle-button.tsx b/src/app/pages/swap/components/swap-asset-select/components/swap-toggle-button.tsx index e6db08a873d..d305b1a45e9 100644 --- a/src/app/pages/swap/components/swap-asset-select/components/swap-toggle-button.tsx +++ b/src/app/pages/swap/components/swap-asset-select/components/swap-toggle-button.tsx @@ -12,7 +12,7 @@ import { SwapFormValues } from '../../../hooks/use-swap-form'; import { useSwapContext } from '../../../swap.context'; export function SwapToggleButton() { - const { fetchToAmount, isFetchingExchangeRate, onSetIsSendingMax } = useSwapContext(); + const { fetchQuoteAmount, isFetchingExchangeRate, onSetIsSendingMax } = useSwapContext(); const { setFieldValue, validateForm, values } = useFormikContext(); const navigate = useNavigate(); @@ -29,7 +29,7 @@ export function SwapToggleButton() { await setFieldValue('swapAmountBase', prevAmountQuote); if (isDefined(prevAssetBase) && isDefined(prevAssetQuote)) { - const quoteAmount = await fetchToAmount(prevAssetQuote, prevAssetBase, prevAmountQuote); + const quoteAmount = await fetchQuoteAmount(prevAssetQuote, prevAssetBase, prevAmountQuote); if (isUndefined(quoteAmount)) { await setFieldValue('swapAmountQuote', ''); return; diff --git a/src/app/pages/swap/components/swap-asset-select/swap-asset-select-base.tsx b/src/app/pages/swap/components/swap-asset-select/swap-asset-select-base.tsx index 94221abaa7b..028607af00b 100644 --- a/src/app/pages/swap/components/swap-asset-select/swap-asset-select-base.tsx +++ b/src/app/pages/swap/components/swap-asset-select/swap-asset-select-base.tsx @@ -22,7 +22,7 @@ const maxAvailableTooltip = const sendingMaxTooltip = 'When sending max, this amount is affected by the fee you choose.'; export function SwapAssetSelectBase() { - const { fetchToAmount, isFetchingExchangeRate, isSendingMax, onSetIsSendingMax } = + const { fetchQuoteAmount, isFetchingExchangeRate, isSendingMax, onSetIsSendingMax } = useSwapContext(); const { setFieldValue, setFieldError, values } = useFormikContext(); const [amountField, amountFieldMeta, amountFieldHelpers] = useField('swapAmountBase'); @@ -48,7 +48,7 @@ export function SwapAssetSelectBase() { await amountFieldHelpers.setValue(Number(formattedBalance)); await amountFieldHelpers.setTouched(true); if (isUndefined(swapAssetQuote)) return; - const toAmount = await fetchToAmount(swapAssetBase, swapAssetQuote, formattedBalance); + const toAmount = await fetchQuoteAmount(swapAssetBase, swapAssetQuote, formattedBalance); if (isUndefined(toAmount)) { await setFieldValue('swapAmountQuote', ''); return; diff --git a/src/app/pages/swap/hooks/use-alex-swap.tsx b/src/app/pages/swap/hooks/use-alex-swap.tsx index 71034ec39c5..d66bc80cd59 100644 --- a/src/app/pages/swap/hooks/use-alex-swap.tsx +++ b/src/app/pages/swap/hooks/use-alex-swap.tsx @@ -1,22 +1,13 @@ -import { useCallback, useState } from 'react'; +import { useState } from 'react'; -import { Currency, TokenInfo } from 'alex-sdk'; import BigNumber from 'bignumber.js'; import { logger } from '@shared/logger'; -import { createMoney } from '@shared/models/money.model'; import { alex } from '@shared/utils/alex-sdk'; -import { useStxBalance } from '@app/common/hooks/balance/stx/use-stx-balance'; -import { convertAmountToFractionalUnit } from '@app/common/money/calculate-money'; -import { pullContractIdFromIdentity } from '@app/common/utils'; -import { useAlexSdkLatestPricesQuery } from '@app/query/common/alex-sdk/latest-prices.query'; -import { useAlexSdkSwappableCurrencyQuery } from '@app/query/common/alex-sdk/swappable-currency.query'; -import { useTransferableStacksFungibleTokenAssetBalances } from '@app/query/stacks/balance/stacks-ft-balances.hooks'; -import { useCurrentStacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks'; +import { type SwapAsset, useAlexSwappableAssets } from '@app/query/common/alex-sdk/alex-sdk.hooks'; import { SwapSubmissionData } from '../swap.context'; -import { SwapAsset } from './use-swap-form'; export const oneHundredMillion = 100_000_000; @@ -24,62 +15,18 @@ export function useAlexSwap() { const [swapSubmissionData, setSwapSubmissionData] = useState(); const [slippage, _setSlippage] = useState(0.04); const [isFetchingExchangeRate, setIsFetchingExchangeRate] = useState(false); - const { data: supportedCurrencies = [] } = useAlexSdkSwappableCurrencyQuery(); - const { data: prices } = useAlexSdkLatestPricesQuery(); - const { availableBalance: availableStxBalance } = useStxBalance(); - const account = useCurrentStacksAccount(); - const stacksFtAssetBalances = useTransferableStacksFungibleTokenAssetBalances( - account?.address ?? '' - ); + const { data: swapAssets = [] } = useAlexSwappableAssets(); - const createSwapAssetFromAlexCurrency = useCallback( - (tokenInfo?: TokenInfo) => { - if (!prices) return; - if (!tokenInfo) { - logger.error('No token data found to swap'); - return; - } - - const currency = tokenInfo.id as Currency; - const price = convertAmountToFractionalUnit(new BigNumber(prices[currency] ?? 0), 2); - const swapAsset = { - currency, - icon: tokenInfo.icon, - name: tokenInfo.name, - price: createMoney(price, 'USD'), - principal: pullContractIdFromIdentity(tokenInfo.contractAddress), - }; - - if (currency === Currency.STX) { - return { - ...swapAsset, - balance: availableStxBalance, - displayName: 'Stacks', - }; - } - - const fungibleTokenBalance = - stacksFtAssetBalances.find(x => tokenInfo.contractAddress === x.asset.contractId) - ?.balance ?? createMoney(0, tokenInfo.name, tokenInfo.decimals); - - return { - ...swapAsset, - balance: fungibleTokenBalance, - }; - }, - [availableStxBalance, prices, stacksFtAssetBalances] - ); - - async function fetchToAmount( - from: SwapAsset, - to: SwapAsset, - fromAmount: string + async function fetchQuoteAmount( + base: SwapAsset, + quote: SwapAsset, + baseAmount: string ): Promise { - const amount = new BigNumber(fromAmount).multipliedBy(oneHundredMillion).dp(0).toString(); + const amount = new BigNumber(baseAmount).multipliedBy(oneHundredMillion).dp(0).toString(); const amountAsBigInt = isNaN(Number(amount)) ? BigInt(0) : BigInt(amount); try { setIsFetchingExchangeRate(true); - const result = await alex.getAmountTo(from.currency, amountAsBigInt, to.currency); + const result = await alex.getAmountTo(base.currency, amountAsBigInt, quote.currency); setIsFetchingExchangeRate(false); return new BigNumber(Number(result)).dividedBy(oneHundredMillion).toString(); } catch (e) { @@ -90,13 +37,12 @@ export function useAlexSwap() { } return { - fetchToAmount, - createSwapAssetFromAlexCurrency, + fetchQuoteAmount, isFetchingExchangeRate, onSetIsFetchingExchangeRate: (value: boolean) => setIsFetchingExchangeRate(value), onSetSwapSubmissionData: (value: SwapSubmissionData) => setSwapSubmissionData(value), slippage, - supportedCurrencies, + swapAssets, swapSubmissionData, }; } diff --git a/src/app/pages/swap/hooks/use-swap-form.tsx b/src/app/pages/swap/hooks/use-swap-form.tsx index 0121f80b6de..9dac104f423 100644 --- a/src/app/pages/swap/hooks/use-swap-form.tsx +++ b/src/app/pages/swap/hooks/use-swap-form.tsx @@ -1,25 +1,15 @@ -import { Currency } from 'alex-sdk'; import BigNumber from 'bignumber.js'; import * as yup from 'yup'; import { FormErrorMessages } from '@shared/error-messages'; import { FeeTypes } from '@shared/models/fees/fees.model'; import { StacksTransactionFormValues } from '@shared/models/form.model'; -import { Money, createMoney } from '@shared/models/money.model'; +import { createMoney } from '@shared/models/money.model'; import { convertAmountToFractionalUnit } from '@app/common/money/calculate-money'; +import type { SwapAsset } from '@app/query/common/alex-sdk/alex-sdk.hooks'; import { useNextNonce } from '@app/query/stacks/nonce/account-nonces.hooks'; -export interface SwapAsset { - balance: Money; - currency: Currency; - displayName?: string; - icon: string; - name: string; - price: Money; - principal: string; -} - export interface SwapFormValues extends StacksTransactionFormValues { swapAmountBase: string; swapAmountQuote: string; diff --git a/src/app/pages/swap/swap.context.ts b/src/app/pages/swap/swap.context.ts index 2b98312c02d..deec0ddbd6f 100644 --- a/src/app/pages/swap/swap.context.ts +++ b/src/app/pages/swap/swap.context.ts @@ -1,6 +1,8 @@ import { createContext, useContext } from 'react'; -import { SwapAsset, SwapFormValues } from './hooks/use-swap-form'; +import type { SwapAsset } from '@app/query/common/alex-sdk/alex-sdk.hooks'; + +import { SwapFormValues } from './hooks/use-swap-form'; export interface SwapSubmissionData extends SwapFormValues { liquidityFee: number; @@ -12,7 +14,7 @@ export interface SwapSubmissionData extends SwapFormValues { } export interface SwapContext { - fetchToAmount(from: SwapAsset, to: SwapAsset, fromAmount: string): Promise; + fetchQuoteAmount(from: SwapAsset, to: SwapAsset, fromAmount: string): Promise; isFetchingExchangeRate: boolean; isSendingMax: boolean; onSetIsFetchingExchangeRate(value: boolean): void; diff --git a/src/app/pages/swap/swap.utils.ts b/src/app/pages/swap/swap.utils.ts index e05a135802d..c31910c2e93 100644 --- a/src/app/pages/swap/swap.utils.ts +++ b/src/app/pages/swap/swap.utils.ts @@ -1,49 +1,17 @@ +import type { MarketData } from '@shared/models/market.model'; import { type Money, createMoney } from '@shared/models/money.model'; -import { - checkIsMoneyAmountGreaterThanZero, - convertCryptoCurrencyMoneyToFiat, -} from '@app/common/money/fiat-conversion'; +import { baseCurrencyAmountInQuote } from '@app/common/money/calculate-money'; +import { isMoneyGreaterThanZero } from '@app/common/money/money.utils'; import { unitToFractionalUnit } from '@app/common/money/unit-conversion'; -import { SwapAsset } from './hooks/use-swap-form'; - -export const defaultSwapFee = createMoney(1000000, 'STX'); - -export function sortSwappableAssetsBySymbol(swappableAssets: SwapAsset[]) { - return swappableAssets - .sort((a, b) => { - if (a.name < b.name) return -1; - if (a.name > b.name) return 1; - return 0; - }) - .sort((a, b) => { - if (a.name === 'STX') return -1; - if (b.name !== 'STX') return 1; - return 0; - }) - .sort((a, b) => { - if (a.name === 'BTC') return -1; - if (b.name !== 'BTC') return 1; - return 0; - }); -} - -export function migratePositiveBalancesToTop(swappableAssets: SwapAsset[]) { - const assetsWithPositiveBalance = swappableAssets.filter(asset => - asset.balance.amount.isGreaterThan(0) - ); - const assetsWithZeroBalance = swappableAssets.filter(asset => asset.balance.amount.isEqualTo(0)); - return [...assetsWithPositiveBalance, ...assetsWithZeroBalance]; -} - -export function convertInputAmountValueToFiat(balance: Money, price: Money, value: string) { +export function convertInputAmountValueToFiat(balance: Money, price: MarketData, value: string) { const valueAsMoney = createMoney( unitToFractionalUnit(balance.decimals)(value), balance.symbol, balance.decimals ); - if (!checkIsMoneyAmountGreaterThanZero(valueAsMoney)) return; - return convertCryptoCurrencyMoneyToFiat(balance.symbol, price, valueAsMoney); + if (!isMoneyGreaterThanZero(valueAsMoney)) return; + return baseCurrencyAmountInQuote(valueAsMoney, price); } diff --git a/src/app/query/bitcoin/bitcoin-client.ts b/src/app/query/bitcoin/bitcoin-client.ts index c7c7c285061..2ad60bd361b 100644 --- a/src/app/query/bitcoin/bitcoin-client.ts +++ b/src/app/query/bitcoin/bitcoin-client.ts @@ -8,6 +8,7 @@ import { HIRO_API_BASE_URL_MAINNET, } from '@shared/constants'; import { Paginated } from '@shared/models/api-types'; +import type { MarketData } from '@shared/models/market.model'; import type { Money } from '@shared/models/money.model'; import type { BitcoinTx } from '@shared/models/transactions/bitcoin-transaction.model'; @@ -70,12 +71,13 @@ interface Brc20TokenResponse { available_balance: string; transferrable_balance: string; image_url: string | null; - min_listed_unit_price: number; + min_listed_unit_price: number | null; } export interface Brc20Token extends Brc20TokenResponse { decimals: number; holderAddress: string; + price: MarketData; } interface Brc20TokenTicker { diff --git a/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.query.ts b/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.query.ts index 4df6782d3ca..26ddfcdad0c 100644 --- a/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.query.ts +++ b/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.query.ts @@ -1,6 +1,10 @@ import { useCallback, useEffect } from 'react'; import { useInfiniteQuery } from '@tanstack/react-query'; +import BigNumber from 'bignumber.js'; + +import { createMarketData, createMarketPair } from '@shared/models/market.model'; +import { createMoney } from '@shared/models/money.model'; import { useAnalytics } from '@app/common/hooks/analytics/use-analytics'; import { createNumArrayOfRange } from '@app/common/utils'; @@ -64,6 +68,10 @@ export function useGetBrc20TokensQuery() { ...token, decimals: tickerPromises[index].data.decimals, holderAddress: address, + price: createMarketData( + createMarketPair(token.ticker, 'USD'), + createMoney(new BigNumber(token.min_listed_unit_price ?? 0), 'USD') + ), }; }); }); diff --git a/src/app/query/common/alex-sdk/latest-prices.query.ts b/src/app/query/common/alex-sdk/alex-sdk-latest-prices.query.ts similarity index 100% rename from src/app/query/common/alex-sdk/latest-prices.query.ts rename to src/app/query/common/alex-sdk/alex-sdk-latest-prices.query.ts diff --git a/src/app/query/common/alex-sdk/alex-sdk-swappable-currency.query.ts b/src/app/query/common/alex-sdk/alex-sdk-swappable-currency.query.ts new file mode 100644 index 00000000000..ba62c6001cb --- /dev/null +++ b/src/app/query/common/alex-sdk/alex-sdk-swappable-currency.query.ts @@ -0,0 +1,25 @@ +import { useQuery } from '@tanstack/react-query'; +import type { TokenInfo } from 'alex-sdk'; + +import { alex } from '@shared/utils/alex-sdk'; + +import type { AppUseQueryConfig } from '@app/query/query-config'; + +const queryOptions = { + refetchOnMount: false, + refetchOnReconnect: false, + refetchOnWindowFocus: false, + retryDelay: 1000 * 60, + staleTime: 1000 * 60 * 10, +}; + +export function useAlexSdkSwappableCurrencyQuery( + options?: AppUseQueryConfig +) { + return useQuery({ + queryKey: ['alex-sdk-swappable-currencies'], + queryFn: async () => alex.fetchSwappableCurrency(), + ...queryOptions, + ...options, + }); +} diff --git a/src/app/query/common/alex-sdk/alex-sdk.hooks.ts b/src/app/query/common/alex-sdk/alex-sdk.hooks.ts index 5add887bfbf..88b56d0e230 100644 --- a/src/app/query/common/alex-sdk/alex-sdk.hooks.ts +++ b/src/app/query/common/alex-sdk/alex-sdk.hooks.ts @@ -1,19 +1,37 @@ import { useCallback } from 'react'; -import { type Currency } from 'alex-sdk'; +import { Currency, type TokenInfo } from 'alex-sdk'; import BigNumber from 'bignumber.js'; import { logger } from '@shared/logger'; -import { createMoney } from '@shared/models/money.model'; +import { type MarketData, createMarketData, createMarketPair } from '@shared/models/market.model'; +import { type Money, createMoney } from '@shared/models/money.model'; import { isDefined } from '@shared/utils'; +import { useStxBalance } from '@app/common/hooks/balance/stx/use-stx-balance'; import { convertAmountToFractionalUnit } from '@app/common/money/calculate-money'; import { pullContractIdFromIdentity } from '@app/common/utils'; +import { useTransferableStacksFungibleTokenAssetBalances } from '@app/query/stacks/balance/stacks-ft-balances.hooks'; +import { useCurrentStacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks'; +import { getAvatarFallback } from '@app/ui/components/avatar/avatar'; -import { useAlexSdkLatestPricesQuery } from './latest-prices.query'; -import { useAlexSdkSwappableCurrencyQuery } from './swappable-currency.query'; +import { useAlexSdkLatestPricesQuery } from './alex-sdk-latest-prices.query'; +import { useAlexSdkSwappableCurrencyQuery } from './alex-sdk-swappable-currency.query'; +import { sortSwappableAssetsBySymbol } from './alex-sdk.utils'; -export function useAlexSdKCurrencyPriceAsMoney() { +export interface SwapAsset { + address?: string; + balance: Money; + currency: Currency; + displayName?: string; + fallback: string; + icon: string; + name: string; + price: MarketData; + principal: string; +} + +export function useAlexCurrencyPriceAsMarketData() { const { data: supportedCurrencies = [] } = useAlexSdkSwappableCurrencyQuery(); const { data: prices } = useAlexSdkLatestPricesQuery(); @@ -26,10 +44,69 @@ export function useAlexSdKCurrencyPriceAsMoney() { const tokenInfo = supportedCurrencies .filter(isDefined) .find(token => pullContractIdFromIdentity(token.contractAddress) === principal); - const currency = tokenInfo?.id as Currency; + if (!tokenInfo) { + logger.error('No token data found to create market data'); + return null; + } + const currency = tokenInfo.id as Currency; const price = convertAmountToFractionalUnit(new BigNumber(prices[currency] ?? 0), 2); - return createMoney(price, 'USD'); + return createMarketData(createMarketPair(tokenInfo.name, 'USD'), createMoney(price, 'USD')); }, [prices, supportedCurrencies] ); } + +function useMakeSwapAsset() { + const account = useCurrentStacksAccount(); + const { data: prices } = useAlexSdkLatestPricesQuery(); + const { availableBalance: availableStxBalance } = useStxBalance(); + const stacksFtAssetBalances = useTransferableStacksFungibleTokenAssetBalances( + account?.address ?? '' + ); + + return useCallback( + (tokenInfo?: TokenInfo): SwapAsset | undefined => { + if (!prices) return; + if (!tokenInfo) { + logger.error('No token data found to swap'); + return; + } + + const currency = tokenInfo.id as Currency; + const price = convertAmountToFractionalUnit(new BigNumber(prices[currency] ?? 0), 2); + const swapAsset = { + currency, + fallback: getAvatarFallback(tokenInfo.name), + icon: tokenInfo.icon, + name: tokenInfo.name, + price: createMarketData(createMarketPair(tokenInfo.name, 'USD'), createMoney(price, 'USD')), + principal: pullContractIdFromIdentity(tokenInfo.contractAddress), + }; + + if (currency === Currency.STX) { + return { + ...swapAsset, + balance: availableStxBalance, + displayName: 'Stacks', + }; + } + + const fungibleTokenBalance = + stacksFtAssetBalances.find(x => tokenInfo.contractAddress === x.asset.contractId) + ?.balance ?? createMoney(0, tokenInfo.name, tokenInfo.decimals); + + return { + ...swapAsset, + balance: fungibleTokenBalance, + }; + }, + [availableStxBalance, prices, stacksFtAssetBalances] + ); +} + +export function useAlexSwappableAssets() { + const makeSwapAsset = useMakeSwapAsset(); + return useAlexSdkSwappableCurrencyQuery({ + select: resp => sortSwappableAssetsBySymbol(resp.map(makeSwapAsset).filter(isDefined)), + }); +} diff --git a/src/app/query/common/alex-sdk/alex-sdk.utils.ts b/src/app/query/common/alex-sdk/alex-sdk.utils.ts new file mode 100644 index 00000000000..5ea74224afe --- /dev/null +++ b/src/app/query/common/alex-sdk/alex-sdk.utils.ts @@ -0,0 +1,32 @@ +import { createMoney } from '@shared/models/money.model'; + +import type { SwapAsset } from './alex-sdk.hooks'; + +export const defaultSwapFee = createMoney(1000000, 'STX'); + +export function sortSwappableAssetsBySymbol(swappableAssets: SwapAsset[]) { + return swappableAssets + .sort((a, b) => { + if (a.name < b.name) return -1; + if (a.name > b.name) return 1; + return 0; + }) + .sort((a, b) => { + if (a.name === 'STX') return -1; + if (b.name !== 'STX') return 1; + return 0; + }) + .sort((a, b) => { + if (a.name === 'BTC') return -1; + if (b.name !== 'BTC') return 1; + return 0; + }); +} + +export function migratePositiveBalancesToTop(swappableAssets: SwapAsset[]) { + const assetsWithPositiveBalance = swappableAssets.filter(asset => + asset.balance.amount.isGreaterThan(0) + ); + const assetsWithZeroBalance = swappableAssets.filter(asset => asset.balance.amount.isEqualTo(0)); + return [...assetsWithPositiveBalance, ...assetsWithZeroBalance]; +} diff --git a/src/app/query/common/alex-sdk/swappable-currency.query.ts b/src/app/query/common/alex-sdk/swappable-currency.query.ts deleted file mode 100644 index 792b60b603e..00000000000 --- a/src/app/query/common/alex-sdk/swappable-currency.query.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useQuery } from '@tanstack/react-query'; - -import { alex } from '@shared/utils/alex-sdk'; - -export function useAlexSdkSwappableCurrencyQuery() { - return useQuery(['alex-sdk-swappable-currencies'], async () => alex.fetchSwappableCurrency(), { - refetchOnMount: false, - refetchOnReconnect: false, - refetchOnWindowFocus: false, - retryDelay: 1000 * 60, - staleTime: 1000 * 60 * 10, - }); -} diff --git a/src/app/query/stacks/balance/stacks-ft-balances.hooks.ts b/src/app/query/stacks/balance/stacks-ft-balances.hooks.ts index 1dcd2a36d37..898b816bd97 100644 --- a/src/app/query/stacks/balance/stacks-ft-balances.hooks.ts +++ b/src/app/query/stacks/balance/stacks-ft-balances.hooks.ts @@ -7,7 +7,7 @@ import type { StacksFungibleTokenAssetBalance } from '@shared/models/crypto-asse import { formatContractId } from '@app/common/utils'; import { useToast } from '@app/features/toasts/use-toast'; -import { useAlexSdKCurrencyPriceAsMoney } from '@app/query/common/alex-sdk/alex-sdk.hooks'; +import { useAlexCurrencyPriceAsMarketData } from '@app/query/common/alex-sdk/alex-sdk.hooks'; import { useCurrentStacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks'; import { useGetFungibleTokenMetadataListQuery } from '../tokens/fungible-tokens/fungible-token-metadata.query'; @@ -36,7 +36,7 @@ function useStacksFungibleTokenAssetBalances(address: string) { export function useStacksFungibleTokenAssetBalancesWithMetadata(address: string) { const { data: initializedAssetBalances = [] } = useStacksFungibleTokenAssetBalances(address); - const priceAsMoney = useAlexSdKCurrencyPriceAsMoney(); + const priceAsMarketData = useAlexCurrencyPriceAsMarketData(); const ftAssetsMetadata = useGetFungibleTokenMetadataListQuery( initializedAssetBalances.map(assetBalance => @@ -52,7 +52,7 @@ export function useStacksFungibleTokenAssetBalancesWithMetadata(address: string) return addQueriedMetadataToInitializedStacksFungibleTokenAssetBalance( assetBalance, metadata, - priceAsMoney( + priceAsMarketData( formatContractId(assetBalance.asset.contractAddress, assetBalance.asset.contractName) ) ); diff --git a/src/app/query/stacks/balance/stacks-ft-balances.utils.ts b/src/app/query/stacks/balance/stacks-ft-balances.utils.ts index 159d0af3409..57da74b70dd 100644 --- a/src/app/query/stacks/balance/stacks-ft-balances.utils.ts +++ b/src/app/query/stacks/balance/stacks-ft-balances.utils.ts @@ -7,7 +7,8 @@ import type { StacksCryptoCurrencyAssetBalance, StacksFungibleTokenAssetBalance, } from '@shared/models/crypto-asset-balance.model'; -import { type Money, createMoney } from '@shared/models/money.model'; +import { type MarketData } from '@shared/models/market.model'; +import { createMoney } from '@shared/models/money.model'; import { isTransferableStacksFungibleTokenAsset } from '@app/common/crypto-assets/stacks-crypto-asset.utils'; import { getAssetStringParts } from '@app/ui/utils/get-asset-string-parts'; @@ -70,7 +71,7 @@ export function convertFtBalancesToStacksFungibleTokenAssetBalanceType( export function addQueriedMetadataToInitializedStacksFungibleTokenAssetBalance( assetBalance: StacksFungibleTokenAssetBalance, metadata: FtMetadataResponse, - price: Money | null + price: MarketData | null ) { return { ...assetBalance, diff --git a/src/shared/models/crypto-asset.model.ts b/src/shared/models/crypto-asset.model.ts index c91dc8d6f5b..88f500ed6d4 100644 --- a/src/shared/models/crypto-asset.model.ts +++ b/src/shared/models/crypto-asset.model.ts @@ -1,4 +1,4 @@ -import type { Money } from './money.model'; +import type { MarketData } from './market.model'; export interface BitcoinCryptoCurrencyAsset { decimals: number; @@ -24,7 +24,7 @@ export interface StacksFungibleTokenAsset { hasMemo: boolean; imageCanonicalUri: string; name: string; - price: Money | null; + price: MarketData | null; symbol: string; }