fix: add StacksAccountLoader

This commit is contained in:
kyranjamie
2023-07-25 14:51:32 +01:00
committed by kyranjamie
parent 824ea332a8
commit aa5d9048d4
14 changed files with 87 additions and 53 deletions

View File

@@ -0,0 +1,12 @@
import { useCurrentStacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';
import { StacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.models';
interface CurrentStacksAccountLoaderProps {
children(data: StacksAccount): React.ReactNode;
}
export function CurrentStacksAccountLoader({ children }: CurrentStacksAccountLoaderProps) {
const currentAccount = useCurrentStacksAccount();
if (!currentAccount) return null;
return children(currentAccount);
}

View File

@@ -1,4 +1,4 @@
import { useOutletContext } from 'react-router-dom';
import { Outlet } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import { Box, Stack, Text } from '@stacks/ui';
@@ -14,37 +14,28 @@ import { Brc20TokensLoader } from '@app/components/brc20-tokens-loader';
import { CryptoCurrencyAssetItem } from '@app/components/crypto-assets/crypto-currency-asset/crypto-currency-asset-item';
import { StxAvatar } from '@app/components/crypto-assets/stacks/components/stx-avatar';
import { BtcIcon } from '@app/components/icons/btc-icon';
import { LoadingSpinner } from '@app/components/loading-spinner';
import { CurrentStacksAccountLoader } from '@app/components/stacks-account-loader';
import { Caption } from '@app/components/typography';
import { useStacksFungibleTokenAssetBalancesAnchoredWithMetadata } from '@app/query/stacks/balance/stacks-ft-balances.hooks';
import { useCurrentAccountNativeSegwitAddressIndexZero } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { StacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.models';
import { Collectibles } from '../collectibles/collectibles';
import { PendingBrc20TransferList } from '../pending-brc-20-transfers/pending-brc-20-transfers';
import { BitcoinFungibleTokenAssetList } from './components/bitcoin-fungible-tokens-asset-list';
import { StacksFungibleTokenAssetList } from './components/stacks-fungible-token-asset-list';
interface BalancesListContextState {
address: string;
interface StacksBalanceViewerProps {
account: StacksAccount;
}
export function BalancesList(): React.JSX.Element {
const { address } = useOutletContext<BalancesListContextState>();
const stacksFtAssetBalances = useStacksFungibleTokenAssetBalancesAnchoredWithMetadata(address);
const btcAddress = useCurrentAccountNativeSegwitAddressIndexZero();
const {
stxEffectiveBalance,
stxEffectiveUsdBalance,
stxLockedBalance,
stxUsdLockedBalance,
isLoading,
} = useStxBalance();
const { btcAvailableAssetBalance, btcAvailableUsdBalance } = useBtcAssetBalance(btcAddress);
const { whenWallet } = useWalletType();
const navigate = useNavigate();
export function StacksBalanceViewer({ account }: StacksBalanceViewerProps) {
const stacksFtAssetBalances = useStacksFungibleTokenAssetBalancesAnchoredWithMetadata(
account.address
);
// Better handle loading state
if (isLoading) return <LoadingSpinner />;
const { stxEffectiveBalance, stxEffectiveUsdBalance, stxLockedBalance, stxUsdLockedBalance } =
useStxBalance();
const stxAdditionalBalanceInfo = stxLockedBalance?.amount.isGreaterThan(0) ? (
<Text>({ftDecimals(stxLockedBalance.amount, stxLockedBalance.decimals || 0)} locked)</Text>
@@ -54,6 +45,28 @@ export function BalancesList(): React.JSX.Element {
<Caption ml="4px">({stxUsdLockedBalance} locked)</Caption>
) : undefined;
return (
<>
<CryptoCurrencyAssetItem
assetBalance={stxEffectiveBalance}
usdBalance={stxEffectiveUsdBalance}
address={account.address}
additionalBalanceInfo={stxAdditionalBalanceInfo}
additionalUsdBalanceInfo={stxAdditionalUsdBalanceInfo}
icon={<StxAvatar />}
/>
<StacksFungibleTokenAssetList assetBalances={stacksFtAssetBalances} />
</>
);
}
export function BalancesList() {
const btcAddress = useCurrentAccountNativeSegwitAddressIndexZero();
const { btcAvailableAssetBalance, btcAvailableUsdBalance } = useBtcAssetBalance(btcAddress);
const { whenWallet } = useWalletType();
const navigate = useNavigate();
return (
<Stack pb="extra-loose" spacing="loose" data-testid={HomePageSelectorsLegacy.BalancesList}>
{/* Temporary duplication during Ledger Bitcoin feature dev */}
@@ -78,15 +91,11 @@ export function BalancesList(): React.JSX.Element {
/>
) : null,
})}
<CryptoCurrencyAssetItem
assetBalance={stxEffectiveBalance}
usdBalance={stxEffectiveUsdBalance}
address={address}
additionalBalanceInfo={stxAdditionalBalanceInfo}
additionalUsdBalanceInfo={stxAdditionalUsdBalanceInfo}
icon={<StxAvatar />}
/>
<StacksFungibleTokenAssetList assetBalances={stacksFtAssetBalances} />
<CurrentStacksAccountLoader>
{account => <StacksBalanceViewer account={account} />}
</CurrentStacksAccountLoader>
{whenWallet({
software: (
<Brc20TokensLoader>
@@ -96,7 +105,9 @@ export function BalancesList(): React.JSX.Element {
ledger: null,
})}
<PendingBrc20TransferList />
<Collectibles />
<Outlet />
</Stack>
);
}

View File

@@ -3,14 +3,17 @@ import { useEffect } from 'react';
import { useAnalytics } from '@app/common/hooks/analytics/use-analytics';
import { parseIfValidPunycode } from '@app/common/utils';
import { useCurrentAccountNames } from '@app/query/stacks/bns/bns.hooks';
import { useNonFungibleTokensMetadata } from '@app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-metadata.hooks';
import { useStacksNonFungibleTokensMetadata } from '@app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-metadata.hooks';
import { useCurrentStacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';
import { StacksBnsName } from './stacks-bns-name';
import { StacksNonFungibleTokens } from './stacks-non-fungible-tokens';
export function StacksCryptoAssets() {
const currentAccount = useCurrentStacksAccount();
const { data: names = [] } = useCurrentAccountNames();
const stacksNftsMetadataResp = useNonFungibleTokensMetadata();
const stacksNftsMetadataResp = useStacksNonFungibleTokensMetadata();
const analytics = useAnalytics();
useEffect(() => {

View File

@@ -6,7 +6,7 @@ import { bitcoinNetworkModeToCoreNetworkMode } from '@shared/crypto/bitcoin/bitc
import { LedgerRequestKeysContext } from '@app/features/ledger/generic-flows/request-keys/ledger-request-keys.context';
import { useLedgerNavigate } from '@app/features/ledger/hooks/use-ledger-navigate';
import { useActionCancellableByUser } from '@app/features/ledger/utils/stacks-ledger-utils';
import { bitcoinKeySlice } from '@app/store/ledger/bitcoin-key.slice';
import { bitcoinKeysSlice } from '@app/store/ledger/bitcoin-key.slice';
import { useCurrentNetwork } from '@app/store/networks/networks.selectors';
import { ledgerRequestKeysRoutes } from '../../generic-flows/request-keys/ledger-request-keys-route-generator';
@@ -46,7 +46,7 @@ function LedgerRequestBitcoinKeys() {
ledgerNavigate.toDeviceBusyStep(`Requesting Bitcoin Taproot address (${index - 4}…5)`);
},
});
dispatch(bitcoinKeySlice.actions.addBitcoinKeys(keys));
dispatch(bitcoinKeysSlice.actions.addBitcoinKeys(keys));
},
});

View File

@@ -10,7 +10,7 @@ import { LoadingSpinner } from '@app/components/loading-spinner';
import { Tabs } from '@app/components/tabs';
interface HomeTabsProps extends StackProps {
children: React.JSX.Element;
children: React.ReactNode;
}
// TODO #4013: Abstract this to generic RouteTab once choose-fee-tab updated
export function HomeTabs({ children }: HomeTabsProps) {

View File

@@ -3,10 +3,10 @@ import { useCurrentStacksAccount } from '@app/store/accounts/blockchain/stacks/s
import { StacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.models';
interface HomeLoaderProps {
children(data: StacksAccount): React.JSX.Element;
children(data?: StacksAccount): React.JSX.Element;
}
export function HomeLoader({ children }: HomeLoaderProps) {
const currentAccount = useCurrentStacksAccount();
if (!currentAccount) return <FullPageLoadingSpinner />;
// if (!currentAccount) return <FullPageLoadingSpinner />;
return children(currentAccount);
}

View File

@@ -1,3 +1,4 @@
import { useDispatch } from 'react-redux';
import { Outlet, useNavigate } from 'react-router-dom';
import { RouteUrls } from '@shared/route-urls';
@@ -11,6 +12,7 @@ import { InAppMessages } from '@app/features/hiro-messages/in-app-messages';
import { SuggestedFirstSteps } from '@app/features/suggested-first-steps/suggested-first-steps';
import { HomeActions } from '@app/pages/home/components/home-actions';
import { StacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.models';
import { keyActions } from '@app/store/keys/key.actions';
import { CurrentAccount } from './components/account-area';
import { HomeTabs } from './components/home-tabs';
@@ -29,6 +31,8 @@ function HomeContainer({ account }: HomeContainerProps) {
const navigate = useNavigate();
useTrackFirstDeposit();
const dispatch = useDispatch();
useRouteHeader(
<>
<InAppMessages />
@@ -47,7 +51,8 @@ function HomeContainer({ account }: HomeContainerProps) {
actions={<HomeActions />}
>
<HomeTabs>
<Outlet context={{ address: account.address }} />
<button onClick={() => dispatch(keyActions.debugKillStacks())}>kill stacks</button>
<Outlet context={{ address: account?.address }} />
</HomeTabs>
</HomeLayout>
);

View File

@@ -32,12 +32,12 @@ interface NonFungibleTokenHoldingListResult {
tx_id: string;
}
export function useAccountNonFungibleTokenHoldings() {
const currentAccount = useCurrentStacksAccount();
// export function useAccountNonFungibleTokenHoldings() {
// const currentAccount = useCurrentStacksAccount();
const { data: nonFungibleTokenHoldings } = useGetNonFungibleTokenHoldingsQuery(
currentAccount?.address
);
// const { data: nonFungibleTokenHoldings } = useGetNonFungibleTokenHoldingsQuery(
// currentAccount?.address
// );
return (nonFungibleTokenHoldings?.results as NonFungibleTokenHoldingListResult[]) ?? [];
}
// return (nonFungibleTokenHoldings?.results as NonFungibleTokenHoldingListResult[]) ?? [];
// }

View File

@@ -1,4 +1,3 @@
import { NonFungibleTokenHoldingsList } from '@stacks/blockchain-api-client';
import { useQueries, useQuery } from '@tanstack/react-query';
import { AppUseQueryConfig } from '@app/query/query-config';
@@ -23,7 +22,7 @@ function fetchNonFungibleTokenHoldings(client: StacksClient, limiter: RateLimite
return client.nonFungibleTokensApi.getNftHoldings({
principal: address,
limit: 50,
}) as Promise<NonFungibleTokenHoldingsList>;
});
};
}

View File

@@ -3,7 +3,7 @@ import { useMemo } from 'react';
import { isNftAsset } from '../token-metadata.utils';
import { useGetNonFungibleTokenMetadataListQuery } from './non-fungible-token-metadata.query';
export function useNonFungibleTokensMetadata() {
export function useStacksNonFungibleTokensMetadata() {
const respList = useGetNonFungibleTokenMetadataListQuery();
return useMemo(

View File

@@ -8,7 +8,6 @@ import { useTokenMetadataClient } from '@app/store/common/api-clients.hooks';
import { RateLimiter, useHiroApiRateLimiter } from '../../rate-limiter';
import { TokenMetadataClient } from '../../token-metadata-client';
import { NftAssetResponse } from '../token-metadata.utils';
import { useAccountNonFungibleTokenHoldings } from './non-fungible-token-holdings.hooks';
const queryOptions = {
refetchOnWindowFocus: true,

View File

@@ -23,7 +23,7 @@ import { appPermissionsSlice } from './app-permissions/app-permissions.slice';
import { stxChainSlice } from './chains/stx-chain.slice';
import { inMemoryKeySlice } from './in-memory-key/in-memory-key.slice';
import { keySlice } from './keys/key.slice';
import { bitcoinKeySlice } from './ledger/bitcoin-key.slice';
import { bitcoinKeysSlice } from './ledger/bitcoin-key.slice';
import { networksSlice } from './networks/networks.slice';
import { onboardingSlice } from './onboarding/onboarding.slice';
import { ordinalsSlice } from './ordinals/ordinals.slice';
@@ -38,7 +38,7 @@ export interface RootState {
stx: ReturnType<typeof stxChainSlice.reducer>;
};
ledger: {
bitcoin: ReturnType<typeof bitcoinKeySlice.reducer>;
bitcoin: ReturnType<typeof bitcoinKeysSlice.reducer>;
};
ordinals: ReturnType<typeof ordinalsSlice.reducer>;
inMemoryKeys: ReturnType<typeof inMemoryKeySlice.reducer>;
@@ -56,7 +56,7 @@ const appReducer = combineReducers({
stx: stxChainSlice.reducer,
}),
ledger: combineReducers({
bitcoin: bitcoinKeySlice.reducer,
bitcoin: bitcoinKeysSlice.reducer,
}),
ordinals: ordinalsSlice.reducer,
inMemoryKeys: inMemoryKeySlice.reducer,

View File

@@ -40,5 +40,10 @@ export const keySlice = createSlice({
signOut(state) {
keyAdapter.removeOne(state, defaultKeyId);
},
debugKillStacks(state) {
if (state.entities.default?.type !== 'ledger') return;
state.entities.default.publicKeys = [];
},
},
});

View File

@@ -11,8 +11,8 @@ interface PersistedBitcoinKeys extends BitcoinLedgerAccountDetails {
const bitcoinKeyAdapter = createEntityAdapter<PersistedBitcoinKeys>();
export const bitcoinKeySlice = createSlice({
name: 'bitcoinKeys',
export const bitcoinKeysSlice = createSlice({
name: 'bitcoinsKeys',
initialState: bitcoinKeyAdapter.getInitialState(),
reducers: {
addBitcoinKeys(state, { payload }: PayloadAction<BitcoinLedgerAccountDetails[]>) {