From bfef259a4149519ba848d66e3d404e687ca14a72 Mon Sep 17 00:00:00 2001 From: sadiabbasi Date: Tue, 26 Nov 2024 19:44:06 +0300 Subject: [PATCH 1/7] added the asset hook --- src/containers/AssetsContainer.tsx | 71 ++------------------ src/containers/MainSplashContainer.tsx | 3 + src/hooks/useAssets.ts | 91 ++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 67 deletions(-) create mode 100644 src/hooks/useAssets.ts diff --git a/src/containers/AssetsContainer.tsx b/src/containers/AssetsContainer.tsx index c8e2959b5..b3c0f63f8 100644 --- a/src/containers/AssetsContainer.tsx +++ b/src/containers/AssetsContainer.tsx @@ -1,9 +1,5 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { StyleSheet, View, Image, Text, TouchableOpacity, ScrollView, RefreshControl } from 'react-native'; -import { TButtonOutlined } from '../components/atoms/TButton'; -import { TP } from '../components/atoms/THeadings'; -import { SafeAreaView } from 'react-native-safe-area-context'; -import { useIsFocused } from '@react-navigation/native'; import theme, { commonStyles } from '../utils/theme'; import { AssetsScreenNavigationProp } from '../screens/AssetListingScreen'; import useWalletStore from '../store/useWalletStore'; @@ -11,12 +7,11 @@ import Debug from 'debug'; import { formatCurrencyValue } from '../utils/numbers'; import { capitalizeFirstLetter } from '../utils/strings'; import { isNetworkError } from '../utils/errors'; -import { assetStorage, connect } from '../utils/StorageManager/setup'; import { ArrowDown, ArrowUp } from 'iconoir-react-native'; import { tokenRegistry } from '../utils/tokenRegistry'; import TSpinner from '../components/atoms/TSpinner'; import useAppSettings from '../hooks/useAppSettings'; -import useUserStore from '../store/userStore'; +import useAssets from '../hooks/useAssets'; const debug = Debug('tonomy-id:containers:AssetsContainer'); @@ -25,71 +20,14 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre const [isAssetLoading, setAssetLoading] = useState(true); const [refreshBalance, setRefreshBalance] = useState(false); const { developerMode } = useAppSettings(); + const { accounts } = useAssets(); - const { accountsInitialized, initializeWalletAccount, updateBalance } = useWalletStore(); + const { updateBalance } = useWalletStore(); const isUpdatingBalances = useRef(false); - const [accounts, setAccounts] = useState< - { network: string; accountName: string; balance: string; usdBalance: number }[] - >([]); - const { user } = useUserStore(); const tokens = useMemo(() => tokenRegistry, []); - const fetchCryptoAssets = useCallback(async () => { - try { - if (!accountsInitialized) await initializeWalletAccount(user); - await connect(); - - for (const { chain, token } of tokens) { - try { - const asset = await assetStorage.findAssetByName(token); - - debug( - `fetchCryptoAssets() fetching asset ${chain.getName()}: ${asset?.accountName}-${asset?.balance}` - ); - let account; - - if (asset) { - account = { - network: capitalizeFirstLetter(chain.getName()), - accountName: asset.accountName, - balance: asset.balance, - usdBalance: asset.usdBalance, - }; - } else { - account = { - network: capitalizeFirstLetter(chain.getName()), - accountName: null, - balance: '0', - usdBalance: 0, - }; - } - - setAccounts((prevAccounts) => { - // find index of the account in the array - const index = prevAccounts.findIndex((acc) => acc.network === account.network); - - if (index !== -1) { - // Update the existing asset - const updatedAccounts = [...prevAccounts]; - - updatedAccounts[index] = account; - return updatedAccounts; - } else { - // Add the new asset - return [...prevAccounts, account]; - } - }); - } catch (error) { - debug(`fetchCryptoAssets() error fetching ${chain.getName()} asset`, error); - } - } - } catch (error) { - console.error('fetchCryptoAssets() error', error); - } - }, [accountsInitialized, initializeWalletAccount, tokens, user]); - const updateAllBalances = useCallback(async () => { if (isUpdatingBalances.current) return; // Prevent re-entry if already running isUpdatingBalances.current = true; @@ -97,7 +35,6 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre try { debug('updateAllBalances()'); await updateBalance(); - await fetchCryptoAssets(); setAssetLoading(false); } catch (error) { if (isNetworkError(error)) { @@ -108,7 +45,7 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre } finally { isUpdatingBalances.current = false; } - }, [updateBalance, fetchCryptoAssets]); + }, [updateBalance]); const onRefresh = useCallback(async () => { try { diff --git a/src/containers/MainSplashContainer.tsx b/src/containers/MainSplashContainer.tsx index 99ee4bfa8..0f0ce8bab 100644 --- a/src/containers/MainSplashContainer.tsx +++ b/src/containers/MainSplashContainer.tsx @@ -13,12 +13,14 @@ import { appStorage, connect } from '../utils/StorageManager/setup'; import { useFonts } from 'expo-font'; import Debug from 'debug'; import { progressiveRetryOnNetworkError } from '../utils/network'; +import useAssets from '../hooks/useAssets'; const debug = Debug('tonomy-id:container:mainSplashScreen'); export default function MainSplashScreenContainer({ navigation }: { navigation: Props['navigation'] }) { const errorStore = useErrorStore(); const { user, initializeStatusFromStorage, isAppInitialized, getStatus, logout, setStatus } = useUserStore(); + const { fetchCryptoAssets } = useAssets(); useFonts({ Roboto: require('../assets/fonts/Roboto-Regular.ttf'), @@ -60,6 +62,7 @@ export default function MainSplashScreenContainer({ navigation }: { navigation: case UserStatus.LOGGED_IN: try { await user.getUsername(); + await fetchCryptoAssets(); } catch (e) { if (e instanceof SdkError && e.code === SdkErrors.InvalidData) { logout("Invalid data in user's storage"); diff --git a/src/hooks/useAssets.ts b/src/hooks/useAssets.ts new file mode 100644 index 000000000..53a3268c4 --- /dev/null +++ b/src/hooks/useAssets.ts @@ -0,0 +1,91 @@ +import { useState, useCallback, useEffect, useMemo } from 'react'; +import { capitalizeFirstLetter } from '../utils/strings'; +import { assetStorage, connect } from '../utils/StorageManager/setup'; +import useWalletStore from '../store/useWalletStore'; +import { tokenRegistry } from '../utils/tokenRegistry'; +import useUserStore from '../store/userStore'; +import Debug from 'debug'; + +const debug = Debug('tonomy-id:hooks:useAssets'); + +const useCryptoAssets = () => { + const { accountsInitialized, initializeWalletAccount } = useWalletStore(); + const { user } = useUserStore(); + + const tokens = useMemo(() => tokenRegistry, []); + + const [accounts, setAccounts] = useState< + { network: string; accountName: string; balance: string; usdBalance: number }[] + >([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const fetchCryptoAssets = useCallback(async () => { + setLoading(true); + setError(null); + + try { + // Ensure accounts are initialized + if (!accountsInitialized) await initializeWalletAccount(user); + await connect(); + + for (const { chain, token } of tokens) { + try { + const asset = await assetStorage.findAssetByName(token); + + debug( + `fetchCryptoAssets() fetching asset ${chain.getName()}: ${asset?.accountName}-${asset?.balance}` + ); + let account; + + if (asset) { + account = { + network: capitalizeFirstLetter(chain.getName()), + accountName: asset.accountName, + balance: asset.balance, + usdBalance: asset.usdBalance, + }; + } else { + account = { + network: capitalizeFirstLetter(chain.getName()), + accountName: null, + balance: '0', + usdBalance: 0, + }; + } + + setAccounts((prevAccounts) => { + // find index of the account in the array + const index = prevAccounts.findIndex((acc) => acc.network === account.network); + + if (index !== -1) { + // Update the existing asset + const updatedAccounts = [...prevAccounts]; + + updatedAccounts[index] = account; + return updatedAccounts; + } else { + // Add the new asset + return [...prevAccounts, account]; + } + }); + } catch (assetError) { + console.error(`Error fetching asset for ${chain.getName()}:`, assetError); + } + } + } catch (fetchError) { + console.error('Error fetching crypto assets:', fetchError); + setError(fetchError); + } finally { + setLoading(false); + } + }, [initializeWalletAccount, tokens, user, accountsInitialized]); + + useEffect(() => { + fetchCryptoAssets(); + }, [fetchCryptoAssets]); + + return { accounts, fetchCryptoAssets, loading, error }; +}; + +export default useCryptoAssets; From 52e9b9fb76133b2359f80622499a69f39e98f593 Mon Sep 17 00:00:00 2001 From: sadiabbasi Date: Wed, 27 Nov 2024 00:10:26 +0300 Subject: [PATCH 2/7] worked on useUpdateBalance hook --- src/containers/AssetsContainer.tsx | 141 +++++++++--------- src/containers/MainSplashContainer.tsx | 3 - src/containers/SelectAssetContainer.tsx | 62 +------- src/hooks/useAssets.ts | 17 ++- src/hooks/useUpdateBalances.ts | 59 ++++++++ src/store/useWalletStore.ts | 1 + .../repositories/assetStorageManager.ts | 2 +- 7 files changed, 142 insertions(+), 143 deletions(-) create mode 100644 src/hooks/useUpdateBalances.ts diff --git a/src/containers/AssetsContainer.tsx b/src/containers/AssetsContainer.tsx index b3c0f63f8..a38c92d4c 100644 --- a/src/containers/AssetsContainer.tsx +++ b/src/containers/AssetsContainer.tsx @@ -1,77 +1,48 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { StyleSheet, View, Image, Text, TouchableOpacity, ScrollView, RefreshControl } from 'react-native'; import theme, { commonStyles } from '../utils/theme'; import { AssetsScreenNavigationProp } from '../screens/AssetListingScreen'; -import useWalletStore from '../store/useWalletStore'; import Debug from 'debug'; import { formatCurrencyValue } from '../utils/numbers'; import { capitalizeFirstLetter } from '../utils/strings'; -import { isNetworkError } from '../utils/errors'; import { ArrowDown, ArrowUp } from 'iconoir-react-native'; import { tokenRegistry } from '../utils/tokenRegistry'; import TSpinner from '../components/atoms/TSpinner'; import useAppSettings from '../hooks/useAppSettings'; import useAssets from '../hooks/useAssets'; +import useUpdateBalances from '../hooks/useUpdateBalances'; +import { useFocusEffect } from '@react-navigation/native'; const debug = Debug('tonomy-id:containers:AssetsContainer'); export default function AssetsContainer({ navigation }: { navigation: AssetsScreenNavigationProp['navigation'] }) { const [total, setTotal] = useState(0); - const [isAssetLoading, setAssetLoading] = useState(true); - const [refreshBalance, setRefreshBalance] = useState(false); - const { developerMode } = useAppSettings(); - const { accounts } = useAssets(); - - const { updateBalance } = useWalletStore(); - const isUpdatingBalances = useRef(false); + const { developerMode } = useAppSettings(); + const { accounts, loading, fetchCryptoAssets } = useAssets(); + const { refreshBalance, onRefresh, updateAllBalances } = useUpdateBalances(); const tokens = useMemo(() => tokenRegistry, []); - const updateAllBalances = useCallback(async () => { - if (isUpdatingBalances.current) return; // Prevent re-entry if already running - isUpdatingBalances.current = true; - - try { - debug('updateAllBalances()'); - await updateBalance(); - setAssetLoading(false); - } catch (error) { - if (isNetworkError(error)) { - debug('updateAllBalances() Error updating account detail network error:'); - } else { - console.error('AssetsContainer() updateAllBalances() error', error); - } - } finally { - isUpdatingBalances.current = false; - } - }, [updateBalance]); - - const onRefresh = useCallback(async () => { - try { - setRefreshBalance(true); - await updateAllBalances(); - } finally { - setRefreshBalance(false); - } - }, [updateAllBalances]); - - // updateAllBalances() on mount and every 20 seconds - useEffect(() => { - updateAllBalances(); - - const interval = setInterval(updateAllBalances, 10000); - - return () => clearInterval(interval); - }, [updateAllBalances]); - + console.log('Accounts updated:', accounts); useEffect(() => { const totalAssetsUSDBalance = accounts.reduce((previousValue, currentValue) => { return previousValue + currentValue.usdBalance; }, 0); setTotal(totalAssetsUSDBalance); - }, [accounts]); + }, [accounts, updateAllBalances]); + + useFocusEffect( + useCallback(() => { + const initializeAssets = async () => { + await fetchCryptoAssets(); + await updateAllBalances(); + }; + + initializeAssets(); + }, [fetchCryptoAssets, updateAllBalances]) + ); const findAccountByChain = (chain: string) => { const accountExists = accounts.find((account) => account.network === chain); @@ -117,7 +88,7 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre - {!isAssetLoading ? ( + {!loading ? ( {tokens.map((chainObj, index) => { const chainName = capitalizeFirstLetter(chainObj.chain.getName()); @@ -162,30 +133,47 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre )} - {accountData.account ? ( - - - {accountData.balance} - - - ${formatCurrencyValue(accountData.usdBalance ?? 0)} - + {refreshBalance ? ( + + ) : ( - - { - navigation.navigate('CreateEthereumKey', { - requestType: 'createKey', - request: null, - transaction: null, - }); - }} - > - Not connected - Generate key - - + <> + {accountData.account ? ( + + + + {accountData.balance} + + + + ${formatCurrencyValue(accountData.usdBalance ?? 0)} + + + ) : ( + + { + navigation.navigate('CreateEthereumKey', { + requestType: 'createKey', + request: null, + transaction: null, + }); + }} + > + Not connected + Generate key + + + )} + )} @@ -194,8 +182,15 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre })} ) : ( - - + + )} diff --git a/src/containers/MainSplashContainer.tsx b/src/containers/MainSplashContainer.tsx index 0f0ce8bab..99ee4bfa8 100644 --- a/src/containers/MainSplashContainer.tsx +++ b/src/containers/MainSplashContainer.tsx @@ -13,14 +13,12 @@ import { appStorage, connect } from '../utils/StorageManager/setup'; import { useFonts } from 'expo-font'; import Debug from 'debug'; import { progressiveRetryOnNetworkError } from '../utils/network'; -import useAssets from '../hooks/useAssets'; const debug = Debug('tonomy-id:container:mainSplashScreen'); export default function MainSplashScreenContainer({ navigation }: { navigation: Props['navigation'] }) { const errorStore = useErrorStore(); const { user, initializeStatusFromStorage, isAppInitialized, getStatus, logout, setStatus } = useUserStore(); - const { fetchCryptoAssets } = useAssets(); useFonts({ Roboto: require('../assets/fonts/Roboto-Regular.ttf'), @@ -62,7 +60,6 @@ export default function MainSplashScreenContainer({ navigation }: { navigation: case UserStatus.LOGGED_IN: try { await user.getUsername(); - await fetchCryptoAssets(); } catch (e) { if (e instanceof SdkError && e.code === SdkErrors.InvalidData) { logout("Invalid data in user's storage"); diff --git a/src/containers/SelectAssetContainer.tsx b/src/containers/SelectAssetContainer.tsx index 3a295c7d9..3fa7c119e 100644 --- a/src/containers/SelectAssetContainer.tsx +++ b/src/containers/SelectAssetContainer.tsx @@ -8,6 +8,7 @@ import Debug from 'debug'; import { formatCurrencyValue } from '../utils/numbers'; import { TokenRegistryEntry, getKeyOrNullFromChain, tokenRegistry } from '../utils/tokenRegistry'; import useAppSettings from '../hooks/useAppSettings'; +import useAssets from '../hooks/useAssets'; const debug = Debug('tonomy-id:containers:MainContainer'); @@ -18,69 +19,14 @@ const SelectAssetContainer = ({ navigation: SelectAssetScreenNavigationProp['navigation']; type: string; }) => { - const [accounts, setAccounts] = useState< - { network: string; accountName: string | null; balance: string; usdBalance: number }[] - >([]); + const { accounts } = useAssets(); + + console.log('accounts', accounts); const { developerMode } = useAppSettings(); const tokens = useMemo(() => tokenRegistry, []); - const fetchCryptoAssets = useCallback(async () => { - try { - await connect(); - - for (const { chain, token } of tokens) { - const asset = await assetStorage.findAssetByName(token); - - debug(`fetchCryptoAssets() fetching asset for ${chain.getName()}`); - let account; - - if (asset) { - account = { - network: capitalizeFirstLetter(chain.getName()), - accountName: asset.accountName, - balance: asset.balance, - usdBalance: asset.usdBalance, - }; - } else { - account = { - network: capitalizeFirstLetter(chain.getName()), - accountName: null, - balance: '0', - usdBalance: 0, - }; - } - - setAccounts((prevAccounts) => { - // find index of the account in the array - const index = prevAccounts.findIndex((acc) => acc.network === account.network); - - if (index !== -1) { - // Update the existing asset - const updatedAccounts = [...prevAccounts]; - - updatedAccounts[index] = account; - return updatedAccounts; - } else { - // Add the new asset - return [...prevAccounts, account]; - } - }); - } - } catch (error) { - debug('fetchCryptoAssets() error', error); - } - }, [tokens]); - - useEffect(() => { - fetchCryptoAssets(); - - const interval = setInterval(fetchCryptoAssets, 10000); - - return () => clearInterval(interval); - }, [fetchCryptoAssets]); - const findAccountByChain = (chain: string) => { const accountExists = accounts.find((account) => account.network === chain); const balance = accountExists?.balance; diff --git a/src/hooks/useAssets.ts b/src/hooks/useAssets.ts index 53a3268c4..f19331b52 100644 --- a/src/hooks/useAssets.ts +++ b/src/hooks/useAssets.ts @@ -5,6 +5,7 @@ import useWalletStore from '../store/useWalletStore'; import { tokenRegistry } from '../utils/tokenRegistry'; import useUserStore from '../store/userStore'; import Debug from 'debug'; +import { useFocusEffect } from '@react-navigation/native'; const debug = Debug('tonomy-id:hooks:useAssets'); @@ -18,11 +19,10 @@ const useCryptoAssets = () => { { network: string; accountName: string; balance: string; usdBalance: number }[] >([]); const [loading, setLoading] = useState(false); - const [error, setError] = useState(null); const fetchCryptoAssets = useCallback(async () => { setLoading(true); - setError(null); + console.log('useCryptoAssets: fetchCryptoAssets()'); try { // Ensure accounts are initialized @@ -33,7 +33,7 @@ const useCryptoAssets = () => { try { const asset = await assetStorage.findAssetByName(token); - debug( + console.log( `fetchCryptoAssets() fetching asset ${chain.getName()}: ${asset?.accountName}-${asset?.balance}` ); let account; @@ -75,17 +75,18 @@ const useCryptoAssets = () => { } } catch (fetchError) { console.error('Error fetching crypto assets:', fetchError); - setError(fetchError); } finally { setLoading(false); } }, [initializeWalletAccount, tokens, user, accountsInitialized]); - useEffect(() => { - fetchCryptoAssets(); - }, [fetchCryptoAssets]); + useFocusEffect( + useCallback(() => { + fetchCryptoAssets(); + }, []) + ); - return { accounts, fetchCryptoAssets, loading, error }; + return { accounts, fetchCryptoAssets, loading }; }; export default useCryptoAssets; diff --git a/src/hooks/useUpdateBalances.ts b/src/hooks/useUpdateBalances.ts new file mode 100644 index 000000000..265cea65b --- /dev/null +++ b/src/hooks/useUpdateBalances.ts @@ -0,0 +1,59 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; +import { isNetworkError } from '../utils/errors'; +import useWalletStore from '../store/useWalletStore'; +import Debug from 'debug'; +import { useFocusEffect } from '@react-navigation/native'; + +const debug = Debug('tonomy-id:hooks:useUpdateBalances'); + +const useUpdateBalances = () => { + const { updateBalance } = useWalletStore(); + + const isUpdatingBalances = useRef(false); + const [refreshBalance, setIsRefreshing] = useState(false); + const [isAssetLoading, setAssetLoading] = useState(true); + + const updateAllBalances = useCallback(async () => { + if (isUpdatingBalances.current) return; // Prevent re-entry if already running + setAssetLoading(true); + isUpdatingBalances.current = true; + + try { + console.log('useAsset: updateAllBalances()'); + await updateBalance(); + } catch (error) { + if (isNetworkError(error)) { + debug('useAsset: Error updating account detail due to network error'); + } else { + console.error('useAsset: updateAllBalances() error', error); + } + } finally { + isUpdatingBalances.current = false; + setAssetLoading(false); + } + }, [updateBalance]); + + const onRefresh = useCallback(async () => { + setIsRefreshing(true); + + try { + await updateAllBalances(); + } finally { + setIsRefreshing(false); + } + }, [updateAllBalances]); + + useFocusEffect( + useCallback(() => { + updateAllBalances(); + + const interval = setInterval(updateAllBalances, 10000); + + return () => clearInterval(interval); + }, []) + ); + + return { updateAllBalances, onRefresh, refreshBalance, isAssetLoading }; +}; + +export default useUpdateBalances; diff --git a/src/store/useWalletStore.ts b/src/store/useWalletStore.ts index 870d95b35..c4a24ec80 100644 --- a/src/store/useWalletStore.ts +++ b/src/store/useWalletStore.ts @@ -183,6 +183,7 @@ const useWalletStore = create((set, get) => ({ const { token } = await getTokenEntryByChain(chain); const balance = await token.getBalance(account); + console.log(`updateBalance() ${chain.getName()} balance:`, await balance.toString(7)); await assetStorage.updateAccountBalance(balance); } catch (error) { console.error(`updateBalance() Error fetching balance ${chain.getName()}:`, error); diff --git a/src/utils/StorageManager/repositories/assetStorageManager.ts b/src/utils/StorageManager/repositories/assetStorageManager.ts index aca2c1d7b..d1ad53df1 100644 --- a/src/utils/StorageManager/repositories/assetStorageManager.ts +++ b/src/utils/StorageManager/repositories/assetStorageManager.ts @@ -29,7 +29,7 @@ export abstract class AssetStorageManager { const existingAsset = await this.repository.findAssetByName(name); if (existingAsset) { - const balance = asset.toString(4); + const balance = asset.toString(6); debug(`updateAccountBalance() updating ${name} balance to ${balance}`); From 2655a65633c666a67d7010d72c981ceb3b835433 Mon Sep 17 00:00:00 2001 From: sadiabbasi Date: Wed, 27 Nov 2024 16:28:40 +0300 Subject: [PATCH 3/7] fixed the hook --- src/containers/AssetsContainer.tsx | 30 +++++++++++++++--------------- src/hooks/useAssets.ts | 20 ++++++-------------- src/hooks/useUpdateBalances.ts | 24 ++++++++++-------------- 3 files changed, 31 insertions(+), 43 deletions(-) diff --git a/src/containers/AssetsContainer.tsx b/src/containers/AssetsContainer.tsx index a38c92d4c..829559570 100644 --- a/src/containers/AssetsContainer.tsx +++ b/src/containers/AssetsContainer.tsx @@ -19,12 +19,23 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre const [total, setTotal] = useState(0); const { developerMode } = useAppSettings(); - const { accounts, loading, fetchCryptoAssets } = useAssets(); - const { refreshBalance, onRefresh, updateAllBalances } = useUpdateBalances(); + const [isAssetLoading, setAssetLoading] = useState(true); + const [refreshBalance, setRefreshBalance] = useState(false); + const [accounts, setAccounts] = useState< + { network: string; accountName: string; balance: string; usdBalance: number }[] + >([]); + const { fetchCryptoAssets } = useAssets({ + setAccounts, + setAssetLoading, + }); + + const { updateAllBalances, onRefresh } = useUpdateBalances({ + fetchCryptoAssets, + setRefreshBalance, + }); const tokens = useMemo(() => tokenRegistry, []); - console.log('Accounts updated:', accounts); useEffect(() => { const totalAssetsUSDBalance = accounts.reduce((previousValue, currentValue) => { return previousValue + currentValue.usdBalance; @@ -33,17 +44,6 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre setTotal(totalAssetsUSDBalance); }, [accounts, updateAllBalances]); - useFocusEffect( - useCallback(() => { - const initializeAssets = async () => { - await fetchCryptoAssets(); - await updateAllBalances(); - }; - - initializeAssets(); - }, [fetchCryptoAssets, updateAllBalances]) - ); - const findAccountByChain = (chain: string) => { const accountExists = accounts.find((account) => account.network === chain); @@ -88,7 +88,7 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre - {!loading ? ( + {!isAssetLoading ? ( {tokens.map((chainObj, index) => { const chainName = capitalizeFirstLetter(chainObj.chain.getName()); diff --git a/src/hooks/useAssets.ts b/src/hooks/useAssets.ts index f19331b52..64a5c57ab 100644 --- a/src/hooks/useAssets.ts +++ b/src/hooks/useAssets.ts @@ -9,19 +9,13 @@ import { useFocusEffect } from '@react-navigation/native'; const debug = Debug('tonomy-id:hooks:useAssets'); -const useCryptoAssets = () => { +const useCryptoAssets = ({ setAccounts, setAssetLoading }) => { const { accountsInitialized, initializeWalletAccount } = useWalletStore(); const { user } = useUserStore(); const tokens = useMemo(() => tokenRegistry, []); - const [accounts, setAccounts] = useState< - { network: string; accountName: string; balance: string; usdBalance: number }[] - >([]); - const [loading, setLoading] = useState(false); - const fetchCryptoAssets = useCallback(async () => { - setLoading(true); console.log('useCryptoAssets: fetchCryptoAssets()'); try { @@ -33,7 +27,7 @@ const useCryptoAssets = () => { try { const asset = await assetStorage.findAssetByName(token); - console.log( + debug( `fetchCryptoAssets() fetching asset ${chain.getName()}: ${asset?.accountName}-${asset?.balance}` ); let account; @@ -75,18 +69,16 @@ const useCryptoAssets = () => { } } catch (fetchError) { console.error('Error fetching crypto assets:', fetchError); - } finally { - setLoading(false); } - }, [initializeWalletAccount, tokens, user, accountsInitialized]); + }, [initializeWalletAccount, tokens, user, accountsInitialized, setAccounts]); useFocusEffect( useCallback(() => { - fetchCryptoAssets(); - }, []) + fetchCryptoAssets().then(() => setAssetLoading(false)); + }, [fetchCryptoAssets, setAssetLoading]) ); - return { accounts, fetchCryptoAssets, loading }; + return { fetchCryptoAssets }; }; export default useCryptoAssets; diff --git a/src/hooks/useUpdateBalances.ts b/src/hooks/useUpdateBalances.ts index 265cea65b..ee460ed03 100644 --- a/src/hooks/useUpdateBalances.ts +++ b/src/hooks/useUpdateBalances.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useRef, useState } from 'react'; import { isNetworkError } from '../utils/errors'; import useWalletStore from '../store/useWalletStore'; import Debug from 'debug'; @@ -6,21 +6,18 @@ import { useFocusEffect } from '@react-navigation/native'; const debug = Debug('tonomy-id:hooks:useUpdateBalances'); -const useUpdateBalances = () => { +const useUpdateBalances = ({ fetchCryptoAssets, setRefreshBalance }) => { const { updateBalance } = useWalletStore(); const isUpdatingBalances = useRef(false); - const [refreshBalance, setIsRefreshing] = useState(false); - const [isAssetLoading, setAssetLoading] = useState(true); const updateAllBalances = useCallback(async () => { if (isUpdatingBalances.current) return; // Prevent re-entry if already running - setAssetLoading(true); isUpdatingBalances.current = true; try { - console.log('useAsset: updateAllBalances()'); await updateBalance(); + await fetchCryptoAssets(); } catch (error) { if (isNetworkError(error)) { debug('useAsset: Error updating account detail due to network error'); @@ -29,31 +26,30 @@ const useUpdateBalances = () => { } } finally { isUpdatingBalances.current = false; - setAssetLoading(false); } - }, [updateBalance]); + }, [updateBalance, fetchCryptoAssets]); const onRefresh = useCallback(async () => { - setIsRefreshing(true); + setRefreshBalance(true); try { await updateAllBalances(); } finally { - setIsRefreshing(false); + setRefreshBalance(false); } - }, [updateAllBalances]); + }, [updateAllBalances, setRefreshBalance]); useFocusEffect( useCallback(() => { updateAllBalances(); - const interval = setInterval(updateAllBalances, 10000); + const interval = setInterval(updateAllBalances, 8000); return () => clearInterval(interval); - }, []) + }, [updateAllBalances]) ); - return { updateAllBalances, onRefresh, refreshBalance, isAssetLoading }; + return { updateAllBalances, onRefresh }; }; export default useUpdateBalances; From cb93c0fb2b15f53ddec6e034e4d6a88a15e9e56a Mon Sep 17 00:00:00 2001 From: sadiabbasi Date: Wed, 27 Nov 2024 16:35:47 +0300 Subject: [PATCH 4/7] fixed the hook and updated in asset container --- src/containers/AssetsContainer.tsx | 3 +-- src/hooks/useAssets.ts | 2 -- src/store/useWalletStore.ts | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/containers/AssetsContainer.tsx b/src/containers/AssetsContainer.tsx index 829559570..b4f8492b2 100644 --- a/src/containers/AssetsContainer.tsx +++ b/src/containers/AssetsContainer.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { StyleSheet, View, Image, Text, TouchableOpacity, ScrollView, RefreshControl } from 'react-native'; import theme, { commonStyles } from '../utils/theme'; import { AssetsScreenNavigationProp } from '../screens/AssetListingScreen'; @@ -11,7 +11,6 @@ import TSpinner from '../components/atoms/TSpinner'; import useAppSettings from '../hooks/useAppSettings'; import useAssets from '../hooks/useAssets'; import useUpdateBalances from '../hooks/useUpdateBalances'; -import { useFocusEffect } from '@react-navigation/native'; const debug = Debug('tonomy-id:containers:AssetsContainer'); diff --git a/src/hooks/useAssets.ts b/src/hooks/useAssets.ts index 64a5c57ab..5ecf1af00 100644 --- a/src/hooks/useAssets.ts +++ b/src/hooks/useAssets.ts @@ -16,8 +16,6 @@ const useCryptoAssets = ({ setAccounts, setAssetLoading }) => { const tokens = useMemo(() => tokenRegistry, []); const fetchCryptoAssets = useCallback(async () => { - console.log('useCryptoAssets: fetchCryptoAssets()'); - try { // Ensure accounts are initialized if (!accountsInitialized) await initializeWalletAccount(user); diff --git a/src/store/useWalletStore.ts b/src/store/useWalletStore.ts index c4a24ec80..74b050cd9 100644 --- a/src/store/useWalletStore.ts +++ b/src/store/useWalletStore.ts @@ -183,7 +183,7 @@ const useWalletStore = create((set, get) => ({ const { token } = await getTokenEntryByChain(chain); const balance = await token.getBalance(account); - console.log(`updateBalance() ${chain.getName()} balance:`, await balance.toString(7)); + debug(`updateBalance() ${chain.getName()} balance:`, await balance.toString(7)); await assetStorage.updateAccountBalance(balance); } catch (error) { console.error(`updateBalance() Error fetching balance ${chain.getName()}:`, error); From 9189c8783cc8aa528a7119f11c2409950ce7a470 Mon Sep 17 00:00:00 2001 From: sadiabbasi Date: Wed, 27 Nov 2024 17:18:51 +0300 Subject: [PATCH 5/7] rename hook and implement in select asset --- src/containers/AssetsContainer.tsx | 20 +-- src/containers/SelectAssetContainer.tsx | 137 +++++++++++------- src/hooks/useAssetManager.ts | 31 ++++ ...{useAssets.ts => useFetchCrytpoAccount.ts} | 6 +- src/hooks/useUpdateBalances.ts | 2 +- 5 files changed, 120 insertions(+), 76 deletions(-) create mode 100644 src/hooks/useAssetManager.ts rename src/hooks/{useAssets.ts => useFetchCrytpoAccount.ts} (95%) diff --git a/src/containers/AssetsContainer.tsx b/src/containers/AssetsContainer.tsx index b4f8492b2..195f24998 100644 --- a/src/containers/AssetsContainer.tsx +++ b/src/containers/AssetsContainer.tsx @@ -9,8 +9,7 @@ import { ArrowDown, ArrowUp } from 'iconoir-react-native'; import { tokenRegistry } from '../utils/tokenRegistry'; import TSpinner from '../components/atoms/TSpinner'; import useAppSettings from '../hooks/useAppSettings'; -import useAssets from '../hooks/useAssets'; -import useUpdateBalances from '../hooks/useUpdateBalances'; +import useAssetManager from '../hooks/useAssetManager'; const debug = Debug('tonomy-id:containers:AssetsContainer'); @@ -18,20 +17,7 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre const [total, setTotal] = useState(0); const { developerMode } = useAppSettings(); - const [isAssetLoading, setAssetLoading] = useState(true); - const [refreshBalance, setRefreshBalance] = useState(false); - const [accounts, setAccounts] = useState< - { network: string; accountName: string; balance: string; usdBalance: number }[] - >([]); - const { fetchCryptoAssets } = useAssets({ - setAccounts, - setAssetLoading, - }); - - const { updateAllBalances, onRefresh } = useUpdateBalances({ - fetchCryptoAssets, - setRefreshBalance, - }); + const { isAssetLoading, accounts, onRefresh, refreshBalance } = useAssetManager(); const tokens = useMemo(() => tokenRegistry, []); @@ -41,7 +27,7 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre }, 0); setTotal(totalAssetsUSDBalance); - }, [accounts, updateAllBalances]); + }, [accounts]); const findAccountByChain = (chain: string) => { const accountExists = accounts.find((account) => account.network === chain); diff --git a/src/containers/SelectAssetContainer.tsx b/src/containers/SelectAssetContainer.tsx index 3fa7c119e..28533a437 100644 --- a/src/containers/SelectAssetContainer.tsx +++ b/src/containers/SelectAssetContainer.tsx @@ -1,14 +1,14 @@ -import { ScrollView, StyleSheet, Text, TouchableOpacity, View, Image } from 'react-native'; +import { ScrollView, StyleSheet, Text, TouchableOpacity, View, Image, RefreshControl } from 'react-native'; import { SelectAssetScreenNavigationProp } from '../screens/SelectAssetScreen'; import theme from '../utils/theme'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import { assetStorage, connect } from '../utils/StorageManager/setup'; +import { useMemo } from 'react'; import { capitalizeFirstLetter } from '../utils/strings'; import Debug from 'debug'; import { formatCurrencyValue } from '../utils/numbers'; import { TokenRegistryEntry, getKeyOrNullFromChain, tokenRegistry } from '../utils/tokenRegistry'; import useAppSettings from '../hooks/useAppSettings'; -import useAssets from '../hooks/useAssets'; +import useAssetManager from '../hooks/useAssetManager'; +import TSpinner from '../components/atoms/TSpinner'; const debug = Debug('tonomy-id:containers:MainContainer'); @@ -19,9 +19,7 @@ const SelectAssetContainer = ({ navigation: SelectAssetScreenNavigationProp['navigation']; type: string; }) => { - const { accounts } = useAssets(); - - console.log('accounts', accounts); + const { isAssetLoading, accounts, onRefresh, refreshBalance } = useAssetManager(); const { developerMode } = useAppSettings(); @@ -61,62 +59,91 @@ const SelectAssetContainer = ({ return ( - + } + > select a currency to {type} - - {tokens.map((chainObj, index) => { - const chainName = capitalizeFirstLetter(chainObj.chain.getName()); - - const accountData = findAccountByChain(chainName); - - if (chainObj.chain.isTestnet() && !developerMode) { - return null; - } - - return ( - handleOnPress(chainObj)} - > - - - + {!isAssetLoading ? ( + + {tokens.map((chainObj, index) => { + const chainName = capitalizeFirstLetter(chainObj.chain.getName()); + + const accountData = findAccountByChain(chainName); + + if (chainObj.chain.isTestnet() && !developerMode) { + return null; + } + + return ( + handleOnPress(chainObj)} + > + + - {chainObj.token.getSymbol()} - - {chainName} + + {chainObj.token.getSymbol()} + + {chainName} + + {chainObj.chain.isTestnet() && ( + + + Testnet + + + )} - {chainObj.chain.isTestnet() && ( - - - Testnet + {refreshBalance ? ( + + + + ) : ( + + + {accountData.balance} + + + ${formatCurrencyValue(accountData.usdBalance ?? 0)} )} - - - {accountData.balance} - - - ${formatCurrencyValue(accountData.usdBalance ?? 0)} - - - - - ); - })} - + + ); + })} + + ) : ( + + + + )} diff --git a/src/hooks/useAssetManager.ts b/src/hooks/useAssetManager.ts new file mode 100644 index 000000000..05a134c35 --- /dev/null +++ b/src/hooks/useAssetManager.ts @@ -0,0 +1,31 @@ +import { useState } from 'react'; +import useFetchCrytpoAccount from './useFetchCrytpoAccount'; +import useUpdateBalances from './useUpdateBalances'; + +const useAssetManager = () => { + const [isAssetLoading, setAssetLoading] = useState(true); + const [refreshBalance, setRefreshBalance] = useState(false); + const [accounts, setAccounts] = useState< + { network: string; accountName: string; balance: string; usdBalance: number }[] + >([]); + + const { fetchCryptoAssets } = useFetchCrytpoAccount({ + setAccounts, + setAssetLoading, + }); + + const { updateAllBalances, onRefresh } = useUpdateBalances({ + fetchCryptoAssets, + setRefreshBalance, + }); + + return { + isAssetLoading, + refreshBalance, + accounts, + updateAllBalances, + onRefresh, + }; +}; + +export default useAssetManager; diff --git a/src/hooks/useAssets.ts b/src/hooks/useFetchCrytpoAccount.ts similarity index 95% rename from src/hooks/useAssets.ts rename to src/hooks/useFetchCrytpoAccount.ts index 5ecf1af00..4ebb396ee 100644 --- a/src/hooks/useAssets.ts +++ b/src/hooks/useFetchCrytpoAccount.ts @@ -1,4 +1,4 @@ -import { useState, useCallback, useEffect, useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { capitalizeFirstLetter } from '../utils/strings'; import { assetStorage, connect } from '../utils/StorageManager/setup'; import useWalletStore from '../store/useWalletStore'; @@ -9,7 +9,7 @@ import { useFocusEffect } from '@react-navigation/native'; const debug = Debug('tonomy-id:hooks:useAssets'); -const useCryptoAssets = ({ setAccounts, setAssetLoading }) => { +const useFetchCrytpoAccount = ({ setAccounts, setAssetLoading }) => { const { accountsInitialized, initializeWalletAccount } = useWalletStore(); const { user } = useUserStore(); @@ -79,4 +79,4 @@ const useCryptoAssets = ({ setAccounts, setAssetLoading }) => { return { fetchCryptoAssets }; }; -export default useCryptoAssets; +export default useFetchCrytpoAccount; diff --git a/src/hooks/useUpdateBalances.ts b/src/hooks/useUpdateBalances.ts index ee460ed03..46fa005ac 100644 --- a/src/hooks/useUpdateBalances.ts +++ b/src/hooks/useUpdateBalances.ts @@ -1,4 +1,4 @@ -import { useCallback, useRef, useState } from 'react'; +import { useCallback, useRef } from 'react'; import { isNetworkError } from '../utils/errors'; import useWalletStore from '../store/useWalletStore'; import Debug from 'debug'; From a7c87c5ea2e0f840ec9df72f29c87b6215422559 Mon Sep 17 00:00:00 2001 From: sadiabbasi Date: Wed, 27 Nov 2024 17:23:11 +0300 Subject: [PATCH 6/7] fixed loading view in select asset --- src/containers/SelectAssetContainer.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/containers/SelectAssetContainer.tsx b/src/containers/SelectAssetContainer.tsx index 28533a437..53bdb53d2 100644 --- a/src/containers/SelectAssetContainer.tsx +++ b/src/containers/SelectAssetContainer.tsx @@ -109,9 +109,8 @@ const SelectAssetContainer = ({ {refreshBalance ? ( From 9260b35cade681049dc69cb84d106c1996d78030 Mon Sep 17 00:00:00 2001 From: sadiabbasi Date: Wed, 27 Nov 2024 17:26:13 +0300 Subject: [PATCH 7/7] revert the dimension to 4 --- src/store/useWalletStore.ts | 2 +- src/utils/StorageManager/repositories/assetStorageManager.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/store/useWalletStore.ts b/src/store/useWalletStore.ts index 74b050cd9..b87801f44 100644 --- a/src/store/useWalletStore.ts +++ b/src/store/useWalletStore.ts @@ -183,7 +183,7 @@ const useWalletStore = create((set, get) => ({ const { token } = await getTokenEntryByChain(chain); const balance = await token.getBalance(account); - debug(`updateBalance() ${chain.getName()} balance:`, await balance.toString(7)); + debug(`updateBalance() ${chain.getName()} balance:`, await balance.toString(4)); await assetStorage.updateAccountBalance(balance); } catch (error) { console.error(`updateBalance() Error fetching balance ${chain.getName()}:`, error); diff --git a/src/utils/StorageManager/repositories/assetStorageManager.ts b/src/utils/StorageManager/repositories/assetStorageManager.ts index d1ad53df1..aca2c1d7b 100644 --- a/src/utils/StorageManager/repositories/assetStorageManager.ts +++ b/src/utils/StorageManager/repositories/assetStorageManager.ts @@ -29,7 +29,7 @@ export abstract class AssetStorageManager { const existingAsset = await this.repository.findAssetByName(name); if (existingAsset) { - const balance = asset.toString(6); + const balance = asset.toString(4); debug(`updateAccountBalance() updating ${name} balance to ${balance}`);