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
24 changes: 17 additions & 7 deletions src/frontend/account/AccountDetail/AccountDetail.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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()
}
})()
: '',
},
]}
Expand Down
10 changes: 5 additions & 5 deletions src/frontend/account/AccountDetail/useAccountDetailHook.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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)
}
}
)
Expand Down
9 changes: 7 additions & 2 deletions src/frontend/account/TokenDropdown/TokenDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,19 @@ export const TokenDropdown: React.FC<TokenDropdownProps> = (props) => {
<input placeholder="Search for Token Name" className={styles.search} ref={inputRef} />
<div className={styles.item}>
<div className={styles.label}>
ERC-20 Tokens <span>(1)</span>
ERC-20 Tokens <span>({tokens.length})</span>
</div>
<SortButton isUp={isSortUp} onSort={() => setIsSortUp(!isSortUp)} />
</div>
{
tokens && tokens.length > 0 ? (
tokens?.map((row, index) => (
<MenuItem key={index} label={row.balance} label2={row?.contractInfo.name} className={styles.menuItem} />
<MenuItem
key={index}
label={row.balance}
label2={row?.contractInfo?.name || row.contractAddress}
className={styles.menuItem}
/>
))
) : (
<div className={styles.empty}>No Tokens Found!</div>
Expand Down
82 changes: 57 additions & 25 deletions src/frontend/token/Token.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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()
}
})()
: ''}
</>
),
Expand Down Expand Up @@ -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 },
Expand All @@ -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()
}
})()
: '',
},
]}
Expand Down Expand Up @@ -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()
}
})()
: ''}
</div>
</div>
Expand Down
46 changes: 41 additions & 5 deletions src/frontend/transaction/TransactionDetail/Overview/Ovewview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ export const Ovewview: React.FC<OvewviewProps> = ({ 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

Expand Down Expand Up @@ -65,7 +75,7 @@ export const Ovewview: React.FC<OvewviewProps> = ({ transaction }) => {
<span>For</span>
<div>{calculateTokenValue(item, item.tokenType, undefined, true)}&nbsp;</div>
<Link href={`/account/${item.contractAddress}`} className={styles.anchor}>
{item.tokenType === TokenType.EVM_Internal ? 'SHM' : item.contractInfo.name || item.contractAddress}
{item.tokenType === TokenType.EVM_Internal ? 'SHM' : item.contractInfo?.name || item.contractAddress}
</Link>
</div>
))}
Expand Down Expand Up @@ -299,9 +309,23 @@ export const Ovewview: React.FC<OvewviewProps> = ({ transaction }) => {
<div className={styles.title}>To:</div>
<div className={styles.value}>
{transaction?.wrappedEVMAccount?.readableReceipt?.to ? (
<Link href={`/account/${transaction?.txTo}`} className={styles.link}>
{transaction?.txTo}
</Link>
isERC20Transfer && primaryERC20Transfer ? (
<div>
<Link href={`/account/${primaryERC20Transfer.tokenTo}`} className={styles.link}>
{primaryERC20Transfer.tokenTo}
</Link>
<div style={{ fontSize: '0.8em', color: '#666', marginTop: '4px' }}>
via{' '}
<Link href={`/account/${transaction?.txTo}`} className={styles.link}>
{primaryERC20Transfer.contractInfo?.name || 'Token Contract'}
</Link>
</div>
</div>
) : (
<Link href={`/account/${transaction?.txTo}`} className={styles.link}>
{transaction?.txTo}
</Link>
)
) : (
<div>
<Link
Expand Down Expand Up @@ -375,7 +399,19 @@ export const Ovewview: React.FC<OvewviewProps> = ({ transaction }) => {
<div className={styles.item}>
<div className={styles.title}>Value:</div>
<div className={styles.value}>
{calculateFullValue(`${transaction?.wrappedEVMAccount?.readableReceipt?.value ?? 0}`)} SHM
{isERC20Transfer && primaryERC20Transfer ? (
<div>
{calculateTokenValue(primaryERC20Transfer, primaryERC20Transfer.tokenType, undefined, true)}{' '}
{primaryERC20Transfer.contractInfo?.symbol || primaryERC20Transfer.contractAddress}
{transaction?.wrappedEVMAccount?.readableReceipt?.value !== '0x0' && (
<div style={{ fontSize: '0.8em', color: '#666', marginTop: '4px' }}>
+ {calculateFullValue(`${transaction?.wrappedEVMAccount?.readableReceipt?.value ?? 0}`)} SHM
</div>
)}
</div>
) : (
`${calculateFullValue(`${transaction?.wrappedEVMAccount?.readableReceipt?.value ?? 0}`)} SHM`
)}
Comment on lines +403 to +414
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The check for transaction?.wrappedEVMAccount?.readableReceipt?.value !== '0x0' may fail if the value is undefined or in a different format (e.g., '0'). Use a more robust check to ensure correct display of the SHM value. [general, importance: 6]

Suggested change
<div>
{calculateTokenValue(primaryERC20Transfer, primaryERC20Transfer.tokenType, undefined, true)}{' '}
{primaryERC20Transfer.contractInfo?.symbol || primaryERC20Transfer.contractAddress}
{transaction?.wrappedEVMAccount?.readableReceipt?.value !== '0x0' && (
<div style={{ fontSize: '0.8em', color: '#666', marginTop: '4px' }}>
+ {calculateFullValue(`${transaction?.wrappedEVMAccount?.readableReceipt?.value ?? 0}`)} SHM
</div>
)}
</div>
) : (
`${calculateFullValue(`${transaction?.wrappedEVMAccount?.readableReceipt?.value ?? 0}`)} SHM`
)}
{isERC20Transfer && primaryERC20Transfer ? (
<div>
{calculateTokenValue(primaryERC20Transfer, primaryERC20Transfer.tokenType, undefined, true)}{' '}
{primaryERC20Transfer.contractInfo?.symbol || primaryERC20Transfer.contractAddress}
{transaction?.wrappedEVMAccount?.readableReceipt?.value && transaction?.wrappedEVMAccount?.readableReceipt?.value !== '0x0' && transaction?.wrappedEVMAccount?.readableReceipt?.value !== '0' && (
<div style={{ fontSize: '0.8em', color: '#666', marginTop: '4px' }}>
+ {calculateFullValue(`${transaction?.wrappedEVMAccount?.readableReceipt?.value ?? 0}`)} SHM
</div>
)}
</div>
) : (
`${calculateFullValue(`${transaction?.wrappedEVMAccount?.readableReceipt?.value ?? 0}`)} SHM`
)}

</div>
</div>
)}
Expand Down
17 changes: 12 additions & 5 deletions src/frontend/utils/calculateValue.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions src/storage/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
}
Expand Down
Loading