Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: balance skeleton loader #5126

Merged
merged 1 commit into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 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 @@ -8,7 +8,11 @@ import { useCryptoCurrencyMarketData } from '@app/query/common/market-data/marke

export function useBtcAssetBalance(btcAddress: string) {
const btcMarketData = useCryptoCurrencyMarketData('BTC');
const btcAssetBalance = useNativeSegwitBalance(btcAddress);
const {
btcBalance: btcAssetBalance,
isLoading,
isInitialLoading,
} = useNativeSegwitBalance(btcAddress);

return useMemo(
() => ({
Expand All @@ -23,7 +27,9 @@ export function useBtcAssetBalance(btcAddress: string) {
btcAvailableUsdBalance: i18nFormatCurrency(
baseCurrencyAmountInQuote(btcAssetBalance.balance, btcMarketData)
),
isLoading,
isInitialLoading,
}),
[btcAddress, btcAssetBalance, btcMarketData]
[btcAddress, btcAssetBalance, btcMarketData, isLoading, isInitialLoading]
);
}
27 changes: 19 additions & 8 deletions src/app/common/hooks/balance/use-total-balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,20 @@ export function useTotalBalance({ btcAddress, stxAddress }: UseTotalBalanceArgs)
const stxMarketData = useCryptoCurrencyMarketData('STX');

// get stx balance
const { data: balances, isLoading } = useStacksAccountBalances(stxAddress);
const { data: balances, isLoading, isInitialLoading } = useStacksAccountBalances(stxAddress);
const stxBalance = balances ? balances.stx.balance : createMoney(0, 'STX');

// get btc balance
const btcBalance = useBtcAssetBalance(btcAddress);
const {
btcAvailableAssetBalance,
isLoading: isLoadingBtcBalance,
isInitialLoading: isInititalLoadingBtcBalance,
} = useBtcAssetBalance(btcAddress);

return useMemo(() => {
// calculate total balance
const stxUsdAmount = baseCurrencyAmountInQuote(stxBalance, stxMarketData);
const btcUsdAmount = baseCurrencyAmountInQuote(
btcBalance.btcAvailableAssetBalance.balance,
btcMarketData
);
const btcUsdAmount = baseCurrencyAmountInQuote(btcAvailableAssetBalance.balance, btcMarketData);

const totalBalance = { ...stxUsdAmount, amount: stxUsdAmount.amount.plus(btcUsdAmount.amount) };
return {
Expand All @@ -41,7 +42,17 @@ export function useTotalBalance({ btcAddress, stxAddress }: UseTotalBalanceArgs)
totalBalance,
totalBalance.amount.isGreaterThanOrEqualTo(100_000) ? 0 : 2
),
isLoading,
isLoading: isLoading || isLoadingBtcBalance,
isInitialLoading: isInitialLoading || isInititalLoadingBtcBalance,
};
}, [btcBalance, btcMarketData, stxMarketData, isLoading, stxBalance]);
}, [
btcAvailableAssetBalance.balance,
btcMarketData,
isInitialLoading,
isInititalLoadingBtcBalance,
stxMarketData,
stxBalance,
isLoading,
isLoadingBtcBalance,
]);
}
27 changes: 17 additions & 10 deletions src/app/components/account-total-balance.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
import { memo } from 'react';

import { css } from 'leather-styles/css';
import { styled } from 'leather-styles/jsx';

import { useTotalBalance } from '@app/common/hooks/balance/use-total-balance';

import { shimmerStyles } from '../../../theme/global/shimmer-styles';
import { SkeletonLoader } from '../ui/components/skeleton-loader/skeleton-loader';
import { shimmerStyles } from '../ui/shared/shimmer-styles';

interface AccountTotalBalanceProps {
btcAddress: string;
stxAddress: string;
}

export const AccountTotalBalance = memo(({ btcAddress, stxAddress }: AccountTotalBalanceProps) => {
const { totalUsdBalance, isLoading } = useTotalBalance({ btcAddress, stxAddress });
const { totalUsdBalance, isLoading, isInitialLoading } = useTotalBalance({
btcAddress,
stxAddress,
});

if (!totalUsdBalance) return null;

return (
<styled.span
fontWeight={500}
textStyle="label.02"
data-state={isLoading ? 'loading' : undefined}
className={shimmerStyles}
>
{totalUsdBalance}
</styled.span>
<SkeletonLoader width="200px" height="38px" isLoading={isInitialLoading}>
<styled.span
className={css(shimmerStyles)}
textStyle="label.02"
data-state={isLoading ? 'loading' : undefined}
>
{totalUsdBalance}
</styled.span>
</SkeletonLoader>
);
});
6 changes: 3 additions & 3 deletions src/app/components/account/account-name.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { memo } from 'react';

import { css } from 'leather-styles/css';
import { styled } from 'leather-styles/jsx';

import { shimmerStyles } from '../../../../theme/global/shimmer-styles';
import { shimmerStyles } from '@app/ui/shared/shimmer-styles';

interface AccountNameLayoutProps {
children: React.ReactNode;
Expand All @@ -11,11 +12,10 @@ interface AccountNameLayoutProps {

export const AccountNameLayout = memo(({ children, isLoading }: AccountNameLayoutProps) => (
<styled.span
fontWeight={500}
className={css(shimmerStyles)}
textStyle="label.02"
aria-busy={isLoading}
data-state={isLoading ? 'loading' : undefined}
className={shimmerStyles}
>
{children}
</styled.span>
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/balance-btc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useCurrentNativeSegwitAddressBalance } from '@app/query/bitcoin/balance
import { Caption } from '@app/ui/components/typography/caption';

export function BtcBalance() {
const balance = useCurrentNativeSegwitAddressBalance();
const { balance } = useCurrentNativeSegwitAddressBalance();

return <Caption>{formatMoney(balance)}</Caption>;
}
6 changes: 3 additions & 3 deletions src/app/components/balance/bitcoin-balance-loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { useNativeSegwitBalance } from '@app/query/bitcoin/balance/btc-native-se

interface BitcoinBalanceLoaderProps {
address: string;
children(balance: BitcoinCryptoCurrencyAssetBalance): React.ReactNode;
children(balance: BitcoinCryptoCurrencyAssetBalance, isInitialLoading: boolean): React.ReactNode;
}

export function BitcoinBalanceLoader({ address, children }: BitcoinBalanceLoaderProps) {
const btcCryptoCurrencyAssetBalance = useNativeSegwitBalance(address);
return children(btcCryptoCurrencyAssetBalance);
const { btcBalance, isInitialLoading } = useNativeSegwitBalance(address);
return children(btcBalance, isInitialLoading);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface UseBitcoinCustomFeeArgs {
recipient: string;
}
export function useBitcoinCustomFee({ amount, isSendingMax, recipient }: UseBitcoinCustomFeeArgs) {
const balance = useCurrentNativeSegwitAddressBalance();
const { balance } = useCurrentNativeSegwitAddressBalance();
const { data: utxos = [] } = useCurrentNativeSegwitUtxos();
const btcMarketData = useCryptoCurrencyMarketData('BTC');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function useBitcoinFeesList({
recipient,
utxos,
}: UseBitcoinFeesListArgs) {
const balance = useCurrentNativeSegwitAddressBalance();
const { balance } = useCurrentNativeSegwitAddressBalance();
const btcMarketData = useCryptoCurrencyMarketData('BTC');
const { data: feeRates, isLoading } = useAverageBitcoinFeeRates();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import { Brc20TokenAssetItemLayout } from './components/brc20-token-asset-item.l
export function Brc20TokenAssetList(props: { brc20Tokens?: Brc20Token[] }) {
const navigate = useNavigate();
const currentAccountBtcAddress = useCurrentAccountNativeSegwitAddressIndexZero();
const btcCryptoCurrencyAssetBalance = useNativeSegwitBalance(currentAccountBtcAddress);
const { btcBalance: btcCryptoCurrencyAssetBalance } =
useNativeSegwitBalance(currentAccountBtcAddress);

const hasPositiveBtcBalanceForFees =
btcCryptoCurrencyAssetBalance.balance.amount.isGreaterThan(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function Brc20TokenAssetItemLayout({
label={formattedBalance.isAbbreviated ? balance.amount.toString() : undefined}
side="left"
>
<styled.span data-testid={token.ticker} fontWeight={500} textStyle="label.02">
<styled.span data-testid={token.ticker} textStyle="label.02">
{formattedBalance.value}
</styled.span>
</BasicTooltip>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ export function CryptoAssetList({
<BitcoinNativeSegwitAccountLoader current>
{signer => (
<BitcoinBalanceLoader address={signer.address}>
{balance => (
{(balance, isLoading) => (
<CryptoCurrencyAssetItemLayout
assetBalance={balance}
icon={<BtcAvatarIcon />}
onClick={() => onItemClick(balance)}
isLoading={isLoading}
/>
)}
</BitcoinBalanceLoader>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { AllCryptoCurrencyAssetBalances } from '@shared/models/crypto-asset-bala

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';
import { BasicTooltip } from '@app/ui/components/tooltip/basic-tooltip';
import { Caption } from '@app/ui/components/typography/caption';
import { Pressable } from '@app/ui/pressable/pressable';
Expand All @@ -18,6 +19,7 @@ interface CryptoCurrencyAssetItemLayoutProps {
address?: string;
assetBalance: AllCryptoCurrencyAssetBalances;
icon: React.ReactNode;
isLoading?: boolean;
onClick?(): void;
rightElement?: React.ReactNode;
usdBalance?: string;
Expand All @@ -31,44 +33,55 @@ export function CryptoCurrencyAssetItemLayout({
onClick,
rightElement,
usdBalance,
isLoading = false,
}: CryptoCurrencyAssetItemLayoutProps) {
const { balance, dataTestId, formattedBalance, title } =
parseCryptoCurrencyAssetBalance(assetBalance);

const titleRight = (
<SkeletonLoader width="126px" isLoading={isLoading}>
{rightElement ? (
rightElement
) : (
<BasicTooltip
asChild
label={formattedBalance.isAbbreviated ? balance.amount.toString() : undefined}
side="left"
>
<styled.span data-testid={title} textStyle="label.02">
{formattedBalance.value} {additionalBalanceInfo}
</styled.span>
</BasicTooltip>
)}
</SkeletonLoader>
);

const captionRight = (
<SkeletonLoader width="78px" isLoading={isLoading}>
{rightElement ? (
rightElement
) : (
<Caption>
<Flex alignItems="center" gap="space.02" color="inherit">
<BulletSeparator>
<Caption>{balance.amount.toNumber() > 0 && address ? usdBalance : null}</Caption>
{additionalUsdBalanceInfo}
</BulletSeparator>
</Flex>
</Caption>
)}
</SkeletonLoader>
);

const isInteractive = !!onClick;

const content = (
<ItemLayout
flagImg={icon}
titleLeft={title}
captionLeft={balance.symbol}
titleRight={
rightElement ? (
rightElement
) : (
<BasicTooltip
asChild
label={formattedBalance.isAbbreviated ? balance.amount.toString() : undefined}
side="left"
>
<styled.span data-testid={title} fontWeight={500} textStyle="label.02">
{formattedBalance.value} {additionalBalanceInfo}
</styled.span>
</BasicTooltip>
)
}
captionRight={
!rightElement && (
<Caption>
<Flex alignItems="center" gap="space.02" color="inherit">
<BulletSeparator>
<Caption>{balance.amount.toNumber() > 0 && address ? usdBalance : null}</Caption>
{additionalUsdBalanceInfo}
</BulletSeparator>
</Flex>
</Caption>
)
}
titleRight={titleRight}
captionRight={captionRight}
/>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function StacksFungibleTokenAssetItemLayout({
label={formattedBalance.isAbbreviated ? amount : undefined}
side="left"
>
<styled.span data-testid={title} fontWeight={500} textStyle="label.02">
<styled.span data-testid={title} textStyle="label.02">
{formattedBalance.value}
</styled.span>
</BasicTooltip>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface TransactionItemLayoutProps {
txStatus?: ReactNode;
children?: ReactNode;
}

export function TransactionItemLayout({
openTxLink,
rightElement,
Expand All @@ -37,13 +38,7 @@ export function TransactionItemLayout({
</HStack>
}
titleRight={
rightElement ? (
rightElement
) : (
<styled.span fontWeight={500} textStyle="label.02">
{txValue}
</styled.span>
)
rightElement ? rightElement : <styled.span textStyle="label.02">{txValue}</styled.span>
}
/>
</Pressable>
Expand Down
1 change: 0 additions & 1 deletion src/app/components/transaction/transaction-title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export function TransactionTitle(props: TransactionTitleProps) {
return (
<BasicTooltip disabled={!isEllipsisActive} label={title} side="top">
<Title
fontWeight={500}
overflow="hidden"
ref={ref}
textOverflow="ellipsis"
Expand Down
5 changes: 4 additions & 1 deletion src/app/features/asset-list/asset-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export function AssetsList() {
const btcAddress = useCurrentAccountNativeSegwitAddressIndexZero();
const network = useCurrentNetwork();

const { btcAvailableAssetBalance, btcAvailableUsdBalance } = useBtcAssetBalance(btcAddress);
const { btcAvailableAssetBalance, btcAvailableUsdBalance, isInitialLoading } =
useBtcAssetBalance(btcAddress);

const { whenWallet } = useWalletType();

Expand All @@ -40,6 +41,7 @@ export function AssetsList() {
usdBalance={btcAvailableUsdBalance}
icon={<BtcAvatarIcon />}
address={btcAddress}
isLoading={isInitialLoading}
/>
),
ledger: (
Expand All @@ -48,6 +50,7 @@ export function AssetsList() {
usdBalance={btcAvailableUsdBalance}
icon={<BtcAvatarIcon />}
address={btcAddress}
isLoading={isInitialLoading}
rightElement={
hasBitcoinLedgerKeys ? undefined : <ConnectLedgerAssetBtn chain="bitcoin" />
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/features/bitcoin-choose-fee/bitcoin-choose-fee.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export function BitcoinChooseFee({
...rest
}: BitcoinChooseFeeProps) {
const nativeSegwitSigner = useCurrentAccountNativeSegwitIndexZeroSigner();
const btcBalance = useNativeSegwitBalance(nativeSegwitSigner.address);
const { btcBalance } = useNativeSegwitBalance(nativeSegwitSigner.address);
const hasAmount = amount.amount.isGreaterThan(0);
const [customFeeInitialValue, setCustomFeeInitialValue] = useState(recommendedFeeRate);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useCurrentNativeSegwitAddressBalance } from '@app/query/bitcoin/balance

export function useValidateBitcoinSpend(amount?: Money, isSendingMax?: boolean) {
const [showInsufficientBalanceError, setShowInsufficientBalanceError] = useState(false);
const balance = useCurrentNativeSegwitAddressBalance();
const { balance } = useCurrentNativeSegwitAddressBalance();

return {
showInsufficientBalanceError,
Expand Down
Loading
Loading