Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 52 additions & 135 deletions src/containers/AssetsContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,133 +1,26 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import React, { useEffect, useMemo, 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';
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 useAssetManager from '../hooks/useAssetManager';

const debug = Debug('tonomy-id:containers:AssetsContainer');

export default function AssetsContainer({ navigation }: { navigation: AssetsScreenNavigationProp['navigation'] }) {
const [total, setTotal] = useState<number>(0);
const [isAssetLoading, setAssetLoading] = useState<boolean>(true);
const [refreshBalance, setRefreshBalance] = useState(false);
const { developerMode } = useAppSettings();

const { accountsInitialized, initializeWalletAccount, updateBalance } = useWalletStore();

const isUpdatingBalances = useRef(false);
const [accounts, setAccounts] = useState<
{ network: string; accountName: string; balance: string; usdBalance: number }[]
>([]);
const { user } = useUserStore();
const { developerMode } = useAppSettings();
const { isAssetLoading, accounts, onRefresh, refreshBalance } = useAssetManager();

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;

try {
debug('updateAllBalances()');
await updateBalance();
await fetchCryptoAssets();
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, fetchCryptoAssets]);

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]);

useEffect(() => {
const totalAssetsUSDBalance = accounts.reduce((previousValue, currentValue) => {
return previousValue + currentValue.usdBalance;
Expand Down Expand Up @@ -225,30 +118,47 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre
)}
</View>
<View style={styles.flexColEnd}>
{accountData.account ? (
<View style={styles.flexColEnd}>
<View style={styles.flexRowCenter}>
<Text style={{ fontSize: 15 }}>{accountData.balance}</Text>
</View>
<Text style={styles.secondaryColor}>
${formatCurrencyValue(accountData.usdBalance ?? 0)}
</Text>
{refreshBalance ? (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 10,
}}
>
<TSpinner size={60} />
</View>
) : (
<View>
<TouchableOpacity
onPress={() => {
navigation.navigate('CreateEthereumKey', {
requestType: 'createKey',
request: null,
transaction: null,
});
}}
>
<Text style={{ fontSize: 13 }}>Not connected</Text>
<Text style={styles.generateKey}>Generate key</Text>
</TouchableOpacity>
</View>
<>
{accountData.account ? (
<View style={styles.flexColEnd}>
<View style={styles.flexRowCenter}>
<Text style={{ fontSize: 15 }}>
{accountData.balance}
</Text>
</View>
<Text style={styles.secondaryColor}>
${formatCurrencyValue(accountData.usdBalance ?? 0)}
</Text>
</View>
) : (
<View>
<TouchableOpacity
onPress={() => {
navigation.navigate('CreateEthereumKey', {
requestType: 'createKey',
request: null,
transaction: null,
});
}}
>
<Text style={{ fontSize: 13 }}>Not connected</Text>
<Text style={styles.generateKey}>Generate key</Text>
</TouchableOpacity>
</View>
)}
</>
)}
</View>
</View>
Expand All @@ -257,8 +167,15 @@ export default function AssetsContainer({ navigation }: { navigation: AssetsScre
})}
</View>
) : (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TSpinner />
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 10,
}}
>
<TSpinner size={60} />
</View>
)}
</ScrollView>
Expand Down
Loading
Loading