diff --git a/.changeset/unlucky-kiwis-brush.md b/.changeset/unlucky-kiwis-brush.md new file mode 100644 index 0000000000..f9a14ff46d --- /dev/null +++ b/.changeset/unlucky-kiwis-brush.md @@ -0,0 +1,5 @@ +--- +"alephium-desktop-wallet": patch +--- + +Improve performance diff --git a/apps/desktop-wallet/package.json b/apps/desktop-wallet/package.json index 3a7494099f..8ad24d6663 100644 --- a/apps/desktop-wallet/package.json +++ b/apps/desktop-wallet/package.json @@ -1,7 +1,7 @@ { "name": "alephium-desktop-wallet", "description": "The official Alephium wallet", - "version": "2.4.4", + "version": "2.5.0-rc.0", "author": "Alephium dev ", "main": "dist-electron/main.js", "homepage": "./", @@ -123,7 +123,7 @@ "jsdom": "^21.1.1", "lodash": "^4.17.21", "lucide-react": "^0.287.0", - "nanoid": "^4.0.0", + "nanoid": "^3.3.8", "posthog-js": "^1.52.0", "qrloop": "^1.4.1", "react": "^18.2.0", diff --git a/apps/desktop-wallet/src/App.tsx b/apps/desktop-wallet/src/App.tsx index 0a808c7484..ac2c618676 100644 --- a/apps/desktop-wallet/src/App.tsx +++ b/apps/desktop-wallet/src/App.tsx @@ -18,7 +18,7 @@ along with the library. If not, see . import { localStorageNetworkSettingsMigrated } from '@alephium/shared' import { useInitializeThrottledClient } from '@alephium/shared-react' -import { ReactNode, useCallback, useEffect } from 'react' +import { memo, ReactNode, useCallback, useEffect } from 'react' import styled, { css, ThemeProvider } from 'styled-components' import PersistedQueryCacheVersionStorage from '@/api/persistedCacheVersionStorage' @@ -54,7 +54,7 @@ import { GlobalStyle } from '@/style/globalStyles' import { currentVersion } from '@/utils/app-data' import { migrateGeneralSettings, migrateNetworkSettings, migrateWalletData } from '@/utils/migration' -const App = () => { +const App = memo(() => { const theme = useAppSelector((s) => s.global.theme) useAutoLock() @@ -90,7 +90,7 @@ const App = () => { ) -} +}) export default App diff --git a/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchListedFtsWorth.ts b/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchListedFtsWorth.ts index f78705ac4f..b5c6c45cbc 100644 --- a/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchListedFtsWorth.ts +++ b/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchListedFtsWorth.ts @@ -21,10 +21,10 @@ import { isNumber } from 'lodash' import { useMemo } from 'react' import useFetchTokenPrices from '@/api/apiDataHooks/market/useFetchTokenPrices' -import { DisplayBalances, ListedFT } from '@/types/tokens' +import { ApiBalances, ListedFT } from '@/types/tokens' interface UseListedFtsWorthProps { - listedFts: (ListedFT & DisplayBalances)[] + listedFts: (ListedFT & ApiBalances)[] } const useFetchListedFtsWorth = ({ listedFts }: UseListedFtsWorthProps) => { @@ -35,7 +35,7 @@ const useFetchListedFtsWorth = ({ listedFts }: UseListedFtsWorthProps) => { listedFts.reduce((totalWorth, token) => { const tokenPrice = tokenPrices?.find(({ symbol }) => symbol === token.symbol)?.price const tokenWorth = isNumber(tokenPrice) - ? calculateAmountWorth(token.totalBalance, tokenPrice, token.decimals) + ? calculateAmountWorth(BigInt(token.totalBalance), tokenPrice, token.decimals) : 0 return totalWorth + tokenWorth diff --git a/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchSortedFts.ts b/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchSortedFts.ts index 564f19ecf4..cff506c56b 100644 --- a/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchSortedFts.ts +++ b/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchSortedFts.ts @@ -27,10 +27,10 @@ import useFetchTokenPrices from '@/api/apiDataHooks/market/useFetchTokenPrices' import { fungibleTokenMetadataQuery } from '@/api/queries/tokenQueries' import { useAppSelector } from '@/hooks/redux' import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' -import { DisplayBalances, ListedFT, TokenId } from '@/types/tokens' +import { ApiBalances, ListedFT, TokenId } from '@/types/tokens' interface UseSortFTsProps extends SkipProp { - listedFts: (ListedFT & DisplayBalances)[] + listedFts: (ListedFT & ApiBalances)[] unlistedFtIds: TokenId[] } @@ -59,7 +59,7 @@ const useFetchSortedFts = ({ listedFts, unlistedFtIds, skip }: UseSortFTsProps) const tokenPrice = tokenPrices?.find((tokenPrice) => tokenPrice.symbol === token.symbol)?.price return isNumber(tokenPrice) - ? calculateAmountWorth(token.totalBalance, tokenPrice, token.decimals) + ? calculateAmountWorth(BigInt(token.totalBalance), tokenPrice, token.decimals) : -1 }, 'name', diff --git a/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchWalletBalancesAlph.ts b/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchWalletBalancesAlph.ts new file mode 100644 index 0000000000..1fd6862459 --- /dev/null +++ b/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchWalletBalancesAlph.ts @@ -0,0 +1,50 @@ +/* +Copyright 2018 - 2024 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +import { useQueries, UseQueryResult } from '@tanstack/react-query' + +import { addressAlphBalancesQuery, AddressAlphBalancesQueryFnData } from '@/api/queries/addressQueries' +import { useAppSelector } from '@/hooks/redux' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' +import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' + +const useFetchWalletBalancesAlph = ( + combine: (results: UseQueryResult[]) => { + data: T + isLoading: boolean + isFetching?: boolean + error?: boolean + } +) => { + const networkId = useAppSelector(selectCurrentlyOnlineNetworkId) + const allAddressHashes = useUnsortedAddressesHashes() + + const { data, isLoading, isFetching, error } = useQueries({ + queries: allAddressHashes.map((addressHash) => addressAlphBalancesQuery({ addressHash, networkId })), + combine + }) + + return { + data, + isLoading, + isFetching, + error + } +} + +export default useFetchWalletBalancesAlph diff --git a/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchWalletBalancesTokens.ts b/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchWalletBalancesTokens.ts new file mode 100644 index 0000000000..3560ad3c5f --- /dev/null +++ b/apps/desktop-wallet/src/api/apiDataHooks/utils/useFetchWalletBalancesTokens.ts @@ -0,0 +1,48 @@ +/* +Copyright 2018 - 2024 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +import { useQueries, UseQueryResult } from '@tanstack/react-query' + +import { addressTokensBalancesQuery, AddressTokensBalancesQueryFnData } from '@/api/queries/addressQueries' +import { useAppSelector } from '@/hooks/redux' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' +import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' + +export const useFetchWalletBalancesTokens = ( + combine: (results: UseQueryResult[]) => { + data: T + isLoading: boolean + isFetching?: boolean + error?: boolean + } +) => { + const networkId = useAppSelector(selectCurrentlyOnlineNetworkId) + const allAddressHashes = useUnsortedAddressesHashes() + + const { data, isLoading, isFetching, error } = useQueries({ + queries: allAddressHashes.map((addressHash) => addressTokensBalancesQuery({ addressHash, networkId })), + combine + }) + + return { + data, + isLoading, + isFetching, + error + } +} diff --git a/apps/desktop-wallet/src/api/apiDataHooks/utils/useMergeAllTokensBalances.ts b/apps/desktop-wallet/src/api/apiDataHooks/utils/useMergeAllTokensBalances.ts index 85cd254b4a..b2f9d4aa5f 100644 --- a/apps/desktop-wallet/src/api/apiDataHooks/utils/useMergeAllTokensBalances.ts +++ b/apps/desktop-wallet/src/api/apiDataHooks/utils/useMergeAllTokensBalances.ts @@ -19,12 +19,12 @@ along with the library. If not, see . import { ALPH } from '@alephium/token-list' import { useMemo } from 'react' -import { DisplayBalances, TokenDisplayBalances } from '@/types/tokens' +import { ApiBalances, TokenApiBalances } from '@/types/tokens' interface UseMergeAllTokensBalancesProps { includeAlph: boolean - alphBalances?: DisplayBalances - tokensBalances?: TokenDisplayBalances[] + alphBalances?: ApiBalances + tokensBalances?: TokenApiBalances[] } const useMergeAllTokensBalances = ({ diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchLatestTransactionOfEachAddress.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchLatestTransactionOfEachAddress.ts index 7e36140eae..005f5ae19d 100644 --- a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchLatestTransactionOfEachAddress.ts +++ b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchLatestTransactionOfEachAddress.ts @@ -22,7 +22,7 @@ import { SkipProp } from '@/api/apiDataHooks/apiDataHooksTypes' import { flatMapCombine } from '@/api/apiDataHooks/apiDataHooksUtils' import { addressLatestTransactionQuery } from '@/api/queries/transactionQueries' import { useAppSelector } from '@/hooks/redux' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' const useFetchLatestTransactionOfEachAddress = (props?: SkipProp) => { diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalances.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalances.ts index d385ed3f73..af093005d1 100644 --- a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalances.ts +++ b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalances.ts @@ -17,8 +17,8 @@ along with the library. If not, see . */ import useMergeAllTokensBalances from '@/api/apiDataHooks/utils/useMergeAllTokensBalances' -import { useFetchWalletBalancesAlphArray } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlph' -import { useFetchWalletBalancesTokensArray } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokens' +import useFetchWalletBalancesAlphArray from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphArray' +import useFetchWalletBalancesTokensArray from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokensArray' interface UseFetchWalletBalancesProps { includeAlph?: boolean diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesAlph.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesAlph.ts deleted file mode 100644 index c48707e899..0000000000 --- a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesAlph.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* -Copyright 2018 - 2024 The Alephium Authors -This file is part of the alephium project. - -The library is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -The library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the library. If not, see . -*/ - -import { AddressHash } from '@alephium/shared' -import { useQueries, UseQueryResult } from '@tanstack/react-query' - -import { DataHook, SkipProp } from '@/api/apiDataHooks/apiDataHooksTypes' -import { combineError, combineIsFetching, combineIsLoading } from '@/api/apiDataHooks/apiDataHooksUtils' -import { addressAlphBalancesQuery, AddressAlphBalancesQueryFnData } from '@/api/queries/addressQueries' -import { useAppSelector } from '@/hooks/redux' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' -import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' -import { DisplayBalances } from '@/types/tokens' - -// Using undefined to avoid adding noUncheckedIndexedAccess in tsconfig while maintaining strong typing when accessing -// values through indexes, ie: alphBalances[addressHash] -export interface AddressesAlphBalances { - data: Record - isLoading: boolean -} - -export const useFetchWalletBalancesAlphArray = (props?: SkipProp) => - useFetchWalletBalancesAlph({ combine: combineBalances, skip: props?.skip }) - -export const useFetchWalletBalancesAlphByAddress = (props?: SkipProp) => - useFetchWalletBalancesAlph({ combine: combineBalancesByAddress, skip: props?.skip }) - -interface UseFetchWalletBalancesAlphProps extends SkipProp { - combine: (results: UseQueryResult[]) => { - data: T - isLoading: boolean - isFetching?: boolean - error?: boolean - } -} - -const useFetchWalletBalancesAlph = ({ combine, skip }: UseFetchWalletBalancesAlphProps) => { - const networkId = useAppSelector(selectCurrentlyOnlineNetworkId) - const allAddressHashes = useUnsortedAddressesHashes() - - const { data, isLoading, isFetching, error } = useQueries({ - queries: allAddressHashes.map((addressHash) => addressAlphBalancesQuery({ addressHash, networkId, skip })), - combine - }) - - return { - data, - isLoading, - isFetching, - error - } -} - -const combineBalancesByAddress = ( - results: UseQueryResult[] -): AddressesAlphBalances => ({ - data: results.reduce( - (acc, { data }) => { - if (data) { - acc[data.addressHash] = data.balances - } - return acc - }, - {} as AddressesAlphBalances['data'] - ), - ...combineIsLoading(results) -}) - -const combineBalances = (results: UseQueryResult[]): DataHook => ({ - data: results.reduce( - (totalBalances, { data }) => { - totalBalances.totalBalance += data ? data.balances.totalBalance : BigInt(0) - totalBalances.lockedBalance += data ? data.balances.lockedBalance : BigInt(0) - totalBalances.availableBalance += data ? data.balances.availableBalance : BigInt(0) - - return totalBalances - }, - { - totalBalance: BigInt(0), - lockedBalance: BigInt(0), - availableBalance: BigInt(0) - } as DisplayBalances - ), - ...combineIsLoading(results), - ...combineIsFetching(results), - ...combineError(results) -}) diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesAlphArray.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesAlphArray.ts new file mode 100644 index 0000000000..2a4f0623dd --- /dev/null +++ b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesAlphArray.ts @@ -0,0 +1,68 @@ +/* +Copyright 2018 - 2024 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +import { UseQueryResult } from '@tanstack/react-query' + +import { combineError, combineIsFetching, combineIsLoading } from '@/api/apiDataHooks/apiDataHooksUtils' +import useFetchWalletBalancesAlph from '@/api/apiDataHooks/utils/useFetchWalletBalancesAlph' +import { ApiContextProps } from '@/api/apiTypes' +import { createDataContext } from '@/api/context/createDataContext' +import { AddressAlphBalancesQueryFnData } from '@/api/queries/addressQueries' +import { ApiBalances } from '@/types/tokens' + +const combineBalances = (results: UseQueryResult[]): ApiContextProps => ({ + data: results.reduce( + (totalBalances, { data }) => { + totalBalances.totalBalance = ( + BigInt(totalBalances.totalBalance) + BigInt(data?.balances.totalBalance ?? '0') + ).toString() + totalBalances.lockedBalance = ( + BigInt(totalBalances.lockedBalance) + BigInt(data?.balances.lockedBalance ?? '0') + ).toString() + totalBalances.availableBalance = ( + BigInt(totalBalances.availableBalance) + BigInt(data?.balances.availableBalance ?? '0') + ).toString() + + return totalBalances + }, + { + totalBalance: '0', + lockedBalance: '0', + availableBalance: '0' + } as ApiBalances + ), + ...combineIsLoading(results), + ...combineIsFetching(results), + ...combineError(results) +}) + +const { + useData: useFetchWalletBalancesAlphArray, + DataContextProvider: UseFetchWalletBalancesAlphArrayContextProvider +} = createDataContext({ + useDataHook: useFetchWalletBalancesAlph, + combineFn: combineBalances, + defaultValue: { + totalBalance: '0', + lockedBalance: '0', + availableBalance: '0' + } +}) + +export default useFetchWalletBalancesAlphArray +export { UseFetchWalletBalancesAlphArrayContextProvider } diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesAlphByAddress.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesAlphByAddress.ts new file mode 100644 index 0000000000..ba96983aa5 --- /dev/null +++ b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesAlphByAddress.ts @@ -0,0 +1,58 @@ +/* +Copyright 2018 - 2024 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +import { AddressHash } from '@alephium/shared' +import { UseQueryResult } from '@tanstack/react-query' + +import { combineIsLoading } from '@/api/apiDataHooks/apiDataHooksUtils' +import useFetchWalletBalancesAlph from '@/api/apiDataHooks/utils/useFetchWalletBalancesAlph' +import { ApiContextProps } from '@/api/apiTypes' +import { createDataContext } from '@/api/context/createDataContext' +import { AddressAlphBalancesQueryFnData } from '@/api/queries/addressQueries' +import { ApiBalances } from '@/types/tokens' + +// Using undefined to avoid adding noUncheckedIndexedAccess in tsconfig while maintaining strong typing when accessing +// values through indexes, ie: alphBalances[addressHash] +type AddressesAlphBalances = ApiContextProps> + +const combineBalancesByAddress = ( + results: UseQueryResult[] +): AddressesAlphBalances => ({ + data: results.reduce( + (acc, { data }) => { + if (data) { + acc[data.addressHash] = data.balances + } + return acc + }, + {} as AddressesAlphBalances['data'] + ), + ...combineIsLoading(results) +}) + +const { + useData: useFetchWalletBalancesAlphByAddress, + DataContextProvider: UseFetchWalletBalancesAlphByAddressContextProvider +} = createDataContext({ + useDataHook: useFetchWalletBalancesAlph, + combineFn: combineBalancesByAddress, + defaultValue: {} +}) + +export default useFetchWalletBalancesAlphByAddress +export { UseFetchWalletBalancesAlphByAddressContextProvider } diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokens.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokens.ts deleted file mode 100644 index 0bd739d927..0000000000 --- a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokens.ts +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright 2018 - 2024 The Alephium Authors -This file is part of the alephium project. - -The library is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -The library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with the library. If not, see . -*/ - -import { AddressHash } from '@alephium/shared' -import { useQueries, UseQueryResult } from '@tanstack/react-query' - -import { combineError, combineIsFetching, combineIsLoading } from '@/api/apiDataHooks/apiDataHooksUtils' -import { addressTokensBalancesQuery, AddressTokensBalancesQueryFnData } from '@/api/queries/addressQueries' -import { useAppSelector } from '@/hooks/redux' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' -import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' -import { DisplayBalances, TokenDisplayBalances, TokenId } from '@/types/tokens' - -export const useFetchWalletBalancesTokensArray = () => useFetchWalletBalancesTokens(combineBalancesToArray) - -export const useFetchWalletBalancesTokensByToken = () => useFetchWalletBalancesTokens(combineBalancesByToken) - -export const useFetchWalletBalancesTokensByAddress = () => useFetchWalletBalancesTokens(combineBalancesByAddress) - -const useFetchWalletBalancesTokens = ( - combine: (results: UseQueryResult[]) => { - data: T - isLoading: boolean - isFetching?: boolean - error?: boolean - } -) => { - const networkId = useAppSelector(selectCurrentlyOnlineNetworkId) - const allAddressHashes = useUnsortedAddressesHashes() - - const { data, isLoading, isFetching, error } = useQueries({ - queries: allAddressHashes.map((addressHash) => addressTokensBalancesQuery({ addressHash, networkId })), - combine - }) - - return { - data, - isLoading, - isFetching, - error - } -} - -const combineBalancesByToken = (results: UseQueryResult[]) => ({ - data: results.reduce( - (tokensBalances, { data: balances }) => { - balances?.balances.forEach(({ id, totalBalance, lockedBalance, availableBalance }) => { - tokensBalances[id] = { - totalBalance: totalBalance + (tokensBalances[id]?.totalBalance ?? BigInt(0)), - lockedBalance: lockedBalance + (tokensBalances[id]?.lockedBalance ?? BigInt(0)), - availableBalance: availableBalance + (tokensBalances[id]?.availableBalance ?? BigInt(0)) - } - }) - return tokensBalances - }, - {} as Record - ), - ...combineIsLoading(results), - ...combineIsFetching(results), - ...combineError(results) -}) - -const combineBalancesByAddress = (results: UseQueryResult[]) => ({ - data: results.reduce( - (acc, { data }) => { - if (data) { - acc[data.addressHash] = data.balances - } - return acc - }, - {} as Record - ), - ...combineIsLoading(results) -}) - -const combineBalancesToArray = (results: UseQueryResult[]) => { - const { data: tokenBalancesByToken, isLoading, isFetching, error } = combineBalancesByToken(results) - - return { - data: Object.keys(tokenBalancesByToken).map((id) => ({ - id, - ...tokenBalancesByToken[id] - })) as TokenDisplayBalances[], - isLoading, - isFetching, - error - } -} diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokensArray.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokensArray.ts new file mode 100644 index 0000000000..56cbd0b11d --- /dev/null +++ b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokensArray.ts @@ -0,0 +1,62 @@ +/* +Copyright 2018 - 2024 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ +import { UseQueryResult } from '@tanstack/react-query' + +import { combineError, combineIsFetching, combineIsLoading } from '@/api/apiDataHooks/apiDataHooksUtils' +import { useFetchWalletBalancesTokens } from '@/api/apiDataHooks/utils/useFetchWalletBalancesTokens' +import { createDataContext } from '@/api/context/createDataContext' +import { AddressTokensBalancesQueryFnData } from '@/api/queries/addressQueries' +import { ApiBalances, TokenApiBalances, TokenId } from '@/types/tokens' + +const combineBalancesToArray = (results: UseQueryResult[]) => { + const tokenBalancesByToken = results.reduce( + (tokensBalances, { data: balances }) => { + balances?.balances.forEach(({ id, totalBalance, lockedBalance, availableBalance }) => { + tokensBalances[id] = { + totalBalance: (BigInt(totalBalance) + BigInt(tokensBalances[id]?.totalBalance ?? 0)).toString(), + lockedBalance: (BigInt(lockedBalance) + BigInt(tokensBalances[id]?.lockedBalance ?? 0)).toString(), + availableBalance: (BigInt(availableBalance) + BigInt(tokensBalances[id]?.availableBalance ?? 0)).toString() + } + }) + return tokensBalances + }, + {} as Record + ) + + return { + data: Object.keys(tokenBalancesByToken).map((id) => ({ + id, + ...tokenBalancesByToken[id] + })) as TokenApiBalances[], + ...combineIsLoading(results), + ...combineIsFetching(results), + ...combineError(results) + } +} + +const { + useData: useFetchWalletBalancesTokensArray, + DataContextProvider: UseFetchWalletBalancesTokensArrayContextProvider +} = createDataContext({ + useDataHook: useFetchWalletBalancesTokens, + combineFn: combineBalancesToArray, + defaultValue: [] +}) + +export default useFetchWalletBalancesTokensArray +export { UseFetchWalletBalancesTokensArrayContextProvider } diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress.ts new file mode 100644 index 0000000000..19c69973eb --- /dev/null +++ b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress.ts @@ -0,0 +1,56 @@ +/* +Copyright 2018 - 2024 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +import { AddressHash } from '@alephium/shared' +import { UseQueryResult } from '@tanstack/react-query' + +import { combineIsLoading } from '@/api/apiDataHooks/apiDataHooksUtils' +import { useFetchWalletBalancesTokens } from '@/api/apiDataHooks/utils/useFetchWalletBalancesTokens' +import { ApiContextProps } from '@/api/apiTypes' +import { createDataContext } from '@/api/context/createDataContext' +import { AddressTokensBalancesQueryFnData } from '@/api/queries/addressQueries' +import { TokenApiBalances } from '@/types/tokens' + +type AddressesTokensBalances = ApiContextProps> + +const combineBalancesByAddress = ( + results: UseQueryResult[] +): AddressesTokensBalances => ({ + data: results.reduce( + (acc, { data }) => { + if (data) { + acc[data.addressHash] = data.balances + } + return acc + }, + {} as AddressesTokensBalances['data'] + ), + ...combineIsLoading(results) +}) + +const { + useData: useFetchWalletBalancesTokensByAddress, + DataContextProvider: UseFetchWalletBalancesTokensByAddressContextProvider +} = createDataContext({ + useDataHook: useFetchWalletBalancesTokens, + combineFn: combineBalancesByAddress, + defaultValue: {} +}) + +export default useFetchWalletBalancesTokensByAddress +export { UseFetchWalletBalancesTokensByAddressContextProvider } diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletSingleTokenBalances.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletSingleTokenBalances.ts index ce1baf109b..e904af31e5 100644 --- a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletSingleTokenBalances.ts +++ b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletSingleTokenBalances.ts @@ -22,12 +22,12 @@ import { useMemo } from 'react' import { SkipProp } from '@/api/apiDataHooks/apiDataHooksTypes' import { combineIsLoading } from '@/api/apiDataHooks/apiDataHooksUtils' -import { useFetchWalletBalancesAlphArray } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlph' +import useFetchWalletBalancesAlphArray from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphArray' import { addressTokensBalancesQuery, AddressTokensBalancesQueryFnData } from '@/api/queries/addressQueries' import { useAppSelector } from '@/hooks/redux' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' -import { DisplayBalances, TokenId } from '@/types/tokens' +import { ApiBalances, TokenId } from '@/types/tokens' interface UseFetchWalletSingleTokenBalancesProps extends SkipProp { tokenId: TokenId @@ -39,7 +39,7 @@ const useFetchWalletSingleTokenBalances = ({ tokenId, skip }: UseFetchWalletSing const isALPH = tokenId === ALPH.id - const { data: alphBalances, isLoading: isLoadingAlphBalances } = useFetchWalletBalancesAlphArray({ skip }) + const { data: alphBalances, isLoading: isLoadingAlphBalances } = useFetchWalletBalancesAlphArray() const { data: tokenBalances, isLoading: isLoadingTokenBalances } = useQueries({ queries: @@ -65,17 +65,23 @@ const combineTokenBalances = (tokenId: string, results: UseQueryResult { const balances = data?.balances.find(({ id }) => id === tokenId) - totalBalances.totalBalance += balances ? balances.totalBalance : BigInt(0) - totalBalances.lockedBalance += balances ? balances.lockedBalance : BigInt(0) - totalBalances.availableBalance += balances ? balances.availableBalance : BigInt(0) + totalBalances.totalBalance = ( + BigInt(totalBalances.totalBalance) + BigInt(balances ? balances.totalBalance : 0) + ).toString() + totalBalances.lockedBalance = ( + BigInt(totalBalances.lockedBalance) + BigInt(balances ? balances.lockedBalance : 0) + ).toString() + totalBalances.availableBalance = ( + BigInt(totalBalances.availableBalance) + BigInt(balances ? balances.availableBalance : 0) + ).toString() return totalBalances }, { - totalBalance: BigInt(0), - lockedBalance: BigInt(0), - availableBalance: BigInt(0) - } as DisplayBalances + totalBalance: '0', + lockedBalance: '0', + availableBalance: '0' + } as ApiBalances ), ...combineIsLoading(results) }) diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletTokensByType.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletTokensByType.ts index 1a3fa17d8d..e7f8a62945 100644 --- a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletTokensByType.ts +++ b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletTokensByType.ts @@ -18,8 +18,8 @@ along with the library. If not, see . import useFetchTokensSeparatedByType from '@/api/apiDataHooks/utils/useFetchTokensSeparatedByType' import useMergeAllTokensBalances from '@/api/apiDataHooks/utils/useMergeAllTokensBalances' -import { useFetchWalletBalancesAlphArray } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlph' -import { useFetchWalletBalancesTokensArray } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokens' +import useFetchWalletBalancesAlphArray from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphArray' +import useFetchWalletBalancesTokensArray from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokensArray' interface UseFetchWalletTokensByType { includeAlph: boolean diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletWorth.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletWorth.ts index 8f4e7cdfe2..b6c59b848a 100644 --- a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletWorth.ts +++ b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletWorth.ts @@ -19,8 +19,8 @@ along with the library. If not, see . import useFetchListedFtsWorth from '@/api/apiDataHooks/utils/useFetchListedFtsWorth' import useFetchTokensSeparatedByListing from '@/api/apiDataHooks/utils/useFetchTokensSeparatedByListing' import useMergeAllTokensBalances from '@/api/apiDataHooks/utils/useMergeAllTokensBalances' -import { useFetchWalletBalancesAlphArray } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlph' -import { useFetchWalletBalancesTokensArray } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokens' +import useFetchWalletBalancesAlphArray from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphArray' +import useFetchWalletBalancesTokensArray from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokensArray' const useFetchWalletWorth = () => { const { diff --git a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletWorthAlph.ts b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletWorthAlph.ts index 872e59b478..66a5ed1f77 100644 --- a/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletWorthAlph.ts +++ b/apps/desktop-wallet/src/api/apiDataHooks/wallet/useFetchWalletWorthAlph.ts @@ -21,7 +21,7 @@ import { ALPH } from '@alephium/token-list' import { useMemo } from 'react' import { useFetchTokenPrice } from '@/api/apiDataHooks/market/useFetchTokenPrices' -import { useFetchWalletBalancesAlphArray } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlph' +import useFetchWalletBalancesAlphArray from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphArray' const useFetchWalletWorthAlph = () => { const { data: alphBalances, isLoading: isLoadingAlphBalances } = useFetchWalletBalancesAlphArray() @@ -29,7 +29,7 @@ const useFetchWalletWorthAlph = () => { return { data: useMemo( - () => calculateAmountWorth(alphBalances?.totalBalance ?? BigInt(0), alphPrice ?? 0, ALPH.decimals), + () => calculateAmountWorth(BigInt(alphBalances?.totalBalance ?? 0), alphPrice ?? 0, ALPH.decimals), [alphBalances?.totalBalance, alphPrice] ), isLoading: isLoadingAlphBalances || isLoadingAlphPrice diff --git a/apps/desktop-wallet/src/api/apiTypes.ts b/apps/desktop-wallet/src/api/apiTypes.ts new file mode 100644 index 0000000000..94c3757ba9 --- /dev/null +++ b/apps/desktop-wallet/src/api/apiTypes.ts @@ -0,0 +1,24 @@ +/* +Copyright 2018 - 2024 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +export interface ApiContextProps { + data: T + isLoading: boolean + isFetching?: boolean + error?: boolean +} diff --git a/apps/desktop-wallet/src/api/context/apiContext.tsx b/apps/desktop-wallet/src/api/context/apiContext.tsx new file mode 100644 index 0000000000..1a1656b779 --- /dev/null +++ b/apps/desktop-wallet/src/api/context/apiContext.tsx @@ -0,0 +1,36 @@ +/* +Copyright 2018 - 2024 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +import { ReactNode } from 'react' + +import { UseFetchWalletBalancesAlphArrayContextProvider } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphArray' +import { UseFetchWalletBalancesAlphByAddressContextProvider } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphByAddress' +import { UseFetchWalletBalancesTokensArrayContextProvider } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokensArray' +import { UseFetchWalletBalancesTokensByAddressContextProvider } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress' +import { composeProviders } from '@/api/context/apiContextUtils' + +const Providers = composeProviders([ + UseFetchWalletBalancesTokensArrayContextProvider, + UseFetchWalletBalancesTokensByAddressContextProvider, + UseFetchWalletBalancesAlphArrayContextProvider, + UseFetchWalletBalancesAlphByAddressContextProvider +]) + +const ApiContextProvider = ({ children }: { children: ReactNode }) => {children} + +export default ApiContextProvider diff --git a/apps/desktop-wallet/src/api/context/apiContextUtils.tsx b/apps/desktop-wallet/src/api/context/apiContextUtils.tsx new file mode 100644 index 0000000000..0f9d3d5570 --- /dev/null +++ b/apps/desktop-wallet/src/api/context/apiContextUtils.tsx @@ -0,0 +1,36 @@ +/* +Copyright 2018 - 2024 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +import { ReactNode } from 'react' + +type ProviderProps = { children: ReactNode } +type ProviderComponent = FC + +export const composeProviders = (providers: ProviderComponent[]): ProviderComponent => + providers.reduce( + (AccumulatedProviders, CurrentProvider) => { + const CombinedProvider: ProviderComponent = ({ children }) => ( + + {children} + + ) + + return CombinedProvider + }, + ({ children }) => children + ) diff --git a/apps/desktop-wallet/src/api/context/createDataContext.tsx b/apps/desktop-wallet/src/api/context/createDataContext.tsx new file mode 100644 index 0000000000..f542fba3b5 --- /dev/null +++ b/apps/desktop-wallet/src/api/context/createDataContext.tsx @@ -0,0 +1,55 @@ +/* +Copyright 2018 - 2024 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +import { UseQueryResult } from '@tanstack/react-query' +import { createContext, ReactNode, useContext, useMemo } from 'react' + +import { ApiContextProps } from '@/api/apiTypes' + +type CombineFn = (results: UseQueryResult[]) => ApiContextProps + +interface CreateDataContextParams { + useDataHook: (combineFn: CombineFn) => ApiContextProps + combineFn: CombineFn + defaultValue: TData +} + +export const createDataContext = ({ + useDataHook, + combineFn, + defaultValue +}: CreateDataContextParams) => { + const DataContext = createContext>({ + data: defaultValue, + isLoading: false, + isFetching: false, + error: false + }) + + const useData = () => useContext(DataContext) + + const DataContextProvider = ({ children }: { children: ReactNode }) => { + const { data, isLoading, isFetching, error } = useDataHook(combineFn) + + const value = useMemo(() => ({ data, isLoading, isFetching, error }), [data, isLoading, isFetching, error]) + + return {children} + } + + return { useData, DataContextProvider } +} diff --git a/apps/desktop-wallet/src/api/queries/addressQueries.ts b/apps/desktop-wallet/src/api/queries/addressQueries.ts index d4ec0b4708..ef8f481aa6 100644 --- a/apps/desktop-wallet/src/api/queries/addressQueries.ts +++ b/apps/desktop-wallet/src/api/queries/addressQueries.ts @@ -22,11 +22,11 @@ import { queryOptions, skipToken } from '@tanstack/react-query' import { getQueryConfig } from '@/api/apiDataHooks/utils/getQueryConfig' import { AddressLatestTransactionQueryProps } from '@/api/queries/transactionQueries' -import { DisplayBalances, TokenDisplayBalances } from '@/types/tokens' +import { ApiBalances, TokenApiBalances } from '@/types/tokens' export type AddressAlphBalancesQueryFnData = { addressHash: AddressHash - balances: DisplayBalances + balances: ApiBalances } // Adding networkId in queryKey ensures that switching the network we get different data. @@ -46,9 +46,9 @@ export const addressAlphBalancesQuery = ({ addressHash, networkId, skip }: Addre return { addressHash, balances: { - totalBalance: BigInt(balances.balance), - lockedBalance: BigInt(balances.lockedBalance), - availableBalance: BigInt(balances.balance) - BigInt(balances.lockedBalance) + totalBalance: balances.balance, + lockedBalance: balances.lockedBalance, + availableBalance: (BigInt(balances.balance) - BigInt(balances.lockedBalance)).toString() } } } @@ -57,7 +57,7 @@ export const addressAlphBalancesQuery = ({ addressHash, networkId, skip }: Addre export type AddressTokensBalancesQueryFnData = { addressHash: AddressHash - balances: TokenDisplayBalances[] + balances: TokenApiBalances[] } export const addressTokensBalancesQuery = ({ addressHash, networkId, skip }: AddressLatestTransactionQueryProps) => @@ -70,7 +70,7 @@ export const addressTokensBalancesQuery = ({ addressHash, networkId, skip }: Add queryFn: !skip && networkId !== undefined ? async () => { - const tokenBalances = [] as TokenDisplayBalances[] + const tokenBalances = [] as TokenApiBalances[] let tokenBalancesInPage = [] as e.AddressTokenBalance[] let page = 1 @@ -86,9 +86,9 @@ export const addressTokensBalancesQuery = ({ addressHash, networkId, skip }: Add tokenBalances.push( ...tokenBalancesInPage.map((tokenBalances) => ({ id: tokenBalances.tokenId, - totalBalance: BigInt(tokenBalances.balance), - lockedBalance: BigInt(tokenBalances.lockedBalance), - availableBalance: BigInt(tokenBalances.balance) - BigInt(tokenBalances.lockedBalance) + totalBalance: tokenBalances.balance, + lockedBalance: tokenBalances.lockedBalance, + availableBalance: (BigInt(tokenBalances.balance) - BigInt(tokenBalances.lockedBalance)).toString() })) ) page += 1 diff --git a/apps/desktop-wallet/src/components/DefaultAddressSwitch.tsx b/apps/desktop-wallet/src/components/DefaultAddressSwitch.tsx index 15da31ec10..a797bfa2b0 100644 --- a/apps/desktop-wallet/src/components/DefaultAddressSwitch.tsx +++ b/apps/desktop-wallet/src/components/DefaultAddressSwitch.tsx @@ -26,7 +26,8 @@ import Button from '@/components/Button' import CheckMark from '@/components/CheckMark' import Select, { SelectOption } from '@/components/Inputs/Select' import { useAppSelector } from '@/hooks/redux' -import { selectAllAddresses, selectDefaultAddress } from '@/storage/addresses/addressesSelectors' +import { useUnsortedAddresses } from '@/hooks/useUnsortedAddresses' +import { selectDefaultAddress } from '@/storage/addresses/addressesSelectors' import { changeDefaultAddress } from '@/storage/addresses/addressesStorageUtils' interface AddressOption { @@ -36,7 +37,7 @@ interface AddressOption { const DefaultAddressSwitch = () => { const { t } = useTranslation() - const addresses = useAppSelector(selectAllAddresses) + const addresses = useUnsortedAddresses() const defaultAddress = useAppSelector(selectDefaultAddress) const addressOptions: AddressOption[] = addresses.map((address) => ({ diff --git a/apps/desktop-wallet/src/components/Inputs/SelectOptionWalletToken.tsx b/apps/desktop-wallet/src/components/Inputs/SelectOptionWalletToken.tsx index ccadc1abdc..aa02422607 100644 --- a/apps/desktop-wallet/src/components/Inputs/SelectOptionWalletToken.tsx +++ b/apps/desktop-wallet/src/components/Inputs/SelectOptionWalletToken.tsx @@ -21,16 +21,17 @@ import useFetchWalletSingleTokenBalances from '@/api/apiDataHooks/wallet/useFetc import SelectOptionToken, { SelectOptionTokenBaseProps } from '@/components/Inputs/SelectOptionToken' const SelectOptionWalletToken = ({ tokenId, ...props }: SelectOptionTokenBaseProps) => { - const { data: token, isLoading: isLoadingToken } = useFetchToken(tokenId) + const { data: token } = useFetchToken(tokenId) const { data: tokenBalances, isLoading: isLoadingTokenBalances } = useFetchWalletSingleTokenBalances({ - tokenId, - skip: isLoadingToken || isNFT(token) + tokenId }) + const amount = tokenBalances?.totalBalance ? BigInt(tokenBalances.totalBalance) : undefined + return ( . import { useMemo } from 'react' -import { useFetchWalletBalancesAlphByAddress } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlph' -import { useFetchWalletBalancesTokensByAddress } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokens' +import useFetchWalletBalancesAlphByAddress from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphByAddress' +import useFetchWalletBalancesTokensByAddress from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress' import useFetchWalletFts from '@/api/apiDataHooks/wallet/useFetchWalletFts' -import { useAppSelector } from '@/hooks/redux' import { useFetchSortedAddressesHashes } from '@/hooks/useAddresses' -import { selectAllAddresses } from '@/storage/addresses/addressesSelectors' +import { useUnsortedAddresses } from '@/hooks/useUnsortedAddresses' export const useFilterAddressesByText = (text = '') => { - const allAddresses = useAppSelector(selectAllAddresses) + const allAddresses = useUnsortedAddresses() const { data: allAddressHashes } = useFetchSortedAddressesHashes() const { listedFts, unlistedFts } = useFetchWalletFts({ sort: false }) const { data: addressesAlphBalances } = useFetchWalletBalancesAlphByAddress() @@ -48,7 +47,7 @@ export const useFilterAddressesByText = (text = '') => { // Step 3. Validate against token names const addressAlphBalances = addressesAlphBalances[addressHash] - const addressHasAlphBalances = (addressAlphBalances?.totalBalance ?? 0) > 0 + const addressHasAlphBalances = BigInt(addressAlphBalances?.totalBalance ?? 0) > 0 if (addressHasAlphBalances) { if ('alephium alph'.includes(text)) return true diff --git a/apps/desktop-wallet/src/features/assetsLists/AddressTokenBadge.tsx b/apps/desktop-wallet/src/features/assetsLists/AddressTokenBadge.tsx index 3a84a03105..6e6ac72508 100644 --- a/apps/desktop-wallet/src/features/assetsLists/AddressTokenBadge.tsx +++ b/apps/desktop-wallet/src/features/assetsLists/AddressTokenBadge.tsx @@ -36,7 +36,9 @@ const AddressTokenBadge = ({ addressHash, tokenId, ...props }: AddressTokenBadge skip: isNFT(token) || isLoadingToken }) - return + const amount = data?.totalBalance ? BigInt(data.totalBalance) : undefined + + return } export default AddressTokenBadge diff --git a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/AddressTokenBalancesRow.tsx b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/AddressTokenBalancesRow.tsx index 84aebcc10e..06c3f026e8 100644 --- a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/AddressTokenBalancesRow.tsx +++ b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/AddressTokenBalancesRow.tsx @@ -57,9 +57,11 @@ const FTAmounts = ({ tokenId, addressHash }: AddressTokenBalancesRowProps) => { tokenId }) + const amount = tokenBalances?.totalBalance ? BigInt(tokenBalances.totalBalance) : undefined + return ( - + ) } @@ -70,11 +72,14 @@ const AddressTokenBalancesRowAmounts = ({ tokenId, addressHash, children }: Addr tokenId }) + const totalBalance = tokenBalances?.totalBalance ? BigInt(tokenBalances.totalBalance) : undefined + const availableBalance = tokenBalances?.availableBalance ? BigInt(tokenBalances.availableBalance) : undefined + return ( {children} diff --git a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/WalletTokenBalancesRow.tsx b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/WalletTokenBalancesRow.tsx index ef5a3b0464..f389d89d83 100644 --- a/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/WalletTokenBalancesRow.tsx +++ b/apps/desktop-wallet/src/features/assetsLists/tokenBalanceRow/WalletTokenBalancesRow.tsx @@ -53,13 +53,11 @@ const FTAmounts = ({ tokenId }: TokenBalancesRowBaseProps) => { tokenId }) + const totalBalance = walletTokenBalances?.totalBalance ? BigInt(walletTokenBalances.totalBalance) : undefined + return ( - + ) } @@ -69,11 +67,16 @@ const WalletTokenBalancesRowAmounts = ({ tokenId, children }: TokenBalancesRowAm tokenId }) + const totalBalance = walletTokenBalances?.totalBalance ? BigInt(walletTokenBalances.totalBalance) : undefined + const availableBalance = walletTokenBalances?.availableBalance + ? BigInt(walletTokenBalances.availableBalance) + : undefined + return ( {children} diff --git a/apps/desktop-wallet/src/features/balancesOverview/TotalAlphBalance.tsx b/apps/desktop-wallet/src/features/balancesOverview/TotalAlphBalance.tsx index 39f4ab1df2..bc00865685 100644 --- a/apps/desktop-wallet/src/features/balancesOverview/TotalAlphBalance.tsx +++ b/apps/desktop-wallet/src/features/balancesOverview/TotalAlphBalance.tsx @@ -20,7 +20,7 @@ import { ALPH } from '@alephium/token-list' import { useTranslation } from 'react-i18next' import styled from 'styled-components' -import { useFetchWalletBalancesAlphArray } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlph' +import useFetchWalletBalancesAlphArray from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphArray' import Amount from '@/components/Amount' interface TotalAlphBalanceProps { @@ -46,23 +46,17 @@ const TotalAlphBalance = ({ className, type }: TotalAlphBalanceProps) => { const AvailableAlphAmount = () => { const { data, isLoading } = useFetchWalletBalancesAlphArray() - return ( - - ) + const value = data?.availableBalance ? BigInt(data.availableBalance) : undefined + + return } const LockedAlphAmount = () => { const { data, isLoading } = useFetchWalletBalancesAlphArray() - return ( - - ) + const value = data?.lockedBalance ? BigInt(data.lockedBalance) : undefined + + return } export default TotalAlphBalance diff --git a/apps/desktop-wallet/src/features/dataPolling/useAddressesDataPolling.ts b/apps/desktop-wallet/src/features/dataPolling/useAddressesDataPolling.ts index 456e905d1b..c820d0a157 100644 --- a/apps/desktop-wallet/src/features/dataPolling/useAddressesDataPolling.ts +++ b/apps/desktop-wallet/src/features/dataPolling/useAddressesDataPolling.ts @@ -21,7 +21,7 @@ import { useQueries } from '@tanstack/react-query' import { addressLatestTransactionQuery } from '@/api/queries/transactionQueries' import { useAppSelector } from '@/hooks/redux' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' const useAddressesDataPolling = () => { diff --git a/apps/desktop-wallet/src/features/dataPolling/usePendingTxPolling.ts b/apps/desktop-wallet/src/features/dataPolling/usePendingTxPolling.ts index 18f56c690b..bd284a507e 100644 --- a/apps/desktop-wallet/src/features/dataPolling/usePendingTxPolling.ts +++ b/apps/desktop-wallet/src/features/dataPolling/usePendingTxPolling.ts @@ -25,7 +25,7 @@ import queryClient from '@/api/queryClient' import { sentTransactionStatusChanged } from '@/features/send/sentTransactions/sentTransactionsActions' import { selectSentTransactionByHash } from '@/features/send/sentTransactions/sentTransactionsSelectors' import { useAppDispatch, useAppSelector } from '@/hooks/redux' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' const usePendingTxPolling = (txHash: e.Transaction['hash']) => { diff --git a/apps/desktop-wallet/src/features/historicChart/HistoricWorthChart.tsx b/apps/desktop-wallet/src/features/historicChart/HistoricWorthChart.tsx index ea91b3660a..b1a14a5f04 100644 --- a/apps/desktop-wallet/src/features/historicChart/HistoricWorthChart.tsx +++ b/apps/desktop-wallet/src/features/historicChart/HistoricWorthChart.tsx @@ -28,7 +28,7 @@ import { ChartLength, DataPoint, LatestAmountPerAddress } from '@/features/histo import { getChartOptions, getFilteredChartData } from '@/features/historicChart/historicChartUtils' import useHistoricData from '@/features/historicChart/useHistoricData' import { useAppSelector } from '@/hooks/redux' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' interface HistoricWorthChartProps { onDataPointHover: (dataPoint?: DataPoint) => void diff --git a/apps/desktop-wallet/src/features/refreshData/useRefreshBalances.ts b/apps/desktop-wallet/src/features/refreshData/useRefreshBalances.ts index 72257ee649..8e6feacb80 100644 --- a/apps/desktop-wallet/src/features/refreshData/useRefreshBalances.ts +++ b/apps/desktop-wallet/src/features/refreshData/useRefreshBalances.ts @@ -20,7 +20,7 @@ import { useIsFetching } from '@tanstack/react-query' import { useCallback } from 'react' import queryClient from '@/api/queryClient' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' const useRefreshBalances = () => { const addressHashes = useUnsortedAddressesHashes() diff --git a/apps/desktop-wallet/src/features/send/SelectOptionAddressToken.tsx b/apps/desktop-wallet/src/features/send/SelectOptionAddressToken.tsx index db0f743d10..f3b8100e8d 100644 --- a/apps/desktop-wallet/src/features/send/SelectOptionAddressToken.tsx +++ b/apps/desktop-wallet/src/features/send/SelectOptionAddressToken.tsx @@ -34,10 +34,12 @@ const SelectOptionAddressToken = ({ tokenId, addressHash, ...props }: SelectOpti skip: isLoadingToken || isNFT(token) }) + const amount = tokenBalances?.totalBalance ? BigInt(tokenBalances.totalBalance) : undefined + return ( selectedTokenId === id) ?? unlistedFts.find(({ id }) => selectedTokenId === id) const availableAmount = toHumanReadableAmount( - selectedTokenBalances.availableBalance ?? BigInt(0), + BigInt(selectedTokenBalances.availableBalance ?? 0), ft?.decimals ?? 0 ) @@ -203,7 +203,7 @@ const TokensAmountInputs = ({ // TODO: If ALPH, subtract dust for each other token, possibly by querying the node `/addresses/{address}/utxos` const availableHumanReadableAmount = toHumanReadableAmount( - tokenBalances.availableBalance ?? BigInt(0), + BigInt(tokenBalances.availableBalance ?? 0), ft?.decimals ?? 0 ) @@ -255,7 +255,7 @@ const TokensAmountInputs = ({ { try { - setIsAmountValid(!alphAmount || isAmountWithinRange(fromHumanReadableAmount(alphAmount), availableBalance)) + setIsAmountValid( + !alphAmount || isAmountWithinRange(fromHumanReadableAmount(alphAmount), BigInt(availableBalance)) + ) } catch (error) { sendAnalytics({ type: 'error', error, message: 'Could not determine if amount is valid' }) } diff --git a/apps/desktop-wallet/src/features/send/sendModals/deployContract/BuildTxModalContent.tsx b/apps/desktop-wallet/src/features/send/sendModals/deployContract/BuildTxModalContent.tsx index 7d682b72d4..9b4dcfcee5 100644 --- a/apps/desktop-wallet/src/features/send/sendModals/deployContract/BuildTxModalContent.tsx +++ b/apps/desktop-wallet/src/features/send/sendModals/deployContract/BuildTxModalContent.tsx @@ -78,7 +78,7 @@ const DeployContractBuildTxModalContent = ({ data, onSubmit, onCancel }: DeployC !gasPriceError && !gasAmountError && !!bytecode && - (!alphAsset.amount || isAmountWithinRange(alphAsset.amount, availableBalance)) + (!alphAsset.amount || isAmountWithinRange(alphAsset.amount, BigInt(availableBalance))) return ( <> diff --git a/apps/desktop-wallet/src/features/send/sendUtils.ts b/apps/desktop-wallet/src/features/send/sendUtils.ts index bcf0a5af62..85837dd2cd 100644 --- a/apps/desktop-wallet/src/features/send/sendUtils.ts +++ b/apps/desktop-wallet/src/features/send/sendUtils.ts @@ -20,7 +20,7 @@ import { AssetAmount } from '@alephium/shared' import { ALPH } from '@alephium/token-list' import { DUST_AMOUNT, MIN_UTXO_SET_AMOUNT } from '@alephium/web3' -import { TokenDisplayBalances } from '@/types/tokens' +import { TokenApiBalances } from '@/types/tokens' export const getTransactionAssetAmounts = (assetAmounts: AssetAmount[]) => { const alphAmount = assetAmounts.find((asset) => asset.id === ALPH.id)?.amount ?? BigInt(0) @@ -43,6 +43,10 @@ export const getOptionalTransactionAssetAmounts = (assetAmounts?: AssetAmount[]) export const isAmountWithinRange = (amount: bigint, maxAmount: bigint): boolean => amount >= MIN_UTXO_SET_AMOUNT && amount <= maxAmount -export const shouldBuildSweepTransactions = (assetAmounts: AssetAmount[], tokensBalances: TokenDisplayBalances[]) => +export const shouldBuildSweepTransactions = (assetAmounts: AssetAmount[], tokensBalances: TokenApiBalances[]) => assetAmounts.length === tokensBalances.length && - tokensBalances.every(({ id, totalBalance }) => totalBalance === assetAmounts.find((asset) => asset.id === id)?.amount) + tokensBalances.every(({ id, totalBalance }) => { + const assetAmount = assetAmounts.find((asset) => asset.id === id) + + return totalBalance === (assetAmount?.amount ?? 0).toString() + }) diff --git a/apps/desktop-wallet/src/features/send/useAreAmountsWithinAddressAvailableBalances.ts b/apps/desktop-wallet/src/features/send/useAreAmountsWithinAddressAvailableBalances.ts index 43773b2e9d..bf73b6d85e 100644 --- a/apps/desktop-wallet/src/features/send/useAreAmountsWithinAddressAvailableBalances.ts +++ b/apps/desktop-wallet/src/features/send/useAreAmountsWithinAddressAvailableBalances.ts @@ -34,7 +34,7 @@ const useAreAmountsWithinAddressAvailableBalances = ( return amountsWithBalance.every(({ id, amount }) => { const balances = addressTokensBalances.find((token) => token.id === id) - return !amount ? true : !balances ? false : amount <= balances.availableBalance + return !amount ? true : !balances ? false : amount <= BigInt(balances.availableBalance) }) } diff --git a/apps/desktop-wallet/src/features/transactionsDisplay/transactionDetailsModal/TransactionDetailsModal.tsx b/apps/desktop-wallet/src/features/transactionsDisplay/transactionDetailsModal/TransactionDetailsModal.tsx index 7b3a42e9d6..d6428f4dc4 100644 --- a/apps/desktop-wallet/src/features/transactionsDisplay/transactionDetailsModal/TransactionDetailsModal.tsx +++ b/apps/desktop-wallet/src/features/transactionsDisplay/transactionDetailsModal/TransactionDetailsModal.tsx @@ -42,7 +42,7 @@ import NFTsDataListRow from '@/features/transactionsDisplay/transactionDetailsMo import NSTsDataListRow from '@/features/transactionsDisplay/transactionDetailsModal/NSTsDataListRow' import TransactionType from '@/features/transactionsDisplay/transactionDetailsModal/TransactionType' import useOpenTxInExplorer from '@/features/transactionsDisplay/transactionDetailsModal/useOpenTxInExplorer' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' import SideModal from '@/modals/SideModal' import { formatDateForDisplay } from '@/utils/misc' diff --git a/apps/desktop-wallet/src/features/transactionsDisplay/transactionDetailsModal/useOnAddressClick.ts b/apps/desktop-wallet/src/features/transactionsDisplay/transactionDetailsModal/useOnAddressClick.ts index aba493bce7..855c0dbdc7 100644 --- a/apps/desktop-wallet/src/features/transactionsDisplay/transactionDetailsModal/useOnAddressClick.ts +++ b/apps/desktop-wallet/src/features/transactionsDisplay/transactionDetailsModal/useOnAddressClick.ts @@ -20,7 +20,7 @@ import { AddressHash } from '@alephium/shared' import { openModal } from '@/features/modals/modalActions' import { useAppDispatch, useAppSelector } from '@/hooks/redux' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' import { openInWebBrowser } from '@/utils/misc' const useOnAddressClick = () => { diff --git a/apps/desktop-wallet/src/features/transactionsDisplay/transactionLists/lists/WalletTransactionsList.tsx b/apps/desktop-wallet/src/features/transactionsDisplay/transactionLists/lists/WalletTransactionsList.tsx index 7aab53df5f..da016d03ff 100644 --- a/apps/desktop-wallet/src/features/transactionsDisplay/transactionLists/lists/WalletTransactionsList.tsx +++ b/apps/desktop-wallet/src/features/transactionsDisplay/transactionLists/lists/WalletTransactionsList.tsx @@ -33,7 +33,7 @@ import TableRowsLoader from '@/features/transactionsDisplay/transactionLists/Tab import TransactionsListFooter from '@/features/transactionsDisplay/transactionLists/TransactionsListFooter' import TransactionRow from '@/features/transactionsDisplay/transactionRow/TransactionRow' import { useAppDispatch } from '@/hooks/redux' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' import { Direction } from '@/types/transactions' import { onEnterOrSpace } from '@/utils/misc' diff --git a/apps/desktop-wallet/src/features/transactionsDisplay/transactionRow/TransactionRow.tsx b/apps/desktop-wallet/src/features/transactionsDisplay/transactionRow/TransactionRow.tsx index cb3b7ea0d4..a428993fbd 100644 --- a/apps/desktop-wallet/src/features/transactionsDisplay/transactionRow/TransactionRow.tsx +++ b/apps/desktop-wallet/src/features/transactionsDisplay/transactionRow/TransactionRow.tsx @@ -30,7 +30,7 @@ import OtherAmounts from '@/features/transactionsDisplay/transactionRow/OtherAmo import SecondAddressColumnCell from '@/features/transactionsDisplay/transactionRow/SecondAddressColumnCell' import TokenBadgesListCell from '@/features/transactionsDisplay/transactionRow/TokenBadgesListCell' import { TransactionRowProps } from '@/features/transactionsDisplay/transactionRow/types' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' const TransactionRow = memo( ({ tx, refAddressHash, isInAddressDetailsModal, compact, ...props }: TransactionRowProps) => { diff --git a/apps/desktop-wallet/src/features/transactionsDisplay/useTransactionDirection.ts b/apps/desktop-wallet/src/features/transactionsDisplay/useTransactionDirection.ts index 78f18dd446..eef69dc7a9 100644 --- a/apps/desktop-wallet/src/features/transactionsDisplay/useTransactionDirection.ts +++ b/apps/desktop-wallet/src/features/transactionsDisplay/useTransactionDirection.ts @@ -28,7 +28,7 @@ import { useMemo } from 'react' import { selectPendingSentTransactionByHash } from '@/features/send/sentTransactions/sentTransactionsSelectors' import { useAppSelector } from '@/hooks/redux' -import { useUnsortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' const useTransactionDirection = ( tx: e.Transaction | e.PendingTransaction, diff --git a/apps/desktop-wallet/src/features/walletConnect/WalletConnectSessionRequestEventHandler.tsx b/apps/desktop-wallet/src/features/walletConnect/WalletConnectSessionRequestEventHandler.tsx index 1762c4a48f..3fd14dd3e0 100644 --- a/apps/desktop-wallet/src/features/walletConnect/WalletConnectSessionRequestEventHandler.tsx +++ b/apps/desktop-wallet/src/features/walletConnect/WalletConnectSessionRequestEventHandler.tsx @@ -37,8 +37,8 @@ import { calcExpiry, getSdkError } from '@walletconnect/utils' import { partition } from 'lodash' import { useCallback, useEffect } from 'react' -import { useFetchWalletBalancesAlphByAddress } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlph' -import { useFetchWalletBalancesTokensByAddress } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokens' +import useFetchWalletBalancesAlphByAddress from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphByAddress' +import useFetchWalletBalancesTokensByAddress from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress' import useAnalytics from '@/features/analytics/useAnalytics' import { openModal } from '@/features/modals/modalActions' import { CallContractTxData, DeployContractTxData, TransferTxData } from '@/features/send/sendTypes' @@ -46,8 +46,8 @@ import { shouldBuildSweepTransactions } from '@/features/send/sendUtils' import { useWalletConnectContext } from '@/features/walletConnect/walletConnectContext' import { SignMessageData, SignUnsignedTxData } from '@/features/walletConnect/walletConnectTypes' import { cleanHistory, cleanMessages } from '@/features/walletConnect/walletConnectUtils' -import { useAppDispatch, useAppSelector } from '@/hooks/redux' -import { selectAllAddresses } from '@/storage/addresses/addressesSelectors' +import { useAppDispatch } from '@/hooks/redux' +import { useUnsortedAddresses } from '@/hooks/useUnsortedAddresses' import { toggleAppLoading } from '@/storage/global/globalActions' // The purpose of this component is to conditionally use the useFetch hooks only when a wallet is unlocked. That's why @@ -64,7 +64,7 @@ const WalletConnectSessionRequestEventHandler = ({ const { data: alphBalancesByAddress, isLoading: isLoadingAlphBalances } = useFetchWalletBalancesAlphByAddress() const { data: tokensBalancesByAddress, isLoading: isLoadingTokensBalances } = useFetchWalletBalancesTokensByAddress() const { walletConnectClient, respondToWalletConnectWithError, respondToWalletConnect } = useWalletConnectContext() - const addresses = useAppSelector(selectAllAddresses) + const addresses = useUnsortedAddresses() const dispatch = useAppDispatch() const { sendAnalytics } = useAnalytics() diff --git a/apps/desktop-wallet/src/hooks/useAddressGeneration.tsx b/apps/desktop-wallet/src/hooks/useAddressGeneration.tsx index 7f67f4a48a..6d495c72ce 100644 --- a/apps/desktop-wallet/src/hooks/useAddressGeneration.tsx +++ b/apps/desktop-wallet/src/hooks/useAddressGeneration.tsx @@ -26,14 +26,14 @@ import { discoverAndCacheActiveAddresses } from '@/api/addresses' import useAnalytics from '@/features/analytics/useAnalytics' import { useLedger } from '@/features/ledger/useLedger' import { generateLedgerAddressesFromMetadata, LedgerAlephium } from '@/features/ledger/utils' -import { useAppDispatch, useAppSelector } from '@/hooks/redux' +import { useAppDispatch } from '@/hooks/redux' +import { useUnsortedAddresses } from '@/hooks/useUnsortedAddresses' import { addressDiscoveryFinished, addressDiscoveryStarted, addressesRestoredFromMetadata, addressRestorationStarted } from '@/storage/addresses/addressesActions' -import { selectAllAddresses } from '@/storage/addresses/addressesSelectors' import { saveNewAddresses } from '@/storage/addresses/addressesStorageUtils' import { addressMetadataStorage } from '@/storage/addresses/addressMetadataPersistentStorage' import { showToast } from '@/storage/global/globalActions' @@ -60,7 +60,7 @@ interface GenerateOneAddressPerGroupProps { const useAddressGeneration = () => { const dispatch = useAppDispatch() - const addresses = useAppSelector(selectAllAddresses) + const addresses = useUnsortedAddresses() const { sendAnalytics } = useAnalytics() const { isLedger, onLedgerError } = useLedger() const { t } = useTranslation() diff --git a/apps/desktop-wallet/src/hooks/useAddresses.ts b/apps/desktop-wallet/src/hooks/useAddresses.ts index 8e82c82b77..448abede2d 100644 --- a/apps/desktop-wallet/src/hooks/useAddresses.ts +++ b/apps/desktop-wallet/src/hooks/useAddresses.ts @@ -16,19 +16,18 @@ You should have received a copy of the GNU Lesser General Public License along with the library. If not, see . */ -import { ADDRESSES_QUERY_LIMIT, AddressHash } from '@alephium/shared' +import { ADDRESSES_QUERY_LIMIT } from '@alephium/shared' import { orderBy } from 'lodash' import { useMemo } from 'react' import { SkipProp } from '@/api/apiDataHooks/apiDataHooksTypes' import useFetchLatestTransactionOfEachAddress from '@/api/apiDataHooks/wallet/useFetchLatestTransactionOfEachAddress' -import { useFetchWalletBalancesAlphByAddress } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlph' +import useFetchWalletBalancesAlphByAddress from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphByAddress' import { useAppSelector } from '@/hooks/redux' -import { selectAllAddressHashes, selectDefaultAddress } from '@/storage/addresses/addressesSelectors' +import { useUnsortedAddressesHashes } from '@/hooks/useUnsortedAddresses' +import { selectDefaultAddress } from '@/storage/addresses/addressesSelectors' import { selectCurrentlyOnlineNetworkId } from '@/storage/network/networkSelectors' -export const useUnsortedAddressesHashes = (): AddressHash[] => useAppSelector(selectAllAddressHashes) - export const useFetchSortedAddressesHashes = (props?: SkipProp) => { const isNetworkOffline = useAppSelector(selectCurrentlyOnlineNetworkId) === undefined const allAddressHashes = useUnsortedAddressesHashes() @@ -92,7 +91,8 @@ export const useFetchAddressesHashesWithBalance = () => { isNetworkOffline ? allAddressHashes : allAddressHashes.filter( - (addressHash) => addressesAlphBalances[addressHash] && addressesAlphBalances[addressHash].totalBalance > 0 + (addressHash) => + addressesAlphBalances[addressHash] && addressesAlphBalances[addressHash].totalBalance !== '0' ), [addressesAlphBalances, allAddressHashes, isNetworkOffline] ) diff --git a/apps/desktop-wallet/src/hooks/useUnsortedAddresses.ts b/apps/desktop-wallet/src/hooks/useUnsortedAddresses.ts new file mode 100644 index 0000000000..6545563937 --- /dev/null +++ b/apps/desktop-wallet/src/hooks/useUnsortedAddresses.ts @@ -0,0 +1,27 @@ +/* +Copyright 2018 - 2024 The Alephium Authors +This file is part of the alephium project. + +The library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the library. If not, see . +*/ + +import { AddressHash } from '@alephium/shared' + +import { useAppSelector } from '@/hooks/redux' +import { selectAllAddresses, selectAllAddressHashes } from '@/storage/addresses/addressesSelectors' +import { Address } from '@/types/addresses' + +export const useUnsortedAddressesHashes = (): AddressHash[] => useAppSelector(selectAllAddressHashes) + +export const useUnsortedAddresses = (): Address[] => useAppSelector(selectAllAddresses) diff --git a/apps/desktop-wallet/src/index.tsx b/apps/desktop-wallet/src/index.tsx index 7e128c65b6..76176436ac 100644 --- a/apps/desktop-wallet/src/index.tsx +++ b/apps/desktop-wallet/src/index.tsx @@ -28,6 +28,7 @@ import { Provider } from 'react-redux' import { HashRouter as Router } from 'react-router-dom' import { StyleSheetManager } from 'styled-components' +import ApiContextProvider from '@/api/context/apiContext' import { PersistQueryClientContextProvider } from '@/api/persistQueryClientContext' import App from '@/App' import Tooltips from '@/components/Tooltips' @@ -48,7 +49,9 @@ ReactDOM.render( - + + + diff --git a/apps/desktop-wallet/src/modals/AddressOptionsModal.tsx b/apps/desktop-wallet/src/modals/AddressOptionsModal.tsx index e318f096c9..30bb83971a 100644 --- a/apps/desktop-wallet/src/modals/AddressOptionsModal.tsx +++ b/apps/desktop-wallet/src/modals/AddressOptionsModal.tsx @@ -33,8 +33,9 @@ import useAnalytics from '@/features/analytics/useAnalytics' import { closeModal, openModal } from '@/features/modals/modalActions' import { AddressModalProps } from '@/features/modals/modalTypes' import { useAppDispatch, useAppSelector } from '@/hooks/redux' +import { useUnsortedAddresses } from '@/hooks/useUnsortedAddresses' import CenteredModal, { ModalFooterButton, ModalFooterButtons } from '@/modals/CenteredModal' -import { selectAddressByHash, selectAllAddresses, selectDefaultAddress } from '@/storage/addresses/addressesSelectors' +import { selectAddressByHash, selectDefaultAddress } from '@/storage/addresses/addressesSelectors' import { saveAddressSettings } from '@/storage/addresses/addressesStorageUtils' import { getName } from '@/utils/addresses' import { getRandomLabelColor } from '@/utils/colors' @@ -45,7 +46,7 @@ const AddressOptionsModal = memo(({ id, addressHash }: AddressModalProps) => { const { sendAnalytics } = useAnalytics() const isPassphraseUsed = useAppSelector((state) => state.activeWallet.isPassphraseUsed) const defaultAddress = useAppSelector(selectDefaultAddress) - const addresses = useAppSelector(selectAllAddresses) + const addresses = useUnsortedAddresses() const address = useAppSelector((s) => selectAddressByHash(s, addressHash)) const activeWalletId = useAppSelector((s) => s.activeWallet.id) const dispatch = useAppDispatch() @@ -62,7 +63,7 @@ const AddressOptionsModal = memo(({ id, addressHash }: AddressModalProps) => { const availableBalance = addressAlphBalances?.availableBalance const isDefaultAddressToggleEnabled = defaultAddress.hash !== address.hash - const isSweepButtonEnabled = addresses.length > 1 && availableBalance !== undefined && availableBalance > 0 + const isSweepButtonEnabled = addresses.length > 1 && availableBalance !== undefined && availableBalance !== '0' const onClose = () => dispatch(closeModal({ id })) @@ -136,7 +137,8 @@ const AddressOptionsModal = memo(({ id, addressHash }: AddressModalProps) => { {availableBalance !== undefined && ( - {t('Available')}: + {t('Available')}:{' '} + )} diff --git a/apps/desktop-wallet/src/modals/AddressSelectModal.tsx b/apps/desktop-wallet/src/modals/AddressSelectModal.tsx index 368a8b7c7f..d4709319ac 100644 --- a/apps/desktop-wallet/src/modals/AddressSelectModal.tsx +++ b/apps/desktop-wallet/src/modals/AddressSelectModal.tsx @@ -20,15 +20,14 @@ import { AddressHash } from '@alephium/shared' import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' -import { useFetchWalletBalancesAlphByAddress } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlph' -import { useFetchWalletBalancesTokensByAddress } from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokens' +import useFetchWalletBalancesAlphByAddress from '@/api/apiDataHooks/wallet/useFetchWalletBalancesAlphByAddress' +import useFetchWalletBalancesTokensByAddress from '@/api/apiDataHooks/wallet/useFetchWalletBalancesTokensByAddress' import useFetchWalletFts from '@/api/apiDataHooks/wallet/useFetchWalletFts' import useFetchWalletNftsSearchStrings from '@/api/apiDataHooks/wallet/useFetchWalletNftsSearchStrings' import { SelectOption, SelectOptionsModal } from '@/components/Inputs/Select' import SelectOptionAddress from '@/components/Inputs/SelectOptionAddress' -import { useAppSelector } from '@/hooks/redux' import { useFetchSortedAddressesHashes } from '@/hooks/useAddresses' -import { selectAllAddresses } from '@/storage/addresses/addressesSelectors' +import { useUnsortedAddresses } from '@/hooks/useUnsortedAddresses' interface AddressSelectModalProps { title: string @@ -88,7 +87,7 @@ export default AddressSelectModal // TODO: See how it can be DRY'ed with useFilterAddressesByText const useAddressSelectOptions = (addressOptions: AddressHash[]) => { - const addresses = useAppSelector(selectAllAddresses) + const addresses = useUnsortedAddresses() const { data: sortedAddressHashes } = useFetchSortedAddressesHashes() const { listedFts, unlistedFts } = useFetchWalletFts({ sort: false }) const { data: nftsSearchStringsByNftId } = useFetchWalletNftsSearchStrings() @@ -102,7 +101,7 @@ const useAddressSelectOptions = (addressOptions: AddressHash[]) => { .map((hash) => { const address = addresses.find((address) => address.hash === hash) const addressAlphBalances = addressesAlphBalances[hash] - const addressHasAlphBalances = (addressAlphBalances?.totalBalance ?? 0) > 0 + const addressHasAlphBalances = addressAlphBalances?.totalBalance !== '0' const addressTokensBalances = addressesTokensBalances[hash] ?? [] const addressTokensSearchableString = addressTokensBalances .map(({ id }) => { diff --git a/apps/desktop-wallet/src/modals/AddressSweepModal.tsx b/apps/desktop-wallet/src/modals/AddressSweepModal.tsx index 904c6de9cc..757aef916b 100644 --- a/apps/desktop-wallet/src/modals/AddressSweepModal.tsx +++ b/apps/desktop-wallet/src/modals/AddressSweepModal.tsx @@ -35,8 +35,9 @@ import { closeModal } from '@/features/modals/modalActions' import { AddressModalBaseProp, ModalBaseProp } from '@/features/modals/modalTypes' import { useAppDispatch, useAppSelector } from '@/hooks/redux' import { useFetchAddressesHashesWithBalance, useFetchSortedAddressesHashes } from '@/hooks/useAddresses' +import { useUnsortedAddresses } from '@/hooks/useUnsortedAddresses' import CenteredModal, { ModalFooterButton, ModalFooterButtons } from '@/modals/CenteredModal' -import { selectAddressByHash, selectAllAddresses, selectDefaultAddress } from '@/storage/addresses/addressesSelectors' +import { selectAddressByHash, selectDefaultAddress } from '@/storage/addresses/addressesSelectors' import { transactionBuildFailed, transactionSendFailed, @@ -54,7 +55,7 @@ const AddressSweepModal = memo( ({ id, addressHash, onSuccessfulSweep, isUtxoConsolidation }: ModalBaseProp & AddressSweepModalProps) => { const { t } = useTranslation() const dispatch = useAppDispatch() - const addresses = useAppSelector(selectAllAddresses) + const addresses = useUnsortedAddresses() const { data: allAddressHashes } = useFetchSortedAddressesHashes() const { sendAnalytics } = useAnalytics() const fromAddress = useAppSelector((s) => selectAddressByHash(s, addressHash)) diff --git a/apps/desktop-wallet/src/modals/SettingsModal/DevToolsSettingsSection.tsx b/apps/desktop-wallet/src/modals/SettingsModal/DevToolsSettingsSection.tsx index 46ef951b83..d9588c8731 100644 --- a/apps/desktop-wallet/src/modals/SettingsModal/DevToolsSettingsSection.tsx +++ b/apps/desktop-wallet/src/modals/SettingsModal/DevToolsSettingsSection.tsx @@ -36,14 +36,15 @@ import { useLedger } from '@/features/ledger/useLedger' import { openModal } from '@/features/modals/modalActions' import { devToolsToggled } from '@/features/settings/settingsActions' import { useAppDispatch, useAppSelector } from '@/hooks/redux' -import { selectAllAddresses, selectDefaultAddress } from '@/storage/addresses/addressesSelectors' +import { useUnsortedAddresses } from '@/hooks/useUnsortedAddresses' +import { selectDefaultAddress } from '@/storage/addresses/addressesSelectors' import { copiedToClipboard, copyToClipboardFailed, receiveFaucetTokens } from '@/storage/global/globalActions' import { Address } from '@/types/addresses' const DevToolsSettingsSection = () => { const { t } = useTranslation() const dispatch = useAppDispatch() - const addresses = useAppSelector(selectAllAddresses) + const addresses = useUnsortedAddresses() const defaultAddress = useAppSelector(selectDefaultAddress) const currentNetwork = useAppSelector((s) => s.network) const faucetCallPending = useAppSelector((s) => s.global.faucetCallPending) diff --git a/apps/desktop-wallet/src/modals/WalletQRCodeExportModal.tsx b/apps/desktop-wallet/src/modals/WalletQRCodeExportModal.tsx index 1577313b63..121468e15f 100644 --- a/apps/desktop-wallet/src/modals/WalletQRCodeExportModal.tsx +++ b/apps/desktop-wallet/src/modals/WalletQRCodeExportModal.tsx @@ -31,8 +31,9 @@ import { Section } from '@/components/PageComponents/PageContainers' import PasswordConfirmation from '@/components/PasswordConfirmation' import { ModalBaseProp } from '@/features/modals/modalTypes' import { useAppSelector } from '@/hooks/redux' +import { useUnsortedAddresses } from '@/hooks/useUnsortedAddresses' import CenteredModal from '@/modals/CenteredModal' -import { selectAllAddresses, selectAllContacts } from '@/storage/addresses/addressesSelectors' +import { selectAllContacts } from '@/storage/addresses/addressesSelectors' import { walletStorage } from '@/storage/wallets/walletPersistentStorage' // Inspired by: @@ -45,7 +46,7 @@ const WalletQRCodeExportModal = memo(({ id }: ModalBaseProp) => { const { t } = useTranslation() const theme = useTheme() const activeWalletId = useAppSelector((s) => s.activeWallet.id) - const addresses = useAppSelector(selectAllAddresses) + const addresses = useUnsortedAddresses() const contacts = useAppSelector(selectAllContacts) const [frames, setFrames] = useState([]) diff --git a/apps/desktop-wallet/src/pages/UnlockedWallet/TransfersPage/FiltersPanel.tsx b/apps/desktop-wallet/src/pages/UnlockedWallet/TransfersPage/FiltersPanel.tsx index fabea299ca..35905ac05c 100644 --- a/apps/desktop-wallet/src/pages/UnlockedWallet/TransfersPage/FiltersPanel.tsx +++ b/apps/desktop-wallet/src/pages/UnlockedWallet/TransfersPage/FiltersPanel.tsx @@ -28,9 +28,8 @@ import Button from '@/components/Button' import MultiSelect from '@/components/Inputs/MultiSelect' import SelectOptionAddress from '@/components/Inputs/SelectOptionAddress' import SelectOptionWalletToken from '@/components/Inputs/SelectOptionWalletToken' -import { useAppSelector } from '@/hooks/redux' +import { useUnsortedAddresses } from '@/hooks/useUnsortedAddresses' import { UnlockedWalletPanel } from '@/pages/UnlockedWallet/UnlockedWalletLayout' -import { selectAllAddresses } from '@/storage/addresses/addressesSelectors' import { appHeaderHeightPx } from '@/style/globalStyles' import { Address } from '@/types/addresses' import { TokenId } from '@/types/tokens' @@ -56,7 +55,7 @@ const FiltersPanel = ({ className }: FiltersPanelProps) => { const { t } = useTranslation() - const addresses = useAppSelector(selectAllAddresses) + const addresses = useUnsortedAddresses() const { listedFts, unlistedFts, isLoading: isLoadingFts } = useFetchWalletFts() const { diff --git a/apps/desktop-wallet/src/pages/UnlockedWallet/TransfersPage/index.tsx b/apps/desktop-wallet/src/pages/UnlockedWallet/TransfersPage/index.tsx index d8ae22f6a2..dfedbccb68 100644 --- a/apps/desktop-wallet/src/pages/UnlockedWallet/TransfersPage/index.tsx +++ b/apps/desktop-wallet/src/pages/UnlockedWallet/TransfersPage/index.tsx @@ -26,11 +26,10 @@ import styled from 'styled-components' import { ShortcutButtonsGroupWallet } from '@/components/Buttons/ShortcutButtons' import { useScrollContext } from '@/contexts/scroll' import WalletTransactionsList from '@/features/transactionsDisplay/transactionLists/lists/WalletTransactionsList' -import { useAppSelector } from '@/hooks/redux' +import { useUnsortedAddresses } from '@/hooks/useUnsortedAddresses' import FiltersPanel from '@/pages/UnlockedWallet/TransfersPage/FiltersPanel' import { UnlockedWalletPanel } from '@/pages/UnlockedWallet/UnlockedWalletLayout' import UnlockedWalletPage from '@/pages/UnlockedWallet/UnlockedWalletPage' -import { selectAllAddresses } from '@/storage/addresses/addressesSelectors' import { walletSidebarWidthPx } from '@/style/globalStyles' import { TokenId } from '@/types/tokens' import { directionOptions } from '@/utils/transactions' @@ -41,7 +40,7 @@ interface TransfersPageProps { const TransfersPage = ({ className }: TransfersPageProps) => { const { t } = useTranslation() - const addresses = useAppSelector(selectAllAddresses) + const addresses = useUnsortedAddresses() const { scrollDirection } = useScrollContext() const [direction, setDirection] = useState(scrollDirection?.get()) diff --git a/apps/desktop-wallet/src/types/tokens.ts b/apps/desktop-wallet/src/types/tokens.ts index 827557ed9c..7912bb3d6a 100644 --- a/apps/desktop-wallet/src/types/tokens.ts +++ b/apps/desktop-wallet/src/types/tokens.ts @@ -33,13 +33,13 @@ export type UnlistedToken = { id: string } // For stricter typings in our components that handle display of multiple token types export type TokenDisplay = ListedFTDisplay | UnlistedFTDisplay | NFTDisplay | NonStandardTokenDisplay -export type ListedFTDisplay = DisplayBalances & +export type ListedFTDisplay = ApiBalances & ListedFT & { type: 'listedFT' worth?: number } -export type UnlistedFTDisplay = DisplayBalances & +export type UnlistedFTDisplay = ApiBalances & UnlistedFT & { type: 'unlistedFT' } @@ -48,18 +48,18 @@ export type NFTDisplay = NFT & { type: 'NFT' } -export type NonStandardTokenDisplay = DisplayBalances & +export type NonStandardTokenDisplay = ApiBalances & NonStandardToken & { type: 'nonStandardToken' } -export type DisplayBalances = { - totalBalance: bigint - lockedBalance: bigint - availableBalance: bigint +export type ApiBalances = { + totalBalance: string + lockedBalance: string + availableBalance: string } -export type TokenDisplayBalances = DisplayBalances & { +export type TokenApiBalances = ApiBalances & { id: e.Token['id'] } diff --git a/apps/mobile-wallet/package.json b/apps/mobile-wallet/package.json index 04b9a68fb7..549599a471 100644 --- a/apps/mobile-wallet/package.json +++ b/apps/mobile-wallet/package.json @@ -77,7 +77,7 @@ "lottie-react-native": "^6.7.0", "lucide-react-native": "^0.216.0", "moti": "^0.29.0", - "nanoid": "^4.0.0", + "nanoid": "^3.3.8", "posthog-react-native": "^2.7.1", "qrloop": "^1.4.1", "react": "^18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index adfabe20ed..95bb791c2d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -292,8 +292,8 @@ importers: specifier: ^0.287.0 version: 0.287.0(react@18.2.0) nanoid: - specifier: ^4.0.0 - version: 4.0.2 + specifier: ^3.3.8 + version: 3.3.8 posthog-js: specifier: ^1.52.0 version: 1.97.1 @@ -758,8 +758,8 @@ importers: specifier: ^0.29.0 version: 0.29.0(react-dom@18.2.0(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.25.7)(react-native@0.74.5(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0))(react@18.2.0) nanoid: - specifier: ^4.0.0 - version: 4.0.2 + specifier: ^3.3.8 + version: 3.3.8 posthog-react-native: specifier: ^2.7.1 version: 2.9.2(@react-native-async-storage/async-storage@1.23.1(react-native@0.74.5(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))(@types/react@18.2.79)(react@18.2.0)))(@react-navigation/native@6.1.9(react-native@0.74.5(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0))(expo-application@5.9.1(expo@51.0.39(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))))(expo-device@6.0.2(expo@51.0.39(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))))(expo-file-system@17.0.1(expo@51.0.39(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))))(expo-localization@15.0.3(expo@51.0.39(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7)))) @@ -8418,16 +8418,11 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanoid@4.0.2: - resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} - engines: {node: ^14 || ^16 || >=18} - hasBin: true - napi-build-utils@1.0.2: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} @@ -14677,7 +14672,7 @@ snapshots: dependencies: '@react-navigation/routers': 6.1.9 escape-string-regexp: 4.0.0 - nanoid: 3.3.7 + nanoid: 3.3.8 query-string: 7.1.3 react: 18.2.0 react-is: 16.13.1 @@ -14705,13 +14700,13 @@ snapshots: '@react-navigation/core': 6.4.10(react@18.2.0) escape-string-regexp: 4.0.0 fast-deep-equal: 3.1.3 - nanoid: 3.3.7 + nanoid: 3.3.8 react: 18.2.0 react-native: 0.74.5(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))(@types/react@18.2.79)(react@18.2.0) '@react-navigation/routers@6.1.9': dependencies: - nanoid: 3.3.7 + nanoid: 3.3.8 '@react-navigation/stack@6.3.20(@react-navigation/native@6.1.9(react-native@0.74.5(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.5(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.5(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.7)(@babel/preset-env@7.23.8(@babel/core@7.25.7))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0)': dependencies: @@ -21137,9 +21132,7 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nanoid@3.3.7: {} - - nanoid@4.0.2: {} + nanoid@3.3.8: {} napi-build-utils@1.0.2: {} @@ -21594,19 +21587,19 @@ snapshots: postcss@8.4.31: dependencies: - nanoid: 3.3.7 + nanoid: 3.3.8 picocolors: 1.0.0 source-map-js: 1.0.2 postcss@8.4.32: dependencies: - nanoid: 3.3.7 + nanoid: 3.3.8 picocolors: 1.0.1 source-map-js: 1.0.2 postcss@8.4.47: dependencies: - nanoid: 3.3.7 + nanoid: 3.3.8 picocolors: 1.1.0 source-map-js: 1.2.1