diff --git a/src/frontend/account/AccountDetail/AccountDetail.tsx b/src/frontend/account/AccountDetail/AccountDetail.tsx index da4b214..ae5d8f6 100644 --- a/src/frontend/account/AccountDetail/AccountDetail.tsx +++ b/src/frontend/account/AccountDetail/AccountDetail.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' import { useRouter } from 'next/router' import web3 from 'web3' -import { utils } from 'ethers' +import { ethers } from 'ethers' import moment from 'moment' import { Button, ContentLayout, CopyButton, Spacer, Pagination } from '../../components' import { Tab } from '../../components/Tab' @@ -245,12 +245,22 @@ export const AccountDetail: React.FC = () => { { key: 'Max Total Supply :', value: account?.contractInfo?.totalSupply - ? utils - .formatUnits( - account?.contractInfo?.totalSupply, - account?.contractInfo?.decimals ? parseInt(account?.contractInfo?.decimals) : 18 - ) - .toString() + ? (() => { + try { + const totalSupply = typeof account.contractInfo.totalSupply === 'number' + ? account.contractInfo.totalSupply.toLocaleString('fullwide', { useGrouping: false }) + : account.contractInfo.totalSupply.toString() + return ethers + .formatUnits( + totalSupply, + account?.contractInfo?.decimals ? parseInt(account?.contractInfo?.decimals) : 18 + ) + .toString() + } catch (error) { + console.error('Error formatting total supply:', error) + return account.contractInfo.totalSupply.toString() + } + })() : '', }, ]} diff --git a/src/frontend/account/AccountDetail/useAccountDetailHook.ts b/src/frontend/account/AccountDetail/useAccountDetailHook.ts index b062d3b..12115cd 100644 --- a/src/frontend/account/AccountDetail/useAccountDetailHook.ts +++ b/src/frontend/account/AccountDetail/useAccountDetailHook.ts @@ -1,7 +1,7 @@ import { useCallback, useEffect, useState } from 'react' import { api, PATHS } from '../../api' import { Account, AccountType, ContractType, Token, Transaction, TransactionSearchType } from '../../../types' -import { BigNumberish, utils } from 'ethers' +import { BigNumberish, ethers } from 'ethers' interface detailProps { id: string @@ -83,12 +83,12 @@ export const useAccountDetailHook = ({ id, txType }: detailProps): AccountDetail (accounts && accounts.length > 0 && accounts[0].accountId) ) { const { tokens } = await getToken() - if (tokens.length > 0) { + if (tokens && tokens.length > 0) { tokens.forEach( - (item: { contractType: ContractType; contractInfo: { decimals: string }; balance: BigNumberish }) => { + (item: { contractType: ContractType; contractInfo: { decimals: string } | null; balance: BigNumberish }) => { if (item.contractType === ContractType.ERC_20) { - const decimalsValue = item.contractInfo.decimals ? parseInt(item.contractInfo.decimals) : 18 - item.balance = utils.formatUnits(item.balance, decimalsValue) + const decimalsValue = item.contractInfo?.decimals ? parseInt(item.contractInfo.decimals) : 18 + item.balance = ethers.formatUnits(item.balance, decimalsValue) } } ) diff --git a/src/frontend/account/TokenDropdown/TokenDropdown.tsx b/src/frontend/account/TokenDropdown/TokenDropdown.tsx index f74c60a..3e2e39b 100644 --- a/src/frontend/account/TokenDropdown/TokenDropdown.tsx +++ b/src/frontend/account/TokenDropdown/TokenDropdown.tsx @@ -53,14 +53,19 @@ export const TokenDropdown: React.FC = (props) => {
- ERC-20 Tokens (1) + ERC-20 Tokens ({tokens.length})
setIsSortUp(!isSortUp)} />
{ tokens && tokens.length > 0 ? ( tokens?.map((row, index) => ( - + )) ) : (
No Tokens Found!
diff --git a/src/frontend/token/Token.tsx b/src/frontend/token/Token.tsx index 1b181d7..c583057 100644 --- a/src/frontend/token/Token.tsx +++ b/src/frontend/token/Token.tsx @@ -1,6 +1,6 @@ import React from 'react' import { useRouter } from 'next/router' -import { utils } from 'ethers' +import { ethers } from 'ethers' import { AnchorLink, Button, ContentLayout, CopyButton, Spacer, Tab, Table, Pagination } from '../components' import { DetailCard } from '../account/DetailCard' @@ -59,12 +59,20 @@ export const Token: React.FC = () => { {val ? transactionType === TransactionSearchType.ERC_721 ? val - : utils - .formatUnits( - val as number, - account?.contractInfo?.decimals ? parseInt(account?.contractInfo?.decimals) : 18 - ) - .toString() + : (() => { + try { + const valueStr = typeof val === 'number' + ? val.toLocaleString('fullwide', { useGrouping: false }) + : val.toString() + return ethers.formatUnits( + valueStr, + account?.contractInfo?.decimals ? parseInt(account?.contractInfo?.decimals) : 18 + ).toString() + } catch (error) { + console.error('Error formatting token value:', error, val) + return val.toString() + } + })() : ''} ), @@ -157,12 +165,20 @@ export const Token: React.FC = () => { { key: 'Max Total Supply :', value: account?.contractInfo?.totalSupply - ? utils - .formatUnits( - account?.contractInfo?.totalSupply, - account?.contractInfo?.decimals ? parseInt(account?.contractInfo?.decimals) : 18 - ) - .toString() + ? (() => { + try { + const totalSupply = typeof account.contractInfo.totalSupply === 'number' + ? account.contractInfo.totalSupply.toLocaleString('fullwide', { useGrouping: false }) + : account.contractInfo.totalSupply.toString() + return ethers.formatUnits( + totalSupply, + account?.contractInfo?.decimals ? parseInt(account?.contractInfo?.decimals) : 18 + ).toString() + } catch (error) { + console.error('Error formatting total supply:', error) + return account.contractInfo.totalSupply.toString() + } + })() : '', }, { key: 'Holders :', value: totalTokenHolders }, @@ -178,12 +194,20 @@ export const Token: React.FC = () => { { key: 'Max Total Supply :', value: account?.contractInfo?.totalSupply - ? utils - .formatUnits( - account?.contractInfo?.totalSupply, - account?.contractInfo?.decimals ? parseInt(account?.contractInfo?.decimals) : 18 - ) - .toString() + ? (() => { + try { + const totalSupply = typeof account.contractInfo.totalSupply === 'number' + ? account.contractInfo.totalSupply.toLocaleString('fullwide', { useGrouping: false }) + : account.contractInfo.totalSupply.toString() + return ethers.formatUnits( + totalSupply, + account?.contractInfo?.decimals ? parseInt(account?.contractInfo?.decimals) : 18 + ).toString() + } catch (error) { + console.error('Error formatting total supply:', error) + return account.contractInfo.totalSupply.toString() + } + })() : '', }, ]} @@ -220,12 +244,20 @@ export const Token: React.FC = () => { {tokenBalance ? transactionType === TransactionSearchType.ERC_721 ? tokenBalance - : utils - .formatUnits( - tokenBalance, - account?.contractInfo?.decimals ? parseInt(account?.contractInfo?.decimals) : 18 - ) - .toString() + : (() => { + try { + const balanceStr = typeof tokenBalance === 'number' + ? tokenBalance.toLocaleString('fullwide', { useGrouping: false }) + : tokenBalance.toString() + return ethers.formatUnits( + balanceStr, + account?.contractInfo?.decimals ? parseInt(account?.contractInfo?.decimals) : 18 + ).toString() + } catch (error) { + console.error('Error formatting token balance:', error, tokenBalance) + return tokenBalance.toString() + } + })() : ''} diff --git a/src/frontend/transaction/TransactionDetail/Overview/Ovewview.tsx b/src/frontend/transaction/TransactionDetail/Overview/Ovewview.tsx index 6662e54..2c2860c 100644 --- a/src/frontend/transaction/TransactionDetail/Overview/Ovewview.tsx +++ b/src/frontend/transaction/TransactionDetail/Overview/Ovewview.tsx @@ -23,6 +23,16 @@ export const Ovewview: React.FC = ({ transaction }) => { const internalTxType = isInternalTx ? transaction.wrappedEVMAccount?.readableReceipt?.internalTx?.internalTXType : undefined + + // Check if this is an ERC20 transfer transaction + const isERC20Transfer = transaction?.tokenTxs && + transaction.tokenTxs.length > 0 && + transaction.tokenTxs[0].tokenType === TokenType.ERC_20 && + (transaction.tokenTxs[0].tokenEvent === 'Transfer' || + transaction.tokenTxs[0].tokenEvent === 'Mint' || + transaction.tokenTxs[0].tokenEvent === 'Burn') + + const primaryERC20Transfer = isERC20Transfer ? transaction.tokenTxs[0] : null const renderErc20Tokens = (): JSX.Element | undefined => { const items = transaction?.tokenTxs @@ -65,7 +75,7 @@ export const Ovewview: React.FC = ({ transaction }) => { For
{calculateTokenValue(item, item.tokenType, undefined, true)} 
- {item.tokenType === TokenType.EVM_Internal ? 'SHM' : item.contractInfo.name || item.contractAddress} + {item.tokenType === TokenType.EVM_Internal ? 'SHM' : item.contractInfo?.name || item.contractAddress} ))} @@ -299,9 +309,23 @@ export const Ovewview: React.FC = ({ transaction }) => {
To:
{transaction?.wrappedEVMAccount?.readableReceipt?.to ? ( - - {transaction?.txTo} - + isERC20Transfer && primaryERC20Transfer ? ( +
+ + {primaryERC20Transfer.tokenTo} + +
+ via{' '} + + {primaryERC20Transfer.contractInfo?.name || 'Token Contract'} + +
+
+ ) : ( + + {transaction?.txTo} + + ) ) : (
= ({ transaction }) => {
Value:
- {calculateFullValue(`${transaction?.wrappedEVMAccount?.readableReceipt?.value ?? 0}`)} SHM + {isERC20Transfer && primaryERC20Transfer ? ( +
+ {calculateTokenValue(primaryERC20Transfer, primaryERC20Transfer.tokenType, undefined, true)}{' '} + {primaryERC20Transfer.contractInfo?.symbol || primaryERC20Transfer.contractAddress} + {transaction?.wrappedEVMAccount?.readableReceipt?.value !== '0x0' && ( +
+ + {calculateFullValue(`${transaction?.wrappedEVMAccount?.readableReceipt?.value ?? 0}`)} SHM +
+ )} +
+ ) : ( + `${calculateFullValue(`${transaction?.wrappedEVMAccount?.readableReceipt?.value ?? 0}`)} SHM` + )}
)} diff --git a/src/frontend/utils/calculateValue.ts b/src/frontend/utils/calculateValue.ts index 257d090..c2818bb 100644 --- a/src/frontend/utils/calculateValue.ts +++ b/src/frontend/utils/calculateValue.ts @@ -1,5 +1,5 @@ import web3 from 'web3' -import { utils } from 'ethers' +import { ethers } from 'ethers' import { TokenTx, TokenType, TransactionType } from '../../types' import BN from 'bn.js' import { fromWeiNoTrailingComma } from './fromWeiNoTrailingComma' @@ -28,13 +28,20 @@ export const calculateTokenValue = ( ): string => { try { if (txType === TokenType.ERC_20 || txType === TokenType.EVM_Internal) { - const decimalsValue = tokenTx.contractInfo.decimals ? parseInt(tokenTx.contractInfo.decimals) : 18 + const decimalsValue = tokenTx.contractInfo?.decimals ? parseInt(tokenTx.contractInfo.decimals) : 18 return tokenTx.tokenValue === '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' ? 'unlimited' - : fullValue - ? utils.formatUnits(tokenTx.tokenValue, decimalsValue) - : roundTokenValue(utils.formatUnits(tokenTx.tokenValue, decimalsValue)) + : (() => { + try { + return fullValue + ? ethers.formatUnits(tokenTx.tokenValue, decimalsValue) + : roundTokenValue(ethers.formatUnits(tokenTx.tokenValue, decimalsValue)) + } catch (error) { + console.error('Error formatting token value:', error, tokenTx.tokenValue) + return 'Error formatting value' + } + })() // : round(web3.utils.fromWei(tokenTx.tokenValue, "ether")); } else if (txType === TokenType.ERC_721) { diff --git a/src/storage/account.ts b/src/storage/account.ts index 0038561..3a8a14c 100644 --- a/src/storage/account.ts +++ b/src/storage/account.ts @@ -266,8 +266,8 @@ export async function queryTokensByAddress(address: string, detail = false): Pro if (accountExist && accountExist.contractType) { filterTokens.push({ contractAddress: contractAddress, - contractInfo: accountExist.contractInfo, - contractType: accountExist.contractType, + contractInfo: accountExist?.contractInfo || null, + contractType: accountExist?.contractType || null, balance: tokenValue, }) }