mirror of
https://github.com/zhigang1992/wallet.git
synced 2026-01-12 22:53:27 +08:00
fix: add StacksAccountLoader
This commit is contained in:
12
src/app/components/stacks-account-loader.tsx
Normal file
12
src/app/components/stacks-account-loader.tsx
Normal 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);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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));
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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[]) ?? [];
|
||||
// }
|
||||
|
||||
@@ -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>;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 = [];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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[]>) {
|
||||
|
||||
Reference in New Issue
Block a user