Skip to content

Commit

Permalink
refactor: price as market data
Browse files Browse the repository at this point in the history
  • Loading branch information
fbwoolf committed Apr 20, 2024
1 parent d59662f commit a15ff27
Show file tree
Hide file tree
Showing 44 changed files with 388 additions and 417 deletions.
39 changes: 39 additions & 0 deletions src/app/common/asset-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { MarketData } from '@shared/models/market.model';
import type { Money } from '@shared/models/money.model';

import { baseCurrencyAmountInQuote } from './money/calculate-money';
import { i18nFormatCurrency } from './money/format-money';
import { isMoneyGreaterThanZero } from './money/money.utils';

export function sortAssetsByName<T extends { name: string }[]>(assets: T) {
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;
});
}

export function migratePositiveAssetBalancesToTop<T extends { balance: Money }[]>(assets: T) {
const assetsWithPositiveBalance = assets.filter(asset => asset.balance.amount.isGreaterThan(0));
const assetsWithZeroBalance = assets.filter(asset => asset.balance.amount.isEqualTo(0));
return [...assetsWithPositiveBalance, ...assetsWithZeroBalance] as T;
}

export function convertAssetBalanceToFiat<
T extends { balance: Money | null; marketData: MarketData | null },
>(asset: T) {
if (!asset.marketData || !asset.balance || !isMoneyGreaterThanZero(asset.marketData.price))
return '';
return i18nFormatCurrency(baseCurrencyAmountInQuote(asset.balance, asset.marketData));
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { StacksFungibleTokenAsset } from '@shared/models/crypto-asset.model';
import { createMoney } from '@shared/models/money.model';

import {
isFtNameLikeStx,
Expand Down Expand Up @@ -32,7 +31,7 @@ describe(isTransferableStacksFungibleTokenAsset.name, () => {
canTransfer: true,
hasMemo: true,
imageCanonicalUri: '',
price: createMoney(0, 'USD'),
marketData: null,
symbol: 'CAT',
};
expect(isTransferableStacksFungibleTokenAsset(asset)).toBeTruthy();
Expand All @@ -49,7 +48,7 @@ describe(isTransferableStacksFungibleTokenAsset.name, () => {
canTransfer: true,
hasMemo: true,
imageCanonicalUri: '',
price: createMoney(0, 'USD'),
marketData: null,
symbol: 'CAT',
};
expect(isTransferableStacksFungibleTokenAsset(asset)).toBeTruthy();
Expand Down
11 changes: 0 additions & 11 deletions src/app/common/hooks/use-brc20-tokens.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/app/common/money/calculate-money.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
18 changes: 0 additions & 18 deletions src/app/common/money/fiat-conversion.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import BigNumber from 'bignumber.js';

import { Money } from '@shared/models/money.model';
import { isObject } from '@shared/utils';

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());
}
23 changes: 0 additions & 23 deletions src/app/common/utils/sort-assets-by-symbol.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { styled } from 'leather-styles/jsx';

import { createMoney } from '@shared/models/money.model';

import { convertAssetBalanceToFiat } from '@app/common/asset-utils';
import { formatBalance } from '@app/common/format-balance';
import {
checkIsMoneyAmountGreaterThanZero,
convertCryptoCurrencyMoneyToFiat,
} from '@app/common/money/fiat-conversion';
import { i18nFormatCurrency } from '@app/common/money/format-money';
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 @@ -19,16 +13,9 @@ interface Brc20TokenAssetItemLayoutProps {
onClick?(): void;
}
export function Brc20TokenAssetItemLayout({ onClick, token }: Brc20TokenAssetItemLayoutProps) {
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 balanceAsFiat = showFiatBalance
? i18nFormatCurrency(
convertCryptoCurrencyMoneyToFiat(token.ticker, priceAsMoney, balanceAsMoney)
)
: '';
const balanceAsString = token.balance?.amount.toString();
const formattedBalance = formatBalance(balanceAsString ?? '0');
const balanceAsFiat = convertAssetBalanceToFiat(token);

return (
<Pressable onClick={onClick} my="space.02">
Expand All @@ -39,7 +26,7 @@ export function Brc20TokenAssetItemLayout({ onClick, token }: Brc20TokenAssetIte
titleRight={
<BasicTooltip
asChild
label={formattedBalance.isAbbreviated ? balanceAsString : undefined}
label={formattedBalance?.isAbbreviated ? balanceAsString : undefined}
side="left"
>
<styled.span data-testid={token.ticker} textStyle="label.02">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ export function Brc20TokenAssetList({ brc20Tokens, variant }: Brc20TokenAssetLis
variant === 'send' && btcCryptoCurrencyAssetBalance.balance.amount.isGreaterThan(0);

function navigateToBrc20SendForm(token: Brc20Token) {
const { ticker, available_balance, decimals, holderAddress } = token;
const { ticker, balance, holderAddress, marketData } = token;
navigate(RouteUrls.SendBrc20SendForm.replace(':ticker', ticker), {
state: { balance: available_balance, ticker, decimals, holderAddress },
state: { balance, ticker, holderAddress, marketData },
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ interface Src20TokenAssetListProps {
src20Tokens: Src20Token[];
}
export function Src20TokenAssetList({ src20Tokens }: Src20TokenAssetListProps) {
return src20Tokens.map(token => <Src20TokenAssetItemLayout key={token.id} token={token} />);
return src20Tokens.map((token, i) => (
<Src20TokenAssetItemLayout key={`${token.id}${i}`} token={token} />
));
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@ import { CryptoAssetSelectors } from '@tests/selectors/crypto-asset.selectors';

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

import { convertAssetBalanceToFiat } from '@app/common/asset-utils';
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 { i18nFormatCurrency } from '@app/common/money/format-money';
import { ftDecimals } from '@app/common/stacks-utils';
import { formatContractId, getTicker } from '@app/common/utils';
import { spamFilter } from '@app/common/utils/spam-filter';
Expand All @@ -33,19 +29,10 @@ export function parseStacksFungibleTokenAssetBalance(
const imageCanonicalUri = getImageCanonicalUri(asset.imageCanonicalUri, asset.name);
const caption = symbol || getTicker(friendlyName);
const title = spamFilter(friendlyName);

const showFiatBalance =
assetBalance.asset.price && checkIsMoneyAmountGreaterThanZero(assetBalance.asset.price);
const balanceAsFiat = showFiatBalance
? assetBalance.asset.price &&
i18nFormatCurrency(
convertCryptoCurrencyMoneyToFiat(
assetBalance.balance.symbol,
assetBalance.asset.price,
assetBalance.balance
)
)
: '';
const balanceAsFiat = convertAssetBalanceToFiat({
...assetBalance.asset,
balance: assetBalance.balance,
});

return {
amount,
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/loaders/brc20-tokens-loader.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useBrc20Tokens } from '@app/common/hooks/use-brc20-tokens';
import { Brc20Token } from '@app/query/bitcoin/bitcoin-client';
import { useBrc20Tokens } from '@app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks';

interface Brc20TokensLoaderProps {
children(brc20Tokens: Brc20Token[]): React.ReactNode;
Expand Down
18 changes: 7 additions & 11 deletions src/app/pages/receive/components/receive-tokens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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 (
<Stack className={css(receiveTabStyle)}>
<ReceiveItem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ import { i18nFormatCurrency } from '@app/common/money/format-money';
interface SendFiatInputProps {
marketData: MarketData;
assetSymbol?: string;
assetDecimals?: number;
}

export function SendFiatValue({ marketData, assetSymbol = '' }: SendFiatInputProps) {
export function SendFiatValue({ marketData, assetSymbol = '', assetDecimals }: SendFiatInputProps) {
const [field] = useField('amount');
const [assetValue, setAssetValue] = useState<Money>(createMoneyFromDecimal(0, assetSymbol));
const [assetValue, setAssetValue] = useState<Money>(
createMoneyFromDecimal(0, assetSymbol, assetDecimals)
);

useEffect(() => {
let amount = Number(field.value);
Expand All @@ -26,9 +29,9 @@ export function SendFiatValue({ marketData, assetSymbol = '' }: SendFiatInputPro
amount = 0;
}

const assetAmount = createMoneyFromDecimal(amount, assetSymbol);
const assetAmount = createMoneyFromDecimal(amount, assetSymbol, assetDecimals);
setAssetValue(assetAmount);
}, [field.value, assetSymbol]);
}, [field.value, assetSymbol, assetDecimals]);

return (
<styled.span textStyle="body.02" color="ink.text-subdued">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { BitcoinChooseFee } from '@app/features/bitcoin-choose-fee/bitcoin-choos
import { useValidateBitcoinSpend } from '@app/features/bitcoin-choose-fee/hooks/use-validate-bitcoin-spend';
import { useToast } from '@app/features/toasts/use-toast';
import { UtxoResponseItem } from '@app/query/bitcoin/bitcoin-client';
import { useBrc20Transfers } from '@app/query/bitcoin/ordinals/brc20/use-brc-20';
import { useBrc20Transfers } from '@app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks';
import { useSignBitcoinTx } from '@app/store/accounts/blockchain/bitcoin/bitcoin.hooks';

import { useSendBitcoinAssetContextState } from '../../family/bitcoin/components/send-bitcoin-asset-container';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
InfoCardSeparator,
} from '@app/components/info-card/info-card';
import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
import { useBrc20Transfers } from '@app/query/bitcoin/ordinals/brc20/use-brc-20';
import { useBrc20Transfers } from '@app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks';
import { useBitcoinBroadcastTransaction } from '@app/query/bitcoin/transaction/use-bitcoin-broadcast-transaction';
import { Button } from '@app/ui/components/button/button';
import { Footer } from '@app/ui/components/containers/footers/footer';
Expand Down
Loading

0 comments on commit a15ff27

Please sign in to comment.