diff --git a/src/app/components/balance/btc-balance.tsx b/src/app/components/balance/btc-balance.tsx
index a35c5af4ec3..09c5cc75be1 100644
--- a/src/app/components/balance/btc-balance.tsx
+++ b/src/app/components/balance/btc-balance.tsx
@@ -9,7 +9,7 @@ export function BtcBalance() {
{signer => (
- {asset => {formatMoney(asset.balance.availableBalance)}}
+ {token => {formatMoney(token.balance.availableBalance)}}
)}
diff --git a/src/app/components/crypto-asset-item/crypto-asset-item.layout.tsx b/src/app/components/crypto-asset-item/crypto-asset-item.layout.tsx
index efe8e0bd245..aa78c4df860 100644
--- a/src/app/components/crypto-asset-item/crypto-asset-item.layout.tsx
+++ b/src/app/components/crypto-asset-item/crypto-asset-item.layout.tsx
@@ -1,9 +1,9 @@
import { ReactNode } from 'react';
+import type { CryptoAssetBalance } from '@leather-wallet/models';
import { Box, Flex, styled } from 'leather-styles/jsx';
import { spamFilter } from '@app/common/utils/spam-filter';
-import type { AccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
import { BulletSeparator } from '@app/ui/components/bullet-separator/bullet-separator';
import { ItemLayout } from '@app/ui/components/item-layout/item-layout';
import { SkeletonLoader } from '@app/ui/components/skeleton-loader/skeleton-loader';
@@ -16,29 +16,33 @@ import { parseCryptoAssetBalance } from './crypto-asset-item.layout.utils';
interface CryptoAssetItemLayoutProps {
additionalBalanceInfo?: ReactNode;
additionalBalanceInfoAsFiat?: ReactNode;
- asset: AccountCryptoAssetWithDetails;
+ balance: CryptoAssetBalance;
caption?: string;
+ contractId?: string;
fiatBalance?: string;
icon: React.ReactNode;
isLoading?: boolean;
name: string;
- onClick?(asset: AccountCryptoAssetWithDetails): void;
+ onClick?(symbol: string, contractId?: string): void;
rightElement?: React.ReactNode;
+ symbol: string;
}
export function CryptoAssetItemLayout({
additionalBalanceInfo,
additionalBalanceInfoAsFiat,
- asset,
+ balance,
caption,
+ contractId,
fiatBalance,
icon,
isLoading = false,
name,
onClick,
rightElement,
+ symbol,
}: CryptoAssetItemLayoutProps) {
- const { dataTestId, formattedBalance } = parseCryptoAssetBalance(asset.balance);
- const { availableBalance } = asset.balance;
+ const { dataTestId, formattedBalance } = parseCryptoAssetBalance(balance);
+ const { availableBalance } = balance;
const title = spamFilter(name);
const titleRight = (
@@ -88,7 +92,7 @@ export function CryptoAssetItemLayout({
if (isInteractive)
return (
- onClick(asset)} my="space.02">
+ onClick(symbol, contractId)} my="space.02">
{content}
);
diff --git a/src/app/components/loaders/brc20-tokens-loader.tsx b/src/app/components/loaders/brc20-tokens-loader.tsx
index b7f152d2e61..df59ccce764 100644
--- a/src/app/components/loaders/brc20-tokens-loader.tsx
+++ b/src/app/components/loaders/brc20-tokens-loader.tsx
@@ -1,10 +1,18 @@
-import { useBrc20AccountCryptoAssetsWithDetails } from '@app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks';
-import type { Brc20AccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
+import type { Brc20CryptoAssetInfo, CryptoAssetBalance, MarketData } from '@leather-wallet/models';
+
+import { useBrc20Tokens } from '@app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks';
interface Brc20TokensLoaderProps {
- children(tokens: Brc20AccountCryptoAssetWithDetails[]): React.ReactNode;
+ children(
+ tokens: {
+ assetInfo: Brc20CryptoAssetInfo;
+ balance: CryptoAssetBalance;
+ holderAddress: string;
+ marketData: MarketData;
+ }[]
+ ): React.ReactNode;
}
export function Brc20TokensLoader({ children }: Brc20TokensLoaderProps) {
- const tokens = useBrc20AccountCryptoAssetsWithDetails();
+ const tokens = useBrc20Tokens();
return children(tokens);
}
diff --git a/src/app/components/loaders/btc-crypto-asset-loader.tsx b/src/app/components/loaders/btc-crypto-asset-loader.tsx
index 3ed06ddb8bf..37536b7f795 100644
--- a/src/app/components/loaders/btc-crypto-asset-loader.tsx
+++ b/src/app/components/loaders/btc-crypto-asset-loader.tsx
@@ -1,11 +1,30 @@
-import { useBtcAccountCryptoAssetWithDetails } from '@app/query/bitcoin/btc/btc-crypto-asset.hooks';
-import type { BtcAccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
+import type { BtcCryptoAssetInfo, CryptoAssetBalance, MarketData } from '@leather-wallet/models';
+
+import { BTC_DECIMALS } from '@shared/constants';
+
+import { useGetBitcoinBalanceByAddress } from '@app/query/bitcoin/balance/btc-balance.hooks';
+import { useCryptoCurrencyMarketDataMeanAverage } from '@app/query/common/market-data/market-data.hooks';
+import { createCryptoAssetBalance } from '@app/query/common/models';
+
+const btcCryptoAssetInfo: BtcCryptoAssetInfo = {
+ decimals: BTC_DECIMALS,
+ hasMemo: false,
+ name: 'bitcoin',
+ symbol: 'BTC',
+};
interface BtcCryptoAssetLoaderProps {
address: string;
- children(asset: BtcAccountCryptoAssetWithDetails, isInitialLoading: boolean): React.ReactNode;
+ children(
+ token: { assetInfo: BtcCryptoAssetInfo; balance: CryptoAssetBalance; marketData: MarketData },
+ isInitialLoading: boolean
+ ): React.ReactNode;
}
export function BtcCryptoAssetLoader({ address, children }: BtcCryptoAssetLoaderProps) {
- const { asset, isInitialLoading } = useBtcAccountCryptoAssetWithDetails(address);
- return children(asset, isInitialLoading);
+ const marketData = useCryptoCurrencyMarketDataMeanAverage('BTC');
+ const { balance, isInitialLoading } = useGetBitcoinBalanceByAddress(address);
+ return children(
+ { assetInfo: btcCryptoAssetInfo, balance: createCryptoAssetBalance(balance), marketData },
+ isInitialLoading
+ );
}
diff --git a/src/app/components/loaders/sip10-tokens-loader.tsx b/src/app/components/loaders/sip10-tokens-loader.tsx
new file mode 100644
index 00000000000..ea1baa87035
--- /dev/null
+++ b/src/app/components/loaders/sip10-tokens-loader.tsx
@@ -0,0 +1,20 @@
+import type { CryptoAssetBalance, MarketData, Sip10CryptoAssetInfo } from '@leather-wallet/models';
+
+import { useFilteredSip10Tokens } from '@app/query/stacks/sip10/sip10-tokens.hooks';
+import type { Sip10CryptoAssetFilter } from '@app/query/stacks/sip10/sip10-tokens.utils';
+
+interface Sip10TokensLoaderProps {
+ address: string;
+ filter: Sip10CryptoAssetFilter;
+ children(
+ tokens: {
+ assetInfo: Sip10CryptoAssetInfo;
+ balance: CryptoAssetBalance;
+ marketData: MarketData;
+ }[]
+ ): React.ReactNode;
+}
+export function Sip10TokensLoader({ address, filter, children }: Sip10TokensLoaderProps) {
+ const tokens = useFilteredSip10Tokens({ address, filter });
+ return children(tokens);
+}
diff --git a/src/app/components/loaders/stx-crypto-asset-loader.tsx b/src/app/components/loaders/stx-crypto-asset-loader.tsx
index 72824eb4770..3692601755e 100644
--- a/src/app/components/loaders/stx-crypto-asset-loader.tsx
+++ b/src/app/components/loaders/stx-crypto-asset-loader.tsx
@@ -1,11 +1,35 @@
-import type { StxAccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
-import { useStxAccountCryptoAssetWithDetails } from '@app/query/stacks/stx/stx-crypto-asset.hooks';
+import type { MarketData, StxCryptoAssetBalance, StxCryptoAssetInfo } from '@leather-wallet/models';
+
+import { STX_DECIMALS } from '@shared/constants';
+
+import { useCryptoCurrencyMarketDataMeanAverage } from '@app/query/common/market-data/market-data.hooks';
+import { isFetchedWithSuccess } from '@app/query/query-config';
+import { useStxCryptoAssetBalance } from '@app/query/stacks/balance/account-balance.hooks';
+
+const stxCryptoAssetInfo: StxCryptoAssetInfo = {
+ decimals: STX_DECIMALS,
+ hasMemo: true,
+ name: 'stacks',
+ symbol: 'STX',
+};
interface StxCryptoAssetLoaderProps {
address: string;
- children(asset: StxAccountCryptoAssetWithDetails, isInitialLoading: boolean): React.ReactNode;
+ children(
+ token: {
+ assetInfo: StxCryptoAssetInfo;
+ balance: StxCryptoAssetBalance;
+ marketData: MarketData;
+ },
+ isInitialLoading: boolean
+ ): React.ReactNode;
}
export function StxCryptoAssetLoader({ address, children }: StxCryptoAssetLoaderProps) {
- const { asset, isInitialLoading } = useStxAccountCryptoAssetWithDetails(address);
- return children(asset, isInitialLoading);
+ const marketData = useCryptoCurrencyMarketDataMeanAverage('STX');
+ const query = useStxCryptoAssetBalance(address);
+ if (!isFetchedWithSuccess(query)) return;
+ return children(
+ { assetInfo: stxCryptoAssetInfo, balance: query.data, marketData },
+ query.isInitialLoading
+ );
}
diff --git a/src/app/features/asset-list/asset-list.tsx b/src/app/features/asset-list/asset-list.tsx
index 570f48e8161..9d99313b6b9 100644
--- a/src/app/features/asset-list/asset-list.tsx
+++ b/src/app/features/asset-list/asset-list.tsx
@@ -1,3 +1,4 @@
+import type { CryptoAssetBalance, MarketData } from '@leather-wallet/models';
import { Stack } from 'leather-styles/jsx';
import { useWalletType } from '@app/common/use-wallet-type';
@@ -9,6 +10,7 @@ import {
import { Brc20TokensLoader } from '@app/components/loaders/brc20-tokens-loader';
import { BtcCryptoAssetLoader } from '@app/components/loaders/btc-crypto-asset-loader';
import { RunesLoader } from '@app/components/loaders/runes-loader';
+import { Sip10TokensLoader } from '@app/components/loaders/sip10-tokens-loader';
import { Src20TokensLoader } from '@app/components/loaders/src20-tokens-loader';
import { CurrentStacksAccountLoader } from '@app/components/loaders/stacks-account-loader';
import { Stx20TokensLoader } from '@app/components/loaders/stx20-tokens-loader';
@@ -19,7 +21,7 @@ import { Src20TokenAssetList } from '@app/features/asset-list/bitcoin/src20-toke
import { Stx20TokenAssetList } from '@app/features/asset-list/stacks/stx20-token-asset-list/stx20-token-asset-list';
import { StxCryptoAssetItem } from '@app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item';
import { StxCryptoAssetItemFallback } from '@app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item-fallback';
-import type { AccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
+import type { CryptoAssetInfo } from '@app/query/common/models';
import { useCurrentNetwork } from '@app/store/networks/networks.selectors';
import { BtcCryptoAssetItem } from './bitcoin/btc-crypto-asset-item/btc-crypto-asset-item';
@@ -28,9 +30,14 @@ import { Sip10TokenAssetList } from './stacks/sip10-token-asset-list/sip10-token
import { Sip10TokenAssetListUnsupported } from './stacks/sip10-token-asset-list/sip10-token-asset-list-unsupported';
export type AssetListVariant = 'interactive' | 'read-only';
+export interface AssetItem {
+ assetInfo: CryptoAssetInfo;
+ balance: CryptoAssetBalance;
+ marketData: MarketData;
+}
interface AssetListProps {
- onClick?(asset: AccountCryptoAssetWithDetails): void;
+ onClick?(symbol: string, contractId?: string): void;
variant?: AssetListVariant;
}
export function AssetList({ onClick, variant = 'read-only' }: AssetListProps) {
@@ -46,11 +53,11 @@ export function AssetList({ onClick, variant = 'read-only' }: AssetListProps) {
{nativeSegwitAccount => (
- {(asset, isInitialLoading) => (
+ {(token, isInitialLoading) => (
)}
@@ -64,11 +71,11 @@ export function AssetList({ onClick, variant = 'read-only' }: AssetListProps) {
>
{nativeSegwitAccount => (
- {(asset, isInitialLoading) => (
+ {(token, isInitialLoading) => (
)}
@@ -89,11 +96,16 @@ export function AssetList({ onClick, variant = 'read-only' }: AssetListProps) {
{account => (
<>
- {(asset, isInitialLoading) => (
-
+ {(token, isInitialLoading) => (
+
)}
-
+
+ {tokens => }
+
{isReadOnly && (
{tokens => }
@@ -109,7 +121,7 @@ export function AssetList({ onClick, variant = 'read-only' }: AssetListProps) {
{taprootAccount => (
<>
- {tokens => }
+ {tokens => }
{isReadOnly && (
<>
@@ -129,7 +141,11 @@ export function AssetList({ onClick, variant = 'read-only' }: AssetListProps) {
{isReadOnly && (
- {account => }
+ {account => (
+
+ {tokens => }
+
+ )}
)}
diff --git a/src/app/features/asset-list/bitcoin/brc20-token-asset-list/brc20-token-asset-list.tsx b/src/app/features/asset-list/bitcoin/brc20-token-asset-list/brc20-token-asset-list.tsx
index 875048d35af..83b46ae205a 100644
--- a/src/app/features/asset-list/bitcoin/brc20-token-asset-list/brc20-token-asset-list.tsx
+++ b/src/app/features/asset-list/bitcoin/brc20-token-asset-list/brc20-token-asset-list.tsx
@@ -7,39 +7,48 @@ import { RouteUrls } from '@shared/route-urls';
import { capitalize } from '@app/common/utils';
import { CryptoAssetItemLayout } from '@app/components/crypto-asset-item/crypto-asset-item.layout';
-import type { AssetListVariant } from '@app/features/asset-list/asset-list';
+import type { AssetItem, AssetListVariant } from '@app/features/asset-list/asset-list';
import { useCurrentBtcAvailableBalanceNativeSegwit } from '@app/query/bitcoin/balance/btc-balance-native-segwit.hooks';
-import type { Brc20AccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
import { Brc20AvatarIcon } from '@app/ui/components/avatar/brc20-avatar-icon';
+interface Brc20AssetItem extends AssetItem {
+ holderAddress: string;
+}
+
interface Brc20TokenAssetListProps {
- assets: Brc20AccountCryptoAssetWithDetails[];
+ tokens: Brc20AssetItem[];
variant?: AssetListVariant;
}
-export function Brc20TokenAssetList({ assets, variant }: Brc20TokenAssetListProps) {
+export function Brc20TokenAssetList({ tokens, variant }: Brc20TokenAssetListProps) {
const navigate = useNavigate();
const { balance, isInitialLoading } = useCurrentBtcAvailableBalanceNativeSegwit();
const hasPositiveBtcBalanceForFees = variant === 'interactive' && balance.amount.isGreaterThan(0);
- function navigateToBrc20SendForm(asset: Brc20AccountCryptoAssetWithDetails) {
- const { balance, holderAddress, info, marketData } = asset;
- navigate(RouteUrls.SendBrc20SendForm.replace(':ticker', info.symbol), {
- state: { balance: balance.availableBalance, holderAddress, marketData, ticker: info.symbol },
+ function navigateToBrc20SendForm(token: Brc20AssetItem) {
+ const { balance, holderAddress, assetInfo, marketData } = token;
+ navigate(RouteUrls.SendBrc20SendForm.replace(':ticker', assetInfo.symbol), {
+ state: {
+ balance: balance.availableBalance,
+ holderAddress,
+ marketData,
+ ticker: assetInfo.symbol,
+ },
});
}
return (
- {assets.map(asset => (
+ {tokens.map(token => (
}
isLoading={isInitialLoading}
- key={asset.info.symbol}
- name={asset.info.symbol}
- onClick={hasPositiveBtcBalanceForFees ? () => navigateToBrc20SendForm(asset) : undefined}
+ key={token.assetInfo.symbol}
+ name={token.assetInfo.name}
+ onClick={hasPositiveBtcBalanceForFees ? () => navigateToBrc20SendForm(token) : undefined}
+ symbol={token.assetInfo.symbol}
/>
))}
diff --git a/src/app/features/asset-list/bitcoin/btc-crypto-asset-item/btc-crypto-asset-item-fallback.tsx b/src/app/features/asset-list/bitcoin/btc-crypto-asset-item/btc-crypto-asset-item-fallback.tsx
index f7e7c71e797..ea7f59c5b87 100644
--- a/src/app/features/asset-list/bitcoin/btc-crypto-asset-item/btc-crypto-asset-item-fallback.tsx
+++ b/src/app/features/asset-list/bitcoin/btc-crypto-asset-item/btc-crypto-asset-item-fallback.tsx
@@ -1,5 +1,6 @@
+import { createMoney } from '@shared/models/money.model';
+
import { CryptoAssetItemLayout } from '@app/components/crypto-asset-item/crypto-asset-item.layout';
-import { btcCryptoAssetPlaceholder } from '@app/query/bitcoin/btc/btc-crypto-asset.hooks';
import { useCheckLedgerBlockchainAvailable } from '@app/store/accounts/blockchain/utils';
import { BtcAvatarIcon } from '@app/ui/components/avatar/btc-avatar-icon';
@@ -14,10 +15,11 @@ export function BtcCryptoAssetItemFallback({ variant }: StxCryptoAssetItemFallba
if (variant === 'interactive' && !checkBlockchainAvailable('bitcoin')) return null;
return (
}
- name={btcCryptoAssetPlaceholder.info.name}
- rightElement={}
+ name="bitcoin"
+ rightElement={}
+ symbol="BTC"
/>
);
}
diff --git a/src/app/features/asset-list/bitcoin/btc-crypto-asset-item/btc-crypto-asset-item.tsx b/src/app/features/asset-list/bitcoin/btc-crypto-asset-item/btc-crypto-asset-item.tsx
index 1128f53945e..df248fbbb26 100644
--- a/src/app/features/asset-list/bitcoin/btc-crypto-asset-item/btc-crypto-asset-item.tsx
+++ b/src/app/features/asset-list/bitcoin/btc-crypto-asset-item/btc-crypto-asset-item.tsx
@@ -2,39 +2,37 @@ import { baseCurrencyAmountInQuote } from '@app/common/money/calculate-money';
import { i18nFormatCurrency } from '@app/common/money/format-money';
import { capitalize } from '@app/common/utils';
import { CryptoAssetItemLayout } from '@app/components/crypto-asset-item/crypto-asset-item.layout';
-import { useCryptoCurrencyMarketDataMeanAverage } from '@app/query/common/market-data/market-data.hooks';
-import type {
- AccountCryptoAssetWithDetails,
- BtcAccountCryptoAssetWithDetails,
-} from '@app/query/models/crypto-asset.model';
import { BtcAvatarIcon } from '@app/ui/components/avatar/btc-avatar-icon';
+import type { AssetItem } from '../../asset-list';
+
interface BtcCryptoAssetItemProps {
- asset: BtcAccountCryptoAssetWithDetails;
+ token: AssetItem;
isLoading: boolean;
- onClick?(asset: AccountCryptoAssetWithDetails): void;
+ onClick?(symbol: string): void;
rightElement?: React.ReactNode;
}
export function BtcCryptoAssetItem({
- asset,
isLoading,
+ token,
onClick,
rightElement,
}: BtcCryptoAssetItemProps) {
- const marketData = useCryptoCurrencyMarketDataMeanAverage('BTC');
+ const { assetInfo, balance, marketData } = token;
const availableBalanceAsFiat = i18nFormatCurrency(
- baseCurrencyAmountInQuote(asset.balance.availableBalance, marketData)
+ baseCurrencyAmountInQuote(balance.availableBalance, marketData)
);
return (
}
isLoading={isLoading}
- name={capitalize(asset.info.name)}
+ name={capitalize(assetInfo.name)}
onClick={onClick}
rightElement={rightElement}
+ symbol={assetInfo.symbol}
/>
);
}
diff --git a/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-item.tsx b/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-item.tsx
index e7b421e56ac..710ab0f567d 100644
--- a/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-item.tsx
+++ b/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-item.tsx
@@ -1,36 +1,47 @@
+import type { CryptoAssetBalance, MarketData, Sip10CryptoAssetInfo } from '@leather-wallet/models';
+
+import { convertAssetBalanceToFiat } from '@app/common/asset-utils';
+import { getSafeImageCanonicalUri } from '@app/common/stacks-utils';
+import { spamFilter } from '@app/common/utils/spam-filter';
import { CryptoAssetItemLayout } from '@app/components/crypto-asset-item/crypto-asset-item.layout';
import { StacksAssetAvatar } from '@app/components/stacks-asset-avatar';
-import type {
- AccountCryptoAssetWithDetails,
- Sip10AccountCryptoAssetWithDetails,
-} from '@app/query/models/crypto-asset.model';
-
-import { parseSip10TokenCryptoAssetBalance } from './sip10-token-asset-item.utils';
interface Sip10TokenAssetItemProps {
- asset: Sip10AccountCryptoAssetWithDetails;
- onClick?(asset: AccountCryptoAssetWithDetails): void;
+ assetInfo: Sip10CryptoAssetInfo;
+ balance: CryptoAssetBalance;
+ marketData: MarketData;
+ onClick?(symbol: string, contractId?: string): void;
}
-export function Sip10TokenAssetItem({ asset, onClick }: Sip10TokenAssetItemProps) {
- const { avatar, fiatBalance, imageCanonicalUri, title } =
- parseSip10TokenCryptoAssetBalance(asset);
+export function Sip10TokenAssetItem({
+ assetInfo,
+ balance,
+ marketData,
+ onClick,
+}: Sip10TokenAssetItemProps) {
+ const name = spamFilter(assetInfo.name);
+ const fiatBalance = convertAssetBalanceToFiat({
+ balance: balance.availableBalance,
+ marketData,
+ });
return (
- {title[0]}
+ {name[0]}
}
- name={asset.info.name}
+ name={name}
onClick={onClick}
+ symbol={assetInfo.symbol}
/>
);
}
diff --git a/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-item.utils.ts b/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-item.utils.ts
deleted file mode 100644
index e1b09175109..00000000000
--- a/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-item.utils.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { CryptoAssetSelectors } from '@tests/selectors/crypto-asset.selectors';
-
-import { convertAssetBalanceToFiat } from '@app/common/asset-utils';
-import { formatBalance } from '@app/common/format-balance';
-import { ftDecimals, getSafeImageCanonicalUri } from '@app/common/stacks-utils';
-import { spamFilter } from '@app/common/utils/spam-filter';
-import type { Sip10AccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
-
-export function parseSip10TokenCryptoAssetBalance(asset: Sip10AccountCryptoAssetWithDetails) {
- const { balance, info } = asset;
- const { contractId, decimals, imageCanonicalUri, name, symbol } = info;
-
- const amount = ftDecimals(balance.availableBalance.amount, decimals);
- const avatar = contractId;
- const dataTestId =
- symbol && CryptoAssetSelectors.CryptoAssetListItem.replace('{symbol}', symbol.toLowerCase());
- const formattedBalance = formatBalance(amount);
- const safeImageCanonicalUri = getSafeImageCanonicalUri(imageCanonicalUri, name);
- const title = spamFilter(name);
- const fiatBalance = convertAssetBalanceToFiat({
- ...asset,
- balance: asset.balance.availableBalance,
- });
-
- return {
- amount,
- avatar,
- fiatBalance,
- dataTestId,
- formattedBalance,
- imageCanonicalUri: safeImageCanonicalUri,
- title,
- };
-}
diff --git a/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-list-unsupported.tsx b/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-list-unsupported.tsx
index 72b52332198..d8c25c5ebd2 100644
--- a/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-list-unsupported.tsx
+++ b/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-list-unsupported.tsx
@@ -2,25 +2,24 @@ import { useState } from 'react';
import { Stack, styled } from 'leather-styles/jsx';
-import { useFilteredSip10AccountCryptoAssetsWithDetails } from '@app/query/stacks/sip10/sip10-tokens.hooks';
import { Accordion } from '@app/ui/components/accordion/accordion';
import { Sip10TokenAssetItem } from './sip10-token-asset-item';
+import type { Sip10AssetItem } from './sip10-token-asset-list';
const accordionValue = 'accordion-unsupported-token-asset-list';
-export function Sip10TokenAssetListUnsupported({ address }: { address: string }) {
+interface Sip10TokenAssetListUnsupportedProps {
+ tokens: Sip10AssetItem[];
+}
+export function Sip10TokenAssetListUnsupported({ tokens }: Sip10TokenAssetListUnsupportedProps) {
const [isOpen, setIsOpen] = useState(false);
- const assets = useFilteredSip10AccountCryptoAssetsWithDetails({
- address,
- filter: 'unsupported',
- });
function onValueChange(value: string) {
setIsOpen(value === accordionValue);
}
- if (!assets.length) return null;
+ if (!tokens.length) return null;
return (
@@ -30,8 +29,13 @@ export function Sip10TokenAssetListUnsupported({ address }: { address: string })
- {assets.map(asset => (
-
+ {tokens.map(token => (
+
))}
diff --git a/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-list.tsx b/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-list.tsx
index 28e2b49c71e..34ebce50741 100644
--- a/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-list.tsx
+++ b/src/app/features/asset-list/stacks/sip10-token-asset-list/sip10-token-asset-list.tsx
@@ -1,28 +1,30 @@
+import type { Sip10CryptoAssetInfo } from '@leather-wallet/models';
import { Stack } from 'leather-styles/jsx';
-import { isDefined } from '@shared/utils';
-
-import type { AccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
-import { useFilteredSip10AccountCryptoAssetsWithDetails } from '@app/query/stacks/sip10/sip10-tokens.hooks';
-
+import type { AssetItem } from '../../asset-list';
import { Sip10TokenAssetItem } from './sip10-token-asset-item';
-interface Sip10TokenAssetListProps {
- address: string;
- onClick?(asset: AccountCryptoAssetWithDetails): void;
+export interface Sip10AssetItem extends AssetItem {
+ assetInfo: Sip10CryptoAssetInfo;
}
-export function Sip10TokenAssetList({ address, onClick }: Sip10TokenAssetListProps) {
- const assets = useFilteredSip10AccountCryptoAssetsWithDetails({
- address,
- filter: isDefined(onClick) ? 'all' : 'supported',
- });
- if (!assets.length) return null;
+interface Sip10TokenAssetListProps {
+ tokens: Sip10AssetItem[];
+ onClick?(symbol: string, contractId?: string): void;
+}
+export function Sip10TokenAssetList({ tokens, onClick }: Sip10TokenAssetListProps) {
+ if (!tokens.length) return null;
return (
- {assets.map(asset => (
-
+ {tokens.map(token => (
+
))}
);
diff --git a/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item-fallback.tsx b/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item-fallback.tsx
index 1eb4c256dcd..e3113593253 100644
--- a/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item-fallback.tsx
+++ b/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item-fallback.tsx
@@ -1,5 +1,6 @@
+import { createMoney } from '@shared/models/money.model';
+
import { CryptoAssetItemLayout } from '@app/components/crypto-asset-item/crypto-asset-item.layout';
-import { stxCryptoAssetPlaceholder } from '@app/query/stacks/stx/stx-crypto-asset.hooks';
import { useCheckLedgerBlockchainAvailable } from '@app/store/accounts/blockchain/utils';
import { StxAvatarIcon } from '@app/ui/components/avatar/stx-avatar-icon';
@@ -14,10 +15,11 @@ export function StxCryptoAssetItemFallback({ variant }: StxCryptoAssetItemFallba
if (variant === 'interactive' && !checkBlockchainAvailable('stacks')) return null;
return (
}
- name={stxCryptoAssetPlaceholder.info.name}
- rightElement={}
+ name="stacks"
+ rightElement={}
+ symbol="STX"
/>
);
}
diff --git a/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item.stories.tsx b/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item.stories.tsx
index 7fe04fcfecb..312ef059e7d 100644
--- a/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item.stories.tsx
+++ b/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item.stories.tsx
@@ -42,8 +42,8 @@ const stxCryptoAssetBalance = {
export const StxCryptoAssetItem: Story = {
args: {
- asset: {
- info: {
+ token: {
+ assetInfo: {
decimals: 6,
hasMemo: true,
name: 'stacks',
@@ -53,17 +53,18 @@ export const StxCryptoAssetItem: Story = {
...stxCryptoAssetBalance,
lockedBalance: { amount: new BigNumber(0), decimals: 6, symbol },
},
- chain: 'stacks',
- marketData: null,
- type: 'stx',
+ marketData: {
+ pair: { base: 'STX', quote: 'USD' },
+ price: { amount: new BigNumber(0), decimals: 6, symbol },
+ },
},
},
};
export const StxCryptoAssetItemWithLockedBalance: Story = {
args: {
- asset: {
- info: {
+ token: {
+ assetInfo: {
decimals: 6,
hasMemo: true,
name: 'stacks',
@@ -73,9 +74,10 @@ export const StxCryptoAssetItemWithLockedBalance: Story = {
...stxCryptoAssetBalance,
lockedBalance: { amount: new BigNumber(1000000000), decimals: 6, symbol },
},
- chain: 'stacks',
- marketData: null,
- type: 'stx',
+ marketData: {
+ pair: { base: 'STX', quote: 'USD' },
+ price: { amount: new BigNumber(0), decimals: 6, symbol },
+ },
},
},
};
diff --git a/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item.tsx b/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item.tsx
index 55092bab5f1..adaf2c5d88e 100644
--- a/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item.tsx
+++ b/src/app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item.tsx
@@ -1,3 +1,4 @@
+import type { StxCryptoAssetBalance } from '@leather-wallet/models';
import { styled } from 'leather-styles/jsx';
import { baseCurrencyAmountInQuote } from '@app/common/money/calculate-money';
@@ -5,24 +6,24 @@ import { i18nFormatCurrency } from '@app/common/money/format-money';
import { ftDecimals } from '@app/common/stacks-utils';
import { capitalize } from '@app/common/utils';
import { CryptoAssetItemLayout } from '@app/components/crypto-asset-item/crypto-asset-item.layout';
-import { useCryptoCurrencyMarketDataMeanAverage } from '@app/query/common/market-data/market-data.hooks';
-import type {
- AccountCryptoAssetWithDetails,
- StxAccountCryptoAssetWithDetails,
-} from '@app/query/models/crypto-asset.model';
import { StxAvatarIcon } from '@app/ui/components/avatar/stx-avatar-icon';
import { BulletOperator } from '@app/ui/components/bullet-separator/bullet-separator';
import { Caption } from '@app/ui/components/typography/caption';
+import type { AssetItem } from '../../asset-list';
+
+interface StxAssetItem extends AssetItem {
+ balance: StxCryptoAssetBalance;
+}
+
interface StxCryptoAssetItemProps {
- asset: StxAccountCryptoAssetWithDetails;
+ token: StxAssetItem;
isLoading: boolean;
- onClick?(asset: AccountCryptoAssetWithDetails): void;
+ onClick?(symbol: string): void;
}
-export function StxCryptoAssetItem({ asset, isLoading, onClick }: StxCryptoAssetItemProps) {
- const marketData = useCryptoCurrencyMarketDataMeanAverage('STX');
-
- const { availableBalance, lockedBalance } = asset.balance;
+export function StxCryptoAssetItem({ token, isLoading, onClick }: StxCryptoAssetItemProps) {
+ const { assetInfo, balance, marketData } = token;
+ const { availableBalance, lockedBalance } = balance;
const showAdditionalInfo = lockedBalance.amount.isGreaterThan(0);
const lockedBalanceAsFiat = i18nFormatCurrency(
@@ -43,12 +44,13 @@ export function StxCryptoAssetItem({ asset, isLoading, onClick }: StxCryptoAsset
}
isLoading={isLoading}
- name={capitalize(asset.info.name)}
+ name={capitalize(assetInfo.name)}
onClick={onClick}
+ symbol={assetInfo.symbol}
/>
);
}
diff --git a/src/app/pages/fund/choose-asset-to-fund/choose-asset-to-fund.tsx b/src/app/pages/fund/choose-asset-to-fund/choose-asset-to-fund.tsx
index 58eb7a9cb2b..d3a2da54c0d 100644
--- a/src/app/pages/fund/choose-asset-to-fund/choose-asset-to-fund.tsx
+++ b/src/app/pages/fund/choose-asset-to-fund/choose-asset-to-fund.tsx
@@ -12,7 +12,6 @@ import { BtcCryptoAssetLoader } from '@app/components/loaders/btc-crypto-asset-l
import { CurrentStacksAccountLoader } from '@app/components/loaders/stacks-account-loader';
import { StxCryptoAssetLoader } from '@app/components/loaders/stx-crypto-asset-loader';
import { StxCryptoAssetItem } from '@app/features/asset-list/stacks/stx-crypo-asset-item/stx-crypto-asset-item';
-import type { AccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
import { BtcAvatarIcon } from '@app/ui/components/avatar/btc-avatar-icon';
import { Card } from '@app/ui/layout/card/card';
import { Page } from '@app/ui/layout/page/page.layout';
@@ -21,8 +20,7 @@ export function ChooseCryptoAssetToFund() {
const navigate = useNavigate();
const navigateToFund = useCallback(
- (asset: AccountCryptoAssetWithDetails) =>
- navigate(RouteUrls.Fund.replace(':currency', asset.info.symbol)),
+ (symbol: string) => navigate(RouteUrls.Fund.replace(':currency', symbol)),
[navigate]
);
@@ -40,13 +38,14 @@ export function ChooseCryptoAssetToFund() {
{signer => (
- {(asset, isLoading) => (
+ {(token, isLoading) => (
}
isLoading={isLoading}
- name={capitalize(asset.info.name)}
- onClick={() => navigateToFund(asset)}
+ name={capitalize(token.assetInfo.name)}
+ onClick={() => navigateToFund(token.assetInfo.symbol)}
+ symbol={token.assetInfo.symbol}
/>
)}
@@ -56,11 +55,11 @@ export function ChooseCryptoAssetToFund() {
{account => (
- {(asset, isInitialLoading) => (
+ {(token, isInitialLoading) => (
navigateToFund(asset)}
+ onClick={() => navigateToFund(token.assetInfo.symbol)}
/>
)}
diff --git a/src/app/pages/home/components/send-button.tsx b/src/app/pages/home/components/send-button.tsx
index 33da083cc91..ee6b1050afa 100644
--- a/src/app/pages/home/components/send-button.tsx
+++ b/src/app/pages/home/components/send-button.tsx
@@ -10,7 +10,7 @@ import { whenPageMode } from '@app/common/utils';
import { openIndexPageInNewTab } from '@app/common/utils/open-in-new-tab';
import { useBtcCryptoAssetBalanceNativeSegwit } from '@app/query/bitcoin/balance/btc-balance-native-segwit.hooks';
import { useStxCryptoAssetBalance } from '@app/query/stacks/balance/account-balance.hooks';
-import { useTransferableSip10CryptoAssetsWithDetails } from '@app/query/stacks/sip10/sip10-tokens.hooks';
+import { useTransferableSip10Tokens } from '@app/query/stacks/sip10/sip10-tokens.hooks';
import { useCurrentAccountNativeSegwitIndexZeroSignerNullable } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { useCurrentStacksAccountAddress } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';
import { IconButton } from '@app/ui/components/icon-button/icon-button';
@@ -23,7 +23,7 @@ function SendButtonSuspense() {
const btcAddress = useCurrentAccountNativeSegwitIndexZeroSignerNullable()?.address;
const { btcCryptoAssetBalance } = useBtcCryptoAssetBalanceNativeSegwit(btcAddress ?? '');
const { data: stxCryptoAssetBalance } = useStxCryptoAssetBalance(address);
- const stacksFtAssets = useTransferableSip10CryptoAssetsWithDetails(address);
+ const stacksFtAssets = useTransferableSip10Tokens(address);
const isDisabled =
!btcCryptoAssetBalance && !stxCryptoAssetBalance && stacksFtAssets?.length === 0;
diff --git a/src/app/pages/send/choose-crypto-asset/choose-crypto-asset.tsx b/src/app/pages/send/choose-crypto-asset/choose-crypto-asset.tsx
index 2cb7f107d19..009b08993f0 100644
--- a/src/app/pages/send/choose-crypto-asset/choose-crypto-asset.tsx
+++ b/src/app/pages/send/choose-crypto-asset/choose-crypto-asset.tsx
@@ -5,35 +5,19 @@ import { Box, styled } from 'leather-styles/jsx';
import { RouteUrls } from '@shared/route-urls';
import { AssetList } from '@app/features/asset-list/asset-list';
-import { useToast } from '@app/features/toasts/use-toast';
import { useConfigBitcoinSendEnabled } from '@app/query/common/remote-config/remote-config.query';
-import type { AccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
-import { getSip10InfoFromAsset } from '@app/query/stacks/sip10/sip10-tokens.hooks';
import { Card } from '@app/ui/layout/card/card';
-import { getAssetStringParts } from '@app/ui/utils/get-asset-string-parts';
export function ChooseCryptoAsset() {
const navigate = useNavigate();
const isBitcoinSendEnabled = useConfigBitcoinSendEnabled();
- const toast = useToast();
- function navigateToSendForm(asset: AccountCryptoAssetWithDetails) {
- switch (asset.type) {
- case 'btc':
- if (!isBitcoinSendEnabled) return navigate(RouteUrls.SendBtcDisabled);
- return navigate(`${RouteUrls.SendCryptoAsset}/${asset.info.symbol.toLowerCase()}`);
- case 'sip-10':
- const info = getSip10InfoFromAsset(asset);
- if (info) {
- const { assetName } = getAssetStringParts(info.contractId);
- const symbol = !info.symbol ? assetName : info.symbol.toLowerCase();
- return navigate(`${RouteUrls.SendCryptoAsset}/${symbol}/${info.contractId}`);
- }
- toast.error('No contract id');
- return navigate('..');
- default:
- return navigate(`${RouteUrls.SendCryptoAsset}/${asset.info.symbol.toLowerCase()}`);
+ function navigateToSendForm(symbol: string, contractId?: string) {
+ if (!isBitcoinSendEnabled) return navigate(RouteUrls.SendBtcDisabled);
+ if (contractId) {
+ return navigate(`${RouteUrls.SendCryptoAsset}/${symbol}/${contractId}`);
}
+ return navigate(`${RouteUrls.SendCryptoAsset}/${symbol.toLowerCase()}`);
}
return (
diff --git a/src/app/pages/send/send-crypto-asset-form/form/btc/btc-send-form-container.tsx b/src/app/pages/send/send-crypto-asset-form/form/btc/btc-send-form-container.tsx
new file mode 100644
index 00000000000..9d70cade2e4
--- /dev/null
+++ b/src/app/pages/send/send-crypto-asset-form/form/btc/btc-send-form-container.tsx
@@ -0,0 +1,140 @@
+import { Outlet } from 'react-router-dom';
+
+import type { BtcCryptoAssetInfo, CryptoAssetBalance, MarketData } from '@leather-wallet/models';
+import { SendCryptoAssetSelectors } from '@tests/selectors/send.selectors';
+import { Form, Formik } from 'formik';
+import { Box } from 'leather-styles/jsx';
+
+import { HIGH_FEE_WARNING_LEARN_MORE_URL_BTC } from '@shared/constants';
+
+import { formatMoney } from '@app/common/money/format-money';
+import { HighFeeDialog } from '@app/features/dialogs/high-fee-dialog/high-fee-dialog';
+import { BtcAvatarIcon } from '@app/ui/components/avatar/btc-avatar-icon';
+import { Button } from '@app/ui/components/button/button';
+import { Callout } from '@app/ui/components/callout/callout';
+import { AvailableBalance } from '@app/ui/components/containers/footers/available-balance';
+import { Footer } from '@app/ui/components/containers/footers/footer';
+import { Link } from '@app/ui/components/link/link';
+import { Card } from '@app/ui/layout/card/card';
+import { CardContent } from '@app/ui/layout/card/card-content';
+
+import { AmountField } from '../../components/amount-field';
+import { SelectedAssetField } from '../../components/selected-asset-field';
+import { SendFiatValue } from '../../components/send-fiat-value';
+import { TransferRecipientField } from '../../family/bitcoin/components/bitcoin-recipient-field';
+import { BitcoinSendMaxButton } from '../../family/bitcoin/components/bitcoin-send-max-button';
+import { useSendFormRouteState } from '../../hooks/use-send-form-route-state';
+import { createDefaultInitialFormValues, defaultSendFormFormikProps } from '../../send-form.utils';
+import { useBtcSendForm } from './use-btc-send-form';
+
+interface BtcSendFormContainerProps {
+ assetInfo: BtcCryptoAssetInfo;
+ balance: CryptoAssetBalance;
+ marketData: MarketData;
+}
+export function BtcSendFormContainer({
+ assetInfo,
+ balance,
+ marketData,
+}: BtcSendFormContainerProps) {
+ const routeState = useSendFormRouteState();
+ const symbol = assetInfo.symbol;
+
+ const {
+ calcMaxSpend,
+ chooseTransactionFee,
+ currentNetwork,
+ formRef,
+ isSendingMax,
+ onFormStateChange,
+ onSetIsSendingMax,
+ utxos,
+ validationSchema,
+ } = useBtcSendForm();
+
+ return (
+
+
+ {props => {
+ onFormStateChange(props.values);
+ const sendMaxCalculation = calcMaxSpend(props.values.recipient, utxos);
+
+ return (
+
+ );
+ }}
+
+
+ );
+}
diff --git a/src/app/pages/send/send-crypto-asset-form/form/btc/btc-send-form.tsx b/src/app/pages/send/send-crypto-asset-form/form/btc/btc-send-form.tsx
index 57eec8dabd2..9298ba2dc84 100644
--- a/src/app/pages/send/send-crypto-asset-form/form/btc/btc-send-form.tsx
+++ b/src/app/pages/send/send-crypto-asset-form/form/btc/btc-send-form.tsx
@@ -1,136 +1,22 @@
-import { Outlet } from 'react-router-dom';
+import { BitcoinNativeSegwitAccountLoader } from '@app/components/loaders/bitcoin-account-loader';
+import { BtcCryptoAssetLoader } from '@app/components/loaders/btc-crypto-asset-loader';
-import { SendCryptoAssetSelectors } from '@tests/selectors/send.selectors';
-import { Form, Formik } from 'formik';
-import { Box } from 'leather-styles/jsx';
-
-import { HIGH_FEE_WARNING_LEARN_MORE_URL_BTC } from '@shared/constants';
-import { CryptoCurrencies } from '@shared/models/currencies.model';
-
-import { formatMoney } from '@app/common/money/format-money';
-import { HighFeeDialog } from '@app/features/dialogs/high-fee-dialog/high-fee-dialog';
-import { useBtcAccountCryptoAssetWithDetails } from '@app/query/bitcoin/btc/btc-crypto-asset.hooks';
-import { useCryptoCurrencyMarketDataMeanAverage } from '@app/query/common/market-data/market-data.hooks';
-import { useCurrentAccountNativeSegwitIndexZeroSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
-import { BtcAvatarIcon } from '@app/ui/components/avatar/btc-avatar-icon';
-import { Button } from '@app/ui/components/button/button';
-import { Callout } from '@app/ui/components/callout/callout';
-import { AvailableBalance } from '@app/ui/components/containers/footers/available-balance';
-import { Footer } from '@app/ui/components/containers/footers/footer';
-import { Link } from '@app/ui/components/link/link';
-import { Card } from '@app/ui/layout/card/card';
-import { CardContent } from '@app/ui/layout/card/card-content';
-
-import { AmountField } from '../../components/amount-field';
-import { SelectedAssetField } from '../../components/selected-asset-field';
-import { SendFiatValue } from '../../components/send-fiat-value';
-import { TransferRecipientField } from '../../family/bitcoin/components/bitcoin-recipient-field';
-import { BitcoinSendMaxButton } from '../../family/bitcoin/components/bitcoin-send-max-button';
-import { useSendFormRouteState } from '../../hooks/use-send-form-route-state';
-import { createDefaultInitialFormValues, defaultSendFormFormikProps } from '../../send-form.utils';
-import { useBtcSendForm } from './use-btc-send-form';
-
-const symbol: CryptoCurrencies = 'BTC';
+import { BtcSendFormContainer } from './btc-send-form-container';
export function BtcSendForm() {
- const routeState = useSendFormRouteState();
- const btcMarketData = useCryptoCurrencyMarketDataMeanAverage(symbol);
-
- const { address } = useCurrentAccountNativeSegwitIndexZeroSigner();
- const { asset } = useBtcAccountCryptoAssetWithDetails(address);
- const { balance, info } = asset;
-
- const {
- calcMaxSpend,
- chooseTransactionFee,
- currentNetwork,
- formRef,
- isSendingMax,
- onFormStateChange,
- onSetIsSendingMax,
- utxos,
- validationSchema,
- } = useBtcSendForm();
-
return (
-
-
- {props => {
- onFormStateChange(props.values);
- const sendMaxCalculation = calcMaxSpend(props.values.recipient, utxos);
-
- return (
-
- );
- }}
-
-
+
+ {signer => (
+
+ {token => (
+
+ )}
+
+ )}
+
);
}
diff --git a/src/app/pages/send/send-crypto-asset-form/form/sip10/sip10-token-send-form-container.tsx b/src/app/pages/send/send-crypto-asset-form/form/sip10/sip10-token-send-form-container.tsx
index fbee8ba9b37..d89feab19b0 100644
--- a/src/app/pages/send/send-crypto-asset-form/form/sip10/sip10-token-send-form-container.tsx
+++ b/src/app/pages/send/send-crypto-asset-form/form/sip10/sip10-token-send-form-container.tsx
@@ -1,5 +1,6 @@
+import type { CryptoAssetBalance, MarketData, Sip10CryptoAssetInfo } from '@leather-wallet/models';
+
import { StacksAssetAvatar } from '@app/components/stacks-asset-avatar';
-import type { Sip10AccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
import { StxAvatarIcon } from '@app/ui/components/avatar/stx-avatar-icon';
import { AmountField } from '../../components/amount-field';
@@ -10,9 +11,15 @@ import { StacksCommonSendForm } from '../stacks/stacks-common-send-form';
import { useSip10SendForm } from './use-sip10-send-form';
interface Sip10TokenSendFormContainerProps {
- asset: Sip10AccountCryptoAssetWithDetails;
+ assetInfo: Sip10CryptoAssetInfo;
+ balance: CryptoAssetBalance;
+ marketData: MarketData;
}
-export function Sip10TokenSendFormContainer({ asset }: Sip10TokenSendFormContainerProps) {
+export function Sip10TokenSendFormContainer({
+ assetInfo,
+ balance,
+ marketData,
+}: Sip10TokenSendFormContainerProps) {
const {
availableTokenBalance,
initialValues,
@@ -21,10 +28,9 @@ export function Sip10TokenSendFormContainer({ asset }: Sip10TokenSendFormContain
stacksFtFees: fees,
validationSchema,
avatar,
- marketData,
decimals,
symbol,
- } = useSip10SendForm({ asset });
+ } = useSip10SendForm({ assetInfo, balance });
const amountField = (
;
}
- return children({ asset });
+ return children(token);
}
export function Sip10TokenSendForm() {
return (
- {({ asset }) => }
+ {token => (
+
+ )}
);
}
diff --git a/src/app/pages/send/send-crypto-asset-form/form/sip10/use-sip10-send-form.tsx b/src/app/pages/send/send-crypto-asset-form/form/sip10/use-sip10-send-form.tsx
index 41c3b66c600..af77f8edd1d 100644
--- a/src/app/pages/send/send-crypto-asset-form/form/sip10/use-sip10-send-form.tsx
+++ b/src/app/pages/send/send-crypto-asset-form/form/sip10/use-sip10-send-form.tsx
@@ -1,5 +1,6 @@
import { useMemo } from 'react';
+import type { CryptoAssetBalance, Sip10CryptoAssetInfo } from '@leather-wallet/models';
import { FormikHelpers } from 'formik';
import * as yup from 'yup';
@@ -9,7 +10,6 @@ import { StacksSendFormValues } from '@shared/models/form.model';
import { convertAmountToBaseUnit } from '@app/common/money/calculate-money';
import { getSafeImageCanonicalUri } from '@app/common/stacks-utils';
import { stacksFungibleTokenAmountValidator } from '@app/common/validation/forms/amount-validators';
-import type { Sip10AccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
import { useCalculateStacksTxFees } from '@app/query/stacks/fees/fees.hooks';
import {
useFtTokenTransferUnsignedTx,
@@ -20,31 +20,32 @@ import { useSendFormNavigate } from '../../hooks/use-send-form-navigate';
import { useStacksCommonSendForm } from '../stacks/use-stacks-common-send-form';
interface UseSip10SendFormArgs {
- asset: Sip10AccountCryptoAssetWithDetails;
+ assetInfo: Sip10CryptoAssetInfo;
+ balance: CryptoAssetBalance;
}
-export function useSip10SendForm({ asset }: UseSip10SendFormArgs) {
- const generateTx = useGenerateFtTokenTransferUnsignedTx(asset.info);
+export function useSip10SendForm({ assetInfo, balance }: UseSip10SendFormArgs) {
+ const generateTx = useGenerateFtTokenTransferUnsignedTx(assetInfo);
const sendFormNavigate = useSendFormNavigate();
- const unsignedTx = useFtTokenTransferUnsignedTx(asset.info);
+ const unsignedTx = useFtTokenTransferUnsignedTx(assetInfo);
const { data: stacksFtFees } = useCalculateStacksTxFees(unsignedTx);
- const availableTokenBalance = asset.balance.availableBalance;
+ const availableTokenBalance = balance.availableBalance;
const sendMaxBalance = useMemo(
() => convertAmountToBaseUnit(availableTokenBalance),
[availableTokenBalance]
);
const { initialValues, checkFormValidation, recipient, memo, nonce } = useStacksCommonSendForm({
- symbol: asset.info.symbol,
+ symbol: assetInfo.symbol,
availableTokenBalance,
});
function createFtAvatar() {
return {
- avatar: asset.info.contractId,
- imageCanonicalUri: getSafeImageCanonicalUri(asset.info.imageCanonicalUri, asset.info.name),
+ avatar: assetInfo.contractId,
+ imageCanonicalUri: getSafeImageCanonicalUri(assetInfo.imageCanonicalUri, assetInfo.name),
};
}
@@ -53,9 +54,8 @@ export function useSip10SendForm({ asset }: UseSip10SendFormArgs) {
initialValues,
sendMaxBalance,
stacksFtFees,
- symbol: asset.info.symbol,
- decimals: asset.info.decimals,
- marketData: asset.marketData,
+ symbol: assetInfo.symbol,
+ decimals: assetInfo.decimals,
avatar: createFtAvatar(),
validationSchema: yup.object({
amount: stacksFungibleTokenAmountValidator(availableTokenBalance),
@@ -75,8 +75,8 @@ export function useSip10SendForm({ asset }: UseSip10SendFormArgs) {
if (!tx) return logger.error('Attempted to generate unsigned tx, but tx is undefined');
sendFormNavigate.toConfirmAndSignStacksSip10Transaction({
- decimals: asset.info.decimals,
- name: asset.info.name,
+ decimals: assetInfo.decimals,
+ name: assetInfo.name,
tx,
});
},
diff --git a/src/app/query/bitcoin/balance/btc-balance-native-segwit.hooks.ts b/src/app/query/bitcoin/balance/btc-balance-native-segwit.hooks.ts
index 84f43815ec3..ad5325c6c08 100644
--- a/src/app/query/bitcoin/balance/btc-balance-native-segwit.hooks.ts
+++ b/src/app/query/bitcoin/balance/btc-balance-native-segwit.hooks.ts
@@ -11,7 +11,7 @@ import { useGetBitcoinBalanceByAddress } from './btc-balance.hooks';
function createBtcCryptoAssetBalance(balance: Money): BtcCryptoAssetBalance {
return {
availableBalance: balance,
- // TODO: Asset refactor: can we determine these here or are they nec?
+ // TODO: Can we determine these here or are they nec?
protectedBalance: createMoney(0, 'BTC'),
uneconomicalBalance: createMoney(0, 'BTC'),
};
diff --git a/src/app/query/bitcoin/btc/btc-crypto-asset.hooks.ts b/src/app/query/bitcoin/btc/btc-crypto-asset.hooks.ts
deleted file mode 100644
index 52cc752989d..00000000000
--- a/src/app/query/bitcoin/btc/btc-crypto-asset.hooks.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import type { BtcCryptoAssetInfo } from '@leather-wallet/models';
-
-import { BTC_DECIMALS } from '@shared/constants';
-import { createMoney } from '@shared/models/money.model';
-
-import { useCryptoCurrencyMarketDataMeanAverage } from '@app/query/common/market-data/market-data.hooks';
-import { createAccountCryptoAssetWithDetailsFactory } from '@app/query/models/crypto-asset.model';
-
-import type { BtcAccountCryptoAssetWithDetails } from '../../models/crypto-asset.model';
-import { useBtcCryptoAssetBalanceNativeSegwit } from '../balance/btc-balance-native-segwit.hooks';
-
-const btcCryptoAssetInfo: BtcCryptoAssetInfo = {
- decimals: BTC_DECIMALS,
- hasMemo: false,
- name: 'bitcoin',
- symbol: 'BTC',
-};
-
-const btcCryptoAssetBalancePlaceholder = {
- availableBalance: createMoney(0, 'BTC'),
- protectedBalance: createMoney(0, 'BTC'),
- uneconomicalBalance: createMoney(0, 'BTC'),
-};
-
-export const btcCryptoAssetPlaceholder =
- createAccountCryptoAssetWithDetailsFactory({
- balance: btcCryptoAssetBalancePlaceholder,
- chain: 'bitcoin',
- info: btcCryptoAssetInfo,
- marketData: null,
- type: 'btc',
- });
-
-export function useBtcAccountCryptoAssetWithDetails(address: string) {
- const { btcCryptoAssetBalance, isInitialLoading } = useBtcCryptoAssetBalanceNativeSegwit(address);
- const marketData = useCryptoCurrencyMarketDataMeanAverage('BTC');
-
- return {
- asset: createAccountCryptoAssetWithDetailsFactory({
- balance: btcCryptoAssetBalance,
- chain: 'bitcoin',
- info: btcCryptoAssetInfo,
- marketData,
- type: 'btc',
- }),
- isInitialLoading,
- };
-}
diff --git a/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks.ts b/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks.ts
index d0dff8e26b9..e836ec9bcd8 100644
--- a/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks.ts
+++ b/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks.ts
@@ -1,3 +1,4 @@
+import type { Brc20CryptoAssetInfo } from '@leather-wallet/models';
import BigNumber from 'bignumber.js';
import { createMarketData, createMarketPair } from '@shared/models/market.model';
@@ -6,11 +7,9 @@ import { createMoney } from '@shared/models/money.model';
import { unitToFractionalUnit } from '@app/common/money/unit-conversion';
import { useGetBrc20TokensQuery } from '@app/query/bitcoin/ordinals/brc20/brc20-tokens.query';
import { useCalculateBitcoinFiatValue } from '@app/query/common/market-data/market-data.hooks';
+import { createCryptoAssetBalance } from '@app/query/common/models';
import { useConfigOrdinalsbot } from '@app/query/common/remote-config/remote-config.query';
-import {
- type Brc20AccountCryptoAssetWithDetails,
- createAccountCryptoAssetWithDetailsFactory,
-} from '@app/query/models/crypto-asset.model';
+import { isFetchedWithSuccess } from '@app/query/query-config';
import { useAppDispatch } from '@app/store';
import { useCurrentAccountIndex } from '@app/store/accounts/account';
import { useCurrentNetwork } from '@app/store/networks/networks.selectors';
@@ -88,44 +87,44 @@ export function useBrc20Transfers(holderAddress: string) {
};
}
-export function useBrc20AccountCryptoAssetsWithDetails() {
+function createBrc20CryptoAssetInfo(decimals: number, ticker: string): Brc20CryptoAssetInfo {
+ return {
+ decimals,
+ hasMemo: false,
+ name: 'brc-20',
+ symbol: ticker,
+ };
+}
+
+export function useBrc20Tokens() {
const calculateBitcoinFiatValue = useCalculateBitcoinFiatValue();
- const { data: allBrc20TokensResponse } = useGetBrc20TokensQuery();
+ const query = useGetBrc20TokensQuery();
+
+ if (!isFetchedWithSuccess(query)) return [];
- const tokens = allBrc20TokensResponse?.pages
+ const tokens = query.data.pages
.flatMap(page => page.brc20Tokens)
.filter(token => token.length > 0)
.flatMap(token => token);
- return (
- tokens?.map(token => {
- const priceAsFiat = calculateBitcoinFiatValue(
- createMoney(new BigNumber(token.balance.min_listed_unit_price ?? 0), 'BTC')
- );
- return createAccountCryptoAssetWithDetailsFactory({
- balance: {
- availableBalance: createMoney(
- unitToFractionalUnit(token.info.decimals)(new BigNumber(token.balance.overall_balance)),
- token.balance.ticker,
- token.info.decimals
- ),
- },
- chain: 'bitcoin',
- holderAddress: token.holderAddress,
- info: {
- decimals: token.info.decimals,
- hasMemo: false,
- name: 'brc-20',
- symbol: token.info.ticker,
- },
- marketData: token.balance.min_listed_unit_price
- ? createMarketData(
- createMarketPair(token.balance.ticker, 'USD'),
- createMoney(priceAsFiat.amount, 'USD')
- )
- : null,
- type: 'brc-20',
- });
- }) ?? []
- );
+ return tokens.map(token => {
+ const fiatPrice = calculateBitcoinFiatValue(
+ createMoney(new BigNumber(token.balance.min_listed_unit_price ?? 0), 'BTC')
+ );
+ return {
+ assetInfo: createBrc20CryptoAssetInfo(token.info.decimals, token.balance.ticker),
+ balance: createCryptoAssetBalance(
+ createMoney(
+ unitToFractionalUnit(token.info.decimals)(new BigNumber(token.balance.overall_balance)),
+ token.balance.ticker,
+ token.info.decimals
+ )
+ ),
+ holderAddress: token.holderAddress,
+ marketData: createMarketData(
+ createMarketPair(token.balance.ticker, 'USD'),
+ createMoney(fiatPrice.amount, 'USD')
+ ),
+ };
+ });
}
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 6d3b95fcb92..e798511448d 100644
--- a/src/app/query/common/alex-sdk/alex-sdk.hooks.ts
+++ b/src/app/query/common/alex-sdk/alex-sdk.hooks.ts
@@ -12,7 +12,7 @@ import { sortAssetsByName } from '@app/common/asset-utils';
import { convertAmountToFractionalUnit } from '@app/common/money/calculate-money';
import { pullContractIdFromIdentity } from '@app/common/utils';
import { useCurrentStxAvailableUnlockedBalance } from '@app/query/stacks/balance/account-balance.hooks';
-import { useTransferableSip10CryptoAssetsWithDetails } from '@app/query/stacks/sip10/sip10-tokens.hooks';
+import { useTransferableSip10Tokens } from '@app/query/stacks/sip10/sip10-tokens.hooks';
import { useCurrentStacksAccountAddress } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';
import { getAvatarFallback } from '@app/ui/components/avatar/avatar';
@@ -38,11 +38,12 @@ export function useAlexCurrencyPriceAsMarketData() {
const { data: prices } = useAlexSdkLatestPricesQuery();
return useCallback(
- (principal: string, symbol?: string) => {
+ (principal: string, symbol: string) => {
const tokenInfo = supportedCurrencies
.filter(isDefined)
.find(token => pullContractIdFromIdentity(token.contractAddress) === principal);
- if (!symbol || !prices || !tokenInfo) return null;
+ if (!prices || !tokenInfo)
+ return createMarketData(createMarketPair(symbol, 'USD'), createMoney(0, 'USD'));
const currency = tokenInfo.id as Currency;
const price = convertAmountToFractionalUnit(new BigNumber(prices[currency] ?? 0), 2);
return createMarketData(createMarketPair(symbol, 'USD'), createMoney(price, 'USD'));
@@ -56,7 +57,7 @@ function useCreateSwapAsset() {
const { data: prices } = useAlexSdkLatestPricesQuery();
const priceAsMarketData = useAlexCurrencyPriceAsMarketData();
const availableUnlockedBalance = useCurrentStxAvailableUnlockedBalance();
- const assets = useTransferableSip10CryptoAssetsWithDetails(address);
+ const sip10Tokens = useTransferableSip10Tokens(address);
return useCallback(
(tokenInfo?: TokenInfo): SwapAsset | undefined => {
@@ -68,8 +69,8 @@ function useCreateSwapAsset() {
const currency = tokenInfo.id as Currency;
const principal = pullContractIdFromIdentity(tokenInfo.contractAddress);
- const availableBalance = assets.find(a => a.info.contractId === principal)?.balance
- .availableBalance;
+ const availableBalance = sip10Tokens.find(token => token.assetInfo.contractId === principal)
+ ?.balance.availableBalance;
const swapAsset = {
currency,
@@ -96,7 +97,7 @@ function useCreateSwapAsset() {
: priceAsMarketData(principal, tokenInfo.name),
};
},
- [assets, availableUnlockedBalance, priceAsMarketData, prices]
+ [availableUnlockedBalance, priceAsMarketData, prices, sip10Tokens]
);
}
diff --git a/src/app/query/common/models.ts b/src/app/query/common/models.ts
new file mode 100644
index 00000000000..a27b269fdc3
--- /dev/null
+++ b/src/app/query/common/models.ts
@@ -0,0 +1,25 @@
+import type {
+ Brc20CryptoAssetInfo,
+ BtcCryptoAssetInfo,
+ CryptoAssetBalance,
+ Money,
+ RuneCryptoAssetInfo,
+ Sip10CryptoAssetInfo,
+ Src20CryptoAssetInfo,
+ Stx20CryptoAssetInfo,
+ StxCryptoAssetInfo,
+} from '@leather-wallet/models';
+
+// TODO: Move to the models pkg
+export type CryptoAssetInfo =
+ | BtcCryptoAssetInfo
+ | StxCryptoAssetInfo
+ | Brc20CryptoAssetInfo
+ | RuneCryptoAssetInfo
+ | Src20CryptoAssetInfo
+ | Sip10CryptoAssetInfo
+ | Stx20CryptoAssetInfo;
+
+export function createCryptoAssetBalance(balance: Money): CryptoAssetBalance {
+ return { availableBalance: balance };
+}
diff --git a/src/app/query/models/crypto-asset.model.ts b/src/app/query/models/crypto-asset.model.ts
deleted file mode 100644
index ac2ecaa1389..00000000000
--- a/src/app/query/models/crypto-asset.model.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import type {
- BaseCryptoAssetInfo,
- Blockchains,
- Brc20CryptoAssetInfo,
- BtcCryptoAssetBalance,
- BtcCryptoAssetInfo,
- CryptoAssetBalance,
- CryptoAssetType,
- MarketData,
- Sip10CryptoAssetInfo,
- StxCryptoAssetBalance,
- StxCryptoAssetInfo,
-} from '@leather-wallet/models';
-
-interface AccountCryptoAssetDetails {
- balance: CryptoAssetBalance;
- chain: Blockchains;
- info: BaseCryptoAssetInfo;
- marketData: MarketData | null;
- type: CryptoAssetType;
-}
-
-export function createAccountCryptoAssetWithDetailsFactory(
- args: T
-): T {
- const { balance, chain, info, marketData, type } = args;
- return {
- balance,
- chain,
- info,
- marketData,
- type,
- } as T;
-}
-
-export interface BtcAccountCryptoAssetWithDetails extends AccountCryptoAssetDetails {
- balance: BtcCryptoAssetBalance;
- info: BtcCryptoAssetInfo;
-}
-
-export interface StxAccountCryptoAssetWithDetails extends AccountCryptoAssetDetails {
- balance: StxCryptoAssetBalance;
- info: StxCryptoAssetInfo;
-}
-
-export interface Brc20AccountCryptoAssetWithDetails extends AccountCryptoAssetDetails {
- holderAddress: string;
- info: Brc20CryptoAssetInfo;
-}
-
-export interface Sip10AccountCryptoAssetWithDetails extends AccountCryptoAssetDetails {
- info: Sip10CryptoAssetInfo;
-}
-
-export type AccountCryptoAssetWithDetails =
- | BtcAccountCryptoAssetWithDetails
- | StxAccountCryptoAssetWithDetails
- | Brc20AccountCryptoAssetWithDetails
- | Sip10AccountCryptoAssetWithDetails;
diff --git a/src/app/query/query-config.ts b/src/app/query/query-config.ts
index a5ede1495ab..ec1998617d7 100644
--- a/src/app/query/query-config.ts
+++ b/src/app/query/query-config.ts
@@ -1,4 +1,8 @@
-import { UseQueryOptions } from '@tanstack/react-query';
+import {
+ type QueryObserverSuccessResult,
+ UseQueryOptions,
+ type UseQueryResult,
+} from '@tanstack/react-query';
type AllowedReactQueryConfigOptions = keyof Pick<
UseQueryOptions,
@@ -9,3 +13,9 @@ export type AppUseQueryConfig = Pick<
UseQueryOptions,
AllowedReactQueryConfigOptions
>;
+
+export function isFetchedWithSuccess(
+ query: UseQueryResult
+): query is QueryObserverSuccessResult {
+ return !query.isError && !query.isLoading && query.data !== undefined;
+}
diff --git a/src/app/query/stacks/sip10/sip10-tokens.hooks.ts b/src/app/query/stacks/sip10/sip10-tokens.hooks.ts
index d50030f12e1..69f56b1bdd9 100644
--- a/src/app/query/stacks/sip10/sip10-tokens.hooks.ts
+++ b/src/app/query/stacks/sip10/sip10-tokens.hooks.ts
@@ -12,31 +12,19 @@ import {
useAlexCurrencyPriceAsMarketData,
useAlexSwappableAssets,
} from '@app/query/common/alex-sdk/alex-sdk.hooks';
-import {
- type AccountCryptoAssetWithDetails,
- type Sip10AccountCryptoAssetWithDetails,
- createAccountCryptoAssetWithDetailsFactory,
-} from '@app/query/models/crypto-asset.model';
+import { createCryptoAssetBalance } from '@app/query/common/models';
import { useCurrentStacksAccountAddress } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';
import { getAssetStringParts } from '@app/ui/utils/get-asset-string-parts';
import { useStacksAccountBalanceFungibleTokens } from '../balance/account-balance.hooks';
import { useStacksAccountFungibleTokenMetadata } from '../token-metadata/fungible-tokens/fungible-token-metadata.hooks';
import { isFtAsset } from '../token-metadata/token-metadata.utils';
-import {
- type Sip10CryptoAssetFilter,
- filterSip10AccountCryptoAssetsWithDetails,
-} from './sip10-tokens.utils';
+import { type Sip10CryptoAssetFilter, filterSip10Tokens } from './sip10-tokens.utils';
export function isTransferableSip10Token(asset: Partial) {
return !isUndefined(asset.decimals) && !isUndefined(asset.name) && !isUndefined(asset.symbol);
}
-export function getSip10InfoFromAsset(asset: AccountCryptoAssetWithDetails) {
- if ('contractId' in asset.info) return asset.info;
- return;
-}
-
function createSip10CryptoAssetInfo(
contractId: string,
key: string,
@@ -57,7 +45,7 @@ function createSip10CryptoAssetInfo(
};
}
-function useSip10AccountCryptoAssetsWithDetails(address: string) {
+function useSip10Tokens(address: string) {
const { data: tokens = {} } = useStacksAccountBalanceFungibleTokens(address);
const tokenMetadata = useStacksAccountFungibleTokenMetadata(tokens);
const priceAsMarketData = useAlexCurrencyPriceAsMarketData();
@@ -69,20 +57,15 @@ function useSip10AccountCryptoAssetsWithDetails(address: string) {
const token = tokenMetadata[i].data;
if (!(token && isFtAsset(token))) return;
const contractId = pullContractIdFromIdentity(key);
+ const symbol = token.symbol ?? getTicker(token.name ?? '');
- return createAccountCryptoAssetWithDetailsFactory({
- balance: {
- availableBalance: createMoney(
- new BigNumber(value.balance),
- token.symbol ?? getTicker(token.name ?? ''),
- token.decimals ?? 0
- ),
- },
- chain: 'stacks',
- info: createSip10CryptoAssetInfo(contractId, key, token),
- marketData: priceAsMarketData(contractId, token.symbol),
- type: 'sip-10',
- });
+ return {
+ assetInfo: createSip10CryptoAssetInfo(contractId, key, token),
+ balance: createCryptoAssetBalance(
+ createMoney(new BigNumber(value.balance), symbol, token.decimals ?? 0)
+ ),
+ marketData: priceAsMarketData(contractId, symbol),
+ };
})
.filter(isDefined)
.filter(asset => asset.balance.availableBalance.amount.isGreaterThan(0)),
@@ -90,35 +73,27 @@ function useSip10AccountCryptoAssetsWithDetails(address: string) {
);
}
-export function useSip10CryptoAssetWithDetails(contractId: string) {
+export function useSip10Token(contractId: string) {
const address = useCurrentStacksAccountAddress();
- const assets = useSip10AccountCryptoAssetsWithDetails(address);
+ const tokens = useSip10Tokens(address);
return useMemo(
- () => assets.find(asset => asset.info.contractId === contractId),
- [assets, contractId]
+ () => tokens.find(token => token.assetInfo.contractId === contractId),
+ [contractId, tokens]
);
}
-interface UseFilteredSip10AccountCryptoAssetsWithDetailsArgs {
+interface UseFilteredSip10TokensArgs {
address: string;
filter?: Sip10CryptoAssetFilter;
}
-export function useFilteredSip10AccountCryptoAssetsWithDetails({
- address,
- filter = 'all',
-}: UseFilteredSip10AccountCryptoAssetsWithDetailsArgs) {
- const assets = useSip10AccountCryptoAssetsWithDetails(address);
+export function useFilteredSip10Tokens({ address, filter = 'all' }: UseFilteredSip10TokensArgs) {
+ const tokens = useSip10Tokens(address);
const { data: swapAssets = [] } = useAlexSwappableAssets();
- return useMemo(
- () => filterSip10AccountCryptoAssetsWithDetails(assets, swapAssets, filter),
- [assets, swapAssets, filter]
- );
+ return useMemo(() => filterSip10Tokens(swapAssets, tokens, filter), [swapAssets, tokens, filter]);
}
-export function useTransferableSip10CryptoAssetsWithDetails(
- address: string
-): Sip10AccountCryptoAssetWithDetails[] {
- const assets = useSip10AccountCryptoAssetsWithDetails(address);
- return useMemo(() => assets.filter(asset => asset.info.canTransfer), [assets]);
+export function useTransferableSip10Tokens(address: string) {
+ const tokens = useSip10Tokens(address);
+ return useMemo(() => tokens.filter(token => token.assetInfo.canTransfer), [tokens]);
}
diff --git a/src/app/query/stacks/sip10/sip10-tokens.utils.ts b/src/app/query/stacks/sip10/sip10-tokens.utils.ts
index 015f5154f60..48922b69606 100644
--- a/src/app/query/stacks/sip10/sip10-tokens.utils.ts
+++ b/src/app/query/stacks/sip10/sip10-tokens.utils.ts
@@ -1,22 +1,27 @@
+import type { CryptoAssetBalance, MarketData, Sip10CryptoAssetInfo } from '@leather-wallet/models';
+
import type { SwapAsset } from '@app/query/common/alex-sdk/alex-sdk.hooks';
-import type { Sip10AccountCryptoAssetWithDetails } from '@app/query/models/crypto-asset.model';
import { getAssetStringParts } from '@app/ui/utils/get-asset-string-parts';
export type Sip10CryptoAssetFilter = 'all' | 'supported' | 'unsupported';
-export function filterSip10AccountCryptoAssetsWithDetails(
- assets: Sip10AccountCryptoAssetWithDetails[],
+export function filterSip10Tokens(
swapAssets: SwapAsset[],
+ tokens: {
+ assetInfo: Sip10CryptoAssetInfo;
+ balance: CryptoAssetBalance;
+ marketData: MarketData;
+ }[],
filter: Sip10CryptoAssetFilter
) {
- return assets.filter(asset => {
- const { address: contractAddress } = getAssetStringParts(asset.info.contractId);
+ return tokens.filter(token => {
+ const { address: contractAddress } = getAssetStringParts(token.assetInfo.contractId);
if (filter === 'supported') {
return swapAssets.some(swapAsset => swapAsset.principal.includes(contractAddress));
}
if (filter === 'unsupported') {
return !swapAssets.some(swapAsset => swapAsset.principal.includes(contractAddress));
}
- return assets;
+ return tokens;
});
}
diff --git a/src/app/query/stacks/stx/stx-crypto-asset.hooks.ts b/src/app/query/stacks/stx/stx-crypto-asset.hooks.ts
deleted file mode 100644
index 6c89c853988..00000000000
--- a/src/app/query/stacks/stx/stx-crypto-asset.hooks.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import type { StxCryptoAssetInfo } from '@leather-wallet/models';
-
-import { STX_DECIMALS } from '@shared/constants';
-import { createMoney } from '@shared/models/money.model';
-import { isUndefined } from '@shared/utils';
-
-import { useCryptoCurrencyMarketDataMeanAverage } from '@app/query/common/market-data/market-data.hooks';
-import {
- type StxAccountCryptoAssetWithDetails,
- createAccountCryptoAssetWithDetailsFactory,
-} from '@app/query/models/crypto-asset.model';
-
-import { useStxCryptoAssetBalance } from '../balance/account-balance.hooks';
-
-const stxCryptoAssetInfo: StxCryptoAssetInfo = {
- decimals: STX_DECIMALS,
- hasMemo: true,
- name: 'stacks',
- symbol: 'STX',
-};
-
-const stxCryptoAssetBalancePlaceholder = {
- availableBalance: createMoney(0, 'STX'),
- availableUnlockedBalance: createMoney(0, 'STX'),
- inboundBalance: createMoney(0, 'STX'),
- lockedBalance: createMoney(0, 'STX'),
- outboundBalance: createMoney(0, 'STX'),
- pendingBalance: createMoney(0, 'STX'),
- totalBalance: createMoney(0, 'STX'),
- unlockedBalance: createMoney(0, 'STX'),
-};
-
-export const stxCryptoAssetPlaceholder =
- createAccountCryptoAssetWithDetailsFactory({
- balance: stxCryptoAssetBalancePlaceholder,
- chain: 'stacks',
- info: stxCryptoAssetInfo,
- marketData: null,
- type: 'stx',
- });
-
-export function useStxAccountCryptoAssetWithDetails(address: string) {
- const { data: balance, isInitialLoading } = useStxCryptoAssetBalance(address);
- const marketData = useCryptoCurrencyMarketDataMeanAverage('STX');
-
- if (isUndefined(balance)) return { asset: stxCryptoAssetPlaceholder, isInitialLoading };
-
- return {
- asset: createAccountCryptoAssetWithDetailsFactory({
- balance,
- chain: 'stacks',
- info: stxCryptoAssetInfo,
- marketData,
- type: 'stx',
- }),
- isInitialLoading,
- };
-}