From aa5d9048d413cd1be24769a7147e0884b244224a Mon Sep 17 00:00:00 2001 From: kyranjamie Date: Tue, 25 Jul 2023 14:51:32 +0100 Subject: [PATCH] fix: add StacksAccountLoader --- src/app/components/stacks-account-loader.tsx | 12 ++++ .../features/balances-list/balances-list.tsx | 69 +++++++++++-------- .../stacks/stacks-crypto-assets.tsx | 7 +- .../ledger-request-bitcoin-keys.tsx | 4 +- src/app/pages/home/components/home-tabs.tsx | 2 +- src/app/pages/home/home.loader.tsx | 4 +- src/app/pages/home/home.tsx | 7 +- .../non-fungible-token-holdings.hooks.ts | 14 ++-- .../non-fungible-token-holdings.query.ts | 3 +- .../non-fungible-token-metadata.hooks.ts | 2 +- .../non-fungible-token-metadata.query.ts | 1 - src/app/store/index.ts | 6 +- src/app/store/keys/key.slice.ts | 5 ++ src/app/store/ledger/bitcoin-key.slice.ts | 4 +- 14 files changed, 87 insertions(+), 53 deletions(-) create mode 100644 src/app/components/stacks-account-loader.tsx diff --git a/src/app/components/stacks-account-loader.tsx b/src/app/components/stacks-account-loader.tsx new file mode 100644 index 00000000..9b71b6ba --- /dev/null +++ b/src/app/components/stacks-account-loader.tsx @@ -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); +} diff --git a/src/app/features/balances-list/balances-list.tsx b/src/app/features/balances-list/balances-list.tsx index af1e7c54..810c02aa 100644 --- a/src/app/features/balances-list/balances-list.tsx +++ b/src/app/features/balances-list/balances-list.tsx @@ -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(); - 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 ; + const { stxEffectiveBalance, stxEffectiveUsdBalance, stxLockedBalance, stxUsdLockedBalance } = + useStxBalance(); const stxAdditionalBalanceInfo = stxLockedBalance?.amount.isGreaterThan(0) ? ( ({ftDecimals(stxLockedBalance.amount, stxLockedBalance.decimals || 0)} locked) @@ -54,6 +45,28 @@ export function BalancesList(): React.JSX.Element { ({stxUsdLockedBalance} locked) ) : undefined; + return ( + <> + } + /> + + + ); +} + +export function BalancesList() { + const btcAddress = useCurrentAccountNativeSegwitAddressIndexZero(); + + const { btcAvailableAssetBalance, btcAvailableUsdBalance } = useBtcAssetBalance(btcAddress); + const { whenWallet } = useWalletType(); + const navigate = useNavigate(); + return ( {/* Temporary duplication during Ledger Bitcoin feature dev */} @@ -78,15 +91,11 @@ export function BalancesList(): React.JSX.Element { /> ) : null, })} - } - /> - + + + {account => } + + {whenWallet({ software: ( @@ -96,7 +105,9 @@ export function BalancesList(): React.JSX.Element { ledger: null, })} + + ); } diff --git a/src/app/features/collectibles/components/stacks/stacks-crypto-assets.tsx b/src/app/features/collectibles/components/stacks/stacks-crypto-assets.tsx index e8d70af8..9eca46ed 100644 --- a/src/app/features/collectibles/components/stacks/stacks-crypto-assets.tsx +++ b/src/app/features/collectibles/components/stacks/stacks-crypto-assets.tsx @@ -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(() => { diff --git a/src/app/features/ledger/flows/request-bitcoin-keys/ledger-request-bitcoin-keys.tsx b/src/app/features/ledger/flows/request-bitcoin-keys/ledger-request-bitcoin-keys.tsx index dde5e481..bd236947 100644 --- a/src/app/features/ledger/flows/request-bitcoin-keys/ledger-request-bitcoin-keys.tsx +++ b/src/app/features/ledger/flows/request-bitcoin-keys/ledger-request-bitcoin-keys.tsx @@ -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)); }, }); diff --git a/src/app/pages/home/components/home-tabs.tsx b/src/app/pages/home/components/home-tabs.tsx index 5eb66e4d..a15a314d 100644 --- a/src/app/pages/home/components/home-tabs.tsx +++ b/src/app/pages/home/components/home-tabs.tsx @@ -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) { diff --git a/src/app/pages/home/home.loader.tsx b/src/app/pages/home/home.loader.tsx index 7341f640..85c132db 100644 --- a/src/app/pages/home/home.loader.tsx +++ b/src/app/pages/home/home.loader.tsx @@ -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 ; + // if (!currentAccount) return ; return children(currentAccount); } diff --git a/src/app/pages/home/home.tsx b/src/app/pages/home/home.tsx index 1f7403b1..087f141c 100644 --- a/src/app/pages/home/home.tsx +++ b/src/app/pages/home/home.tsx @@ -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( <> @@ -47,7 +51,8 @@ function HomeContainer({ account }: HomeContainerProps) { actions={} > - + + ); diff --git a/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-holdings.hooks.ts b/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-holdings.hooks.ts index d8033865..511e46fb 100644 --- a/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-holdings.hooks.ts +++ b/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-holdings.hooks.ts @@ -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[]) ?? []; +// } diff --git a/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-holdings.query.ts b/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-holdings.query.ts index f380cc95..56e7363a 100644 --- a/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-holdings.query.ts +++ b/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-holdings.query.ts @@ -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; + }); }; } diff --git a/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-metadata.hooks.ts b/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-metadata.hooks.ts index 79fcff0d..6e4c20d6 100644 --- a/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-metadata.hooks.ts +++ b/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-metadata.hooks.ts @@ -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( diff --git a/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-metadata.query.ts b/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-metadata.query.ts index 1561c372..5bdcd233 100644 --- a/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-metadata.query.ts +++ b/src/app/query/stacks/tokens/non-fungible-tokens/non-fungible-token-metadata.query.ts @@ -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, diff --git a/src/app/store/index.ts b/src/app/store/index.ts index 4ef73a6a..c5d15646 100644 --- a/src/app/store/index.ts +++ b/src/app/store/index.ts @@ -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; }; ledger: { - bitcoin: ReturnType; + bitcoin: ReturnType; }; ordinals: ReturnType; inMemoryKeys: ReturnType; @@ -56,7 +56,7 @@ const appReducer = combineReducers({ stx: stxChainSlice.reducer, }), ledger: combineReducers({ - bitcoin: bitcoinKeySlice.reducer, + bitcoin: bitcoinKeysSlice.reducer, }), ordinals: ordinalsSlice.reducer, inMemoryKeys: inMemoryKeySlice.reducer, diff --git a/src/app/store/keys/key.slice.ts b/src/app/store/keys/key.slice.ts index 5c5668dd..1e2fc8a7 100644 --- a/src/app/store/keys/key.slice.ts +++ b/src/app/store/keys/key.slice.ts @@ -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 = []; + }, }, }); diff --git a/src/app/store/ledger/bitcoin-key.slice.ts b/src/app/store/ledger/bitcoin-key.slice.ts index 303f0b48..8a3a36f3 100644 --- a/src/app/store/ledger/bitcoin-key.slice.ts +++ b/src/app/store/ledger/bitcoin-key.slice.ts @@ -11,8 +11,8 @@ interface PersistedBitcoinKeys extends BitcoinLedgerAccountDetails { const bitcoinKeyAdapter = createEntityAdapter(); -export const bitcoinKeySlice = createSlice({ - name: 'bitcoinKeys', +export const bitcoinKeysSlice = createSlice({ + name: 'bitcoinsKeys', initialState: bitcoinKeyAdapter.getInitialState(), reducers: { addBitcoinKeys(state, { payload }: PayloadAction) {