Skip to content

Commit

Permalink
feat: brc-20 token balances as fiat, #4408
Browse files Browse the repository at this point in the history
  • Loading branch information
fbwoolf committed Apr 8, 2024
1 parent 1cd2625 commit abbe247
Show file tree
Hide file tree
Showing 25 changed files with 102 additions and 96 deletions.
4 changes: 2 additions & 2 deletions src/app/common/hooks/balance/btc/use-btc-balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { baseCurrencyAmountInQuote } from '@app/common/money/calculate-money';
import { i18nFormatCurrency } from '@app/common/money/format-money';
import { createBitcoinCryptoCurrencyAssetTypeWrapper } from '@app/query/bitcoin/address/address.utils';
import { useNativeSegwitBalance } from '@app/query/bitcoin/balance/btc-native-segwit-balance.hooks';
import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks';
import { useCryptoCurrencyMarketDataMean } from '@app/query/common/market-data/market-data.hooks';

export function useBtcAssetBalance(btcAddress: string) {
const btcMarketData = useCryptoCurrencyMarketData('BTC');
const btcMarketData = useCryptoCurrencyMarketDataMean('BTC');
const {
btcBalance: btcAssetBalance,
isLoading,
Expand Down
4 changes: 2 additions & 2 deletions src/app/common/hooks/balance/stx/use-stx-balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { isDefined } from '@shared/utils';

import { baseCurrencyAmountInQuote, subtractMoney } from '@app/common/money/calculate-money';
import { i18nFormatCurrency } from '@app/common/money/format-money';
import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks';
import { useCryptoCurrencyMarketDataMean } from '@app/query/common/market-data/market-data.hooks';
import { createStacksCryptoCurrencyAssetTypeWrapper } from '@app/query/stacks/balance/stacks-ft-balances.utils';
import { useCurrentStacksAccountBalances } from '@app/query/stacks/balance/stx-balance.hooks';
import { useCurrentAccountMempoolTransactionsBalance } from '@app/query/stacks/mempool/mempool.hooks';
Expand All @@ -15,7 +15,7 @@ export function useStxBalance() {
const totalBalance = stxBalanceQuery.data?.stx.balance;
const unlockedStxBalance = stxBalanceQuery.data?.stx.unlockedStx;

const stxMarketData = useCryptoCurrencyMarketData('STX');
const stxMarketData = useCryptoCurrencyMarketDataMean('STX');
const pendingTxsBalance = useCurrentAccountMempoolTransactionsBalance();

const stxEffectiveBalance = isDefined(totalBalance)
Expand Down
6 changes: 3 additions & 3 deletions src/app/common/hooks/balance/use-total-balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { createMoney } from '@shared/models/money.model';

import { baseCurrencyAmountInQuote } from '@app/common/money/calculate-money';
import { i18nFormatCurrency } from '@app/common/money/format-money';
import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks';
import { useCryptoCurrencyMarketDataMean } from '@app/query/common/market-data/market-data.hooks';
import { useStacksAccountBalances } from '@app/query/stacks/balance/stx-balance.hooks';

import { useBtcAssetBalance } from './btc/use-btc-balance';
Expand All @@ -16,8 +16,8 @@ interface UseTotalBalanceArgs {

export function useTotalBalance({ btcAddress, stxAddress }: UseTotalBalanceArgs) {
// get market data
const btcMarketData = useCryptoCurrencyMarketData('BTC');
const stxMarketData = useCryptoCurrencyMarketData('STX');
const btcMarketData = useCryptoCurrencyMarketDataMean('BTC');
const stxMarketData = useCryptoCurrencyMarketDataMean('STX');

// get stx balance
const { data: balances, isLoading, isInitialLoading } = useStacksAccountBalances(stxAddress);
Expand Down
38 changes: 0 additions & 38 deletions src/app/common/hooks/use-alex-sdk.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/app/common/hooks/use-bitcoin-contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { makeRpcErrorResponse, makeRpcSuccessResponse } from '@shared/rpc/rpc-me
import { sendAcceptedBitcoinContractOfferToProtocolWallet } from '@app/query/bitcoin/contract/send-accepted-bitcoin-contract-offer';
import {
useCalculateBitcoinFiatValue,
useCryptoCurrencyMarketData,
useCryptoCurrencyMarketDataMean,
} from '@app/query/common/market-data/market-data.hooks';
import { useCurrentAccountIndex } from '@app/store/accounts/account';
import {
Expand Down Expand Up @@ -57,7 +57,7 @@ export interface BitcoinContractOfferDetails {
export function useBitcoinContracts() {
const navigate = useNavigate();
const defaultParams = useDefaultRequestParams();
const bitcoinMarketData = useCryptoCurrencyMarketData('BTC');
const bitcoinMarketData = useCryptoCurrencyMarketDataMean('BTC');
const calculateFiatValue = useCalculateBitcoinFiatValue();

const bitcoinAccountDetails = useCurrentAccountNativeSegwitIndexZeroSigner();
Expand Down
51 changes: 43 additions & 8 deletions src/app/common/hooks/use-convert-to-fiat-amount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,64 @@ import { useCallback, useMemo } from 'react';

import { CryptoCurrencies } from '@shared/models/currencies.model';
import { createMarketData, createMarketPair } from '@shared/models/market.model';
import type { Money } from '@shared/models/money.model';
import { type Money, createMoney } from '@shared/models/money.model';
import { isUndefined } from '@shared/utils';

import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks';
import { i18nFormatCurrency } from '@app/common/money/format-money';
import { unitToFractionalUnit } from '@app/common/money/unit-conversion';
import { useCryptoCurrencyMarketDataMean } from '@app/query/common/market-data/market-data.hooks';

import { baseCurrencyAmountInQuote } from '../money/calculate-money';

export function useConvertCryptoCurrencyToFiatAmount(currency: CryptoCurrencies) {
const cryptoCurrencyMarketData = useCryptoCurrencyMarketData(currency);
export function useConvertCryptoCurrencyToFiatAmountMean(currency: CryptoCurrencies) {
const cryptoCurrencyMarketData = useCryptoCurrencyMarketDataMean(currency);

return useCallback(
(value: Money) => baseCurrencyAmountInQuote(value, cryptoCurrencyMarketData),
[cryptoCurrencyMarketData]
);
}

export function useConvertAlexSdkCurrencyToFiatAmount(currency: CryptoCurrencies, price: Money) {
const alexCurrencyMarketData = useMemo(
function useConvertCryptoCurrencyToFiatAmount(currency: CryptoCurrencies, price: Money) {
const cryptoCurrencyMarketData = useMemo(
() => createMarketData(createMarketPair(currency, 'USD'), price),
[currency, price]
);

return useCallback(
(value: Money) => baseCurrencyAmountInQuote(value, alexCurrencyMarketData),
[alexCurrencyMarketData]
(value: Money) => baseCurrencyAmountInQuote(value, cryptoCurrencyMarketData),
[cryptoCurrencyMarketData]
);
}

export function useFormattedFractionalUnitAsFiat(balance?: Money, price?: Money, value?: string) {
const convertAlexSdkCurrencyToUsd = useConvertCryptoCurrencyToFiatAmount(
balance?.symbol ?? '',
price ?? createMoney(0, 'USD')
);

if (isUndefined(balance) || isUndefined(price) || isUndefined(value)) return;

const convertedAmountAsMoney = convertAlexSdkCurrencyToUsd(
createMoney(unitToFractionalUnit(balance.decimals)(value), balance.symbol, balance.decimals)
);

if (convertedAmountAsMoney.amount.isNaN()) return;
return i18nFormatCurrency(convertedAmountAsMoney);
}

export function useFormattedBaseUnitAsFiat(balance: Money, price?: Money | null) {
const convertAlexSdkCurrencyToUsd = useConvertCryptoCurrencyToFiatAmount(
balance.symbol,
price ?? createMoney(0, 'USD')
);

if (isUndefined(balance) || isUndefined(price)) return;

const convertedBalanceAsMoney = convertAlexSdkCurrencyToUsd(
createMoney(balance.amount, balance.symbol, balance.decimals)
);

if (convertedBalanceAsMoney.amount.isNaN() || convertedBalanceAsMoney.amount.isEqualTo(0)) return;
return i18nFormatCurrency(convertedBalanceAsMoney);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from '@app/common/transactions/bitcoin/coinselect/local-coin-selection';
import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useCurrentNativeSegwitAddressBalance } from '@app/query/bitcoin/balance/btc-native-segwit-balance.hooks';
import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks';
import { useCryptoCurrencyMarketDataMean } from '@app/query/common/market-data/market-data.hooks';

export const MAX_FEE_RATE_MULTIPLIER = 50;

Expand All @@ -22,7 +22,7 @@ interface UseBitcoinCustomFeeArgs {
export function useBitcoinCustomFee({ amount, isSendingMax, recipient }: UseBitcoinCustomFeeArgs) {
const { balance } = useCurrentNativeSegwitAddressBalance();
const { data: utxos = [] } = useCurrentNativeSegwitUtxos();
const btcMarketData = useCryptoCurrencyMarketData('BTC');
const btcMarketData = useCryptoCurrencyMarketDataMean('BTC');

return useCallback(
(feeRate: number) => {
Expand Down
4 changes: 2 additions & 2 deletions src/app/components/bitcoin-fees-list/use-bitcoin-fees-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import { useCurrentNativeSegwitAddressBalance } from '@app/query/bitcoin/balance/btc-native-segwit-balance.hooks';
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 { useCryptoCurrencyMarketDataMean } from '@app/query/common/market-data/market-data.hooks';

import { FeesListItem } from './bitcoin-fees-list';

Expand Down Expand Up @@ -44,7 +44,7 @@ export function useBitcoinFeesList({
utxos,
}: UseBitcoinFeesListArgs) {
const { balance } = useCurrentNativeSegwitAddressBalance();
const btcMarketData = useCryptoCurrencyMarketData('BTC');
const btcMarketData = useCryptoCurrencyMarketDataMean('BTC');
const { data: feeRates, isLoading } = useAverageBitcoinFeeRates();

const feesList: FeesListItem[] = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { styled } from 'leather-styles/jsx';
import { createMoney } from '@shared/models/money.model';

import { formatBalance } from '@app/common/format-balance';
import { useFormattedBaseUnitAsFiat } from '@app/common/hooks/use-convert-to-fiat-amount';
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';
Expand All @@ -14,8 +15,14 @@ interface Brc20TokenAssetItemLayoutProps {
onClick?(): void;
}
export function Brc20TokenAssetItemLayout({ onClick, token }: Brc20TokenAssetItemLayoutProps) {
const balance = createMoney(Number(token.overall_balance), token.ticker, 0).amount.toString();
const formattedBalance = formatBalance(balance);
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 balaceAsFiat = useFormattedBaseUnitAsFiat(
balanceAsMoney,
priceAsMoney ?? createMoney(0, 'USD')
);

return (
<Pressable onClick={onClick} my="space.02">
Expand All @@ -26,14 +33,15 @@ export function Brc20TokenAssetItemLayout({ onClick, token }: Brc20TokenAssetIte
titleRight={
<BasicTooltip
asChild
label={formattedBalance.isAbbreviated ? balance : undefined}
label={formattedBalance.isAbbreviated ? balanceAsString : undefined}
side="left"
>
<styled.span data-testid={token.ticker} textStyle="label.02">
{formattedBalance.value}
</styled.span>
</BasicTooltip>
}
captionRight={balaceAsFiat}
/>
</Pressable>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { styled } from 'leather-styles/jsx';

import { StacksFungibleTokenAssetBalance } from '@shared/models/crypto-asset-balance.model';

import { useAlexSdkBalanceAsFiat } from '@app/common/hooks/use-alex-sdk';
import { useFormattedBaseUnitAsFiat } from '@app/common/hooks/use-convert-to-fiat-amount';
import { StacksAssetAvatar } from '@app/components/crypto-assets/stacks/components/stacks-asset-avatar';
import { ItemLayout } from '@app/ui/components/item-layout/item-layout';
import { BasicTooltip } from '@app/ui/components/tooltip/basic-tooltip';
Expand All @@ -18,7 +18,7 @@ export function StacksFungibleTokenAssetItemLayout({
assetBalance,
onClick,
}: StacksFungibleTokenAssetItemLayoutProps) {
const balanceAsFiat = useAlexSdkBalanceAsFiat(assetBalance.balance, assetBalance.asset.price);
const balanceAsFiat = useFormattedBaseUnitAsFiat(assetBalance.balance, assetBalance.asset.price);
const { amount, avatar, caption, dataTestId, formattedBalance, imageCanonicalUri, title } =
parseStacksFungibleTokenAssetBalance(assetBalance);

Expand Down
4 changes: 2 additions & 2 deletions src/app/components/fees-row/fees-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { FeeTypes, Fees } from '@shared/models/fees/fees.model';
import { createMoney } from '@shared/models/money.model';
import { isNumber, isString } from '@shared/utils';

import { useConvertCryptoCurrencyToFiatAmount } from '@app/common/hooks/use-convert-to-fiat-amount';
import { useConvertCryptoCurrencyToFiatAmountMean } from '@app/common/hooks/use-convert-to-fiat-amount';
import { convertAmountToBaseUnit } from '@app/common/money/calculate-money';
import { LoadingRectangle } from '@app/components/loading-rectangle';

Expand Down Expand Up @@ -45,7 +45,7 @@ export function FeesRow({
const hasFeeEstimates = fees?.estimates.length;
const feeCurrencySymbol = feeCurrencyField.value;

const convertCryptoCurrencyToUsd = useConvertCryptoCurrencyToFiatAmount(feeCurrencySymbol);
const convertCryptoCurrencyToUsd = useConvertCryptoCurrencyToFiatAmountMean(feeCurrencySymbol);

const feeInUsd = useMemo(() => {
if ((!isNumber(feeField.value) && !isString(feeField.value)) || !feeCurrencySymbol) return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ import {
import { formatMoney, i18nFormatCurrency } from '@app/common/money/format-money';
import { getEstimatedConfirmationTime } from '@app/common/transactions/stacks/transaction.utils';
import { removeTrailingNullCharacters } from '@app/common/utils';
import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks';
import { useCryptoCurrencyMarketDataMean } from '@app/query/common/market-data/market-data.hooks';
import { useStacksBlockTime } from '@app/query/stacks/info/info.hooks';
import { useCurrentNetworkState } from '@app/store/networks/networks.hooks';
import { microStxToStx } from '@app/ui/utils/micro-stx-to-stx';

export function useStacksTransactionSummary(token: CryptoCurrencies) {
const tokenMarketData = useCryptoCurrencyMarketData(token);
const tokenMarketData = useCryptoCurrencyMarketDataMean(token);
const { isTestnet } = useCurrentNetworkState();
const { data: blockTime } = useStacksBlockTime();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useBitcoinExplorerLink } from '@app/common/hooks/use-bitcoin-explorer-l
import { baseCurrencyAmountInQuote } from '@app/common/money/calculate-money';
import { i18nFormatCurrency } from '@app/common/money/format-money';
import { satToBtc } from '@app/common/money/unit-conversion';
import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks';
import { useCryptoCurrencyMarketDataMean } from '@app/query/common/market-data/market-data.hooks';
import { Flag } from '@app/ui/components/flag/flag';
import { Caption } from '@app/ui/components/typography/caption';
import { BitcoinContractIcon } from '@app/ui/icons/bitcoin-contract-icon';
Expand All @@ -26,7 +26,7 @@ export function BitcoinContractListItemLayout({
txid,
}: BitcoinContractListItemLayoutProps) {
const { handleOpenBitcoinTxLink: handleOpenTxLink } = useBitcoinExplorerLink();
const bitcoinMarketData = useCryptoCurrencyMarketData('BTC');
const bitcoinMarketData = useCryptoCurrencyMarketDataMean('BTC');

const getFiatValue = useCallback(
(value: string) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { satToBtc } from '@app/common/money/unit-conversion';
import { InfoCardFooter } from '@app/components/info-card/info-card';
import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useBitcoinBroadcastTransaction } from '@app/query/bitcoin/transaction/use-bitcoin-broadcast-transaction';
import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/market-data.hooks';
import { useCryptoCurrencyMarketDataMean } from '@app/query/common/market-data/market-data.hooks';
import { useCurrentAccountNativeSegwitAddressIndexZero } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { Button } from '@app/ui/components/button/button';
import { truncateMiddle } from '@app/ui/utils/truncate-middle';
Expand Down Expand Up @@ -45,7 +45,7 @@ export function RpcSendTransferConfirmation() {
const bitcoinAddress = useCurrentAccountNativeSegwitAddressIndexZero();
const { broadcastTx, isBroadcasting } = useBitcoinBroadcastTransaction();
const { refetch } = useCurrentNativeSegwitUtxos();
const btcMarketData = useCryptoCurrencyMarketData('BTC');
const btcMarketData = useCryptoCurrencyMarketDataMean('BTC');

const psbt = decodeBitcoinTx(tx);
const transferAmount = satToBtc(psbt.outputs[0].amount.toString()).toString();
Expand Down
4 changes: 2 additions & 2 deletions src/app/pages/rpc-sign-psbt/use-rpc-sign-psbt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by
import { useBitcoinBroadcastTransaction } from '@app/query/bitcoin/transaction/use-bitcoin-broadcast-transaction';
import {
useCalculateBitcoinFiatValue,
useCryptoCurrencyMarketData,
useCryptoCurrencyMarketDataMean,
} from '@app/query/common/market-data/market-data.hooks';
import { useGetAssumedZeroIndexSigningConfig } from '@app/store/accounts/blockchain/bitcoin/bitcoin.hooks';

Expand All @@ -36,7 +36,7 @@ export function useRpcSignPsbt() {
const { signPsbt, getPsbtAsTransaction } = usePsbtSigner();
const { broadcastTx, isBroadcasting } = useBitcoinBroadcastTransaction();
const { refetch } = useCurrentNativeSegwitUtxos();
const btcMarketData = useCryptoCurrencyMarketData('BTC');
const btcMarketData = useCryptoCurrencyMarketDataMean('BTC');
const calculateBitcoinFiatValue = useCalculateBitcoinFiatValue();
const getDefaultSigningConfig = useGetAssumedZeroIndexSigningConfig();

Expand Down
Loading

0 comments on commit abbe247

Please sign in to comment.