From d0e299c1a8311f85ad905ad0103969092a6ad5d2 Mon Sep 17 00:00:00 2001 From: Tien Nam Dao Date: Tue, 18 Oct 2022 15:51:06 +0700 Subject: [PATCH] fix: rawTrace + get evm tx with cosmos hash --- api/api_list.ts | 16 +++++---- .../Card/CardInfo/Components/Decode.tsx | 2 +- components/Loader/PageLoader.tsx | 5 ++- next.config.js | 2 +- pages/tx/[tx].tsx | 9 ++--- types/transactions.d.ts | 9 +++++ utils/helper.ts | 8 ++--- views/transactions/DecodeInput.tsx | 35 ++++++++++--------- .../TransactionRowContentMobile.tsx | 2 +- views/transactions/TransactionTabs.tsx | 21 +++-------- views/transactions/hook/useTxRawTrace.ts | 26 ++++++++++++++ views/transactions/utils.ts | 32 +++++++++++++++-- 12 files changed, 113 insertions(+), 54 deletions(-) create mode 100644 views/transactions/hook/useTxRawTrace.ts diff --git a/api/api_list.ts b/api/api_list.ts index 63fc8ef4..f2335d23 100644 --- a/api/api_list.ts +++ b/api/api_list.ts @@ -1,16 +1,17 @@ const API_LIST = { SEARCH: '/search?keyword=', - ALL_BLOCKS: '/blocks', - BLOCKS: '/blocks/', - TRANSACTION_OF_BLOCK: '/blocks/:id/transactions?pagination=offset&page=1&limit=20&order=height.desc', + ALL_BLOCKS: '/api/v1/blocks', + BLOCKS: '/api/v1/blocks/', + TRANSACTION_OF_BLOCK: '/api/v1/blocks/:id/transactions?pagination=offset&page=1&limit=20&order=height.desc', LATEST_BLOCK: 'evm_/api/v1?module=block&action=eth_block_number', ALL_TOKENS: 'evm_/api/v1?module=token&action=getListTokens', // &page=1&offset=20 ALL_HOLDERS: 'evm_/api/v1?module=account&action=getTopAddressesBalance', // &page=1&offset=20 - ALL_TRANSACTIONS: '/transactions', + ALL_TRANSACTIONS: '/api/v1/transactions', - TRANSACTIONS: '/transactions/', + TRANSACTIONS: '/api/v1/transactions', + EVM_TRANSACTION_DETAIL_WITH_COSMOSHASH: '/api/v1/transactions', // call axios EVM_TRANSACTION_DETAIL: '/api/v1?module=transaction&action=gettxinfo&txhash=', // call axios EVM_INTERNAL_TRANSACTION: 'evm_/api/v1?module=account&action=txlistinternal&txhash=', // call axios COSMOS_TRANSACTION: '/api/v1?module=transaction&action=getTxCosmosInfo&txhash=', // call axios @@ -18,10 +19,11 @@ const API_LIST = { ABI: '/api/v1?module=contract&action=getabi&address=', HASH_ABI: '/api/v1?module=transaction&action=getabibytxhash&txhash=', - VALIDATORS: 'http://128.199.238.171:8080/api/v1/validators', + VALIDATORS: '/api/v1/validators', MARKET_HISTORY_PRICE: 'evm_/api/v1/market-history-chart', TRANSACTION_HISTORY_COUNTER: 'evm_/api/v1/transaction-history-chart', + TRANSACTION_RAW_TRACE: 'evm_/api/v1?module=transaction&action=getrawtracebytxhash', // txhash MARKET_PRICE: 'https://api.tiki.vn/sandseel/api/v2/public/markets/astra/summary', COMMON_STATS: 'evm_/api/v1/common-stats', @@ -33,7 +35,7 @@ const API_LIST = { ADDRESS_BALANCE: 'evm_/api/v1?module=account&action=balance', // address=? ADDRESS_COIN_BALANCE_HISTORY: 'evm_/api/v1?module=account&action=getcoinbalancehistory', // address, page, offset=? ADDRESS_COIN_BALANCE_HISTORY_CHART: 'evm_/address', // address, page, offset=? - ADDRESS_TRANSACTION: 'http://128.199.238.171:8080/api/v1/accounts', + ADDRESS_TRANSACTION: '/api/v1/accounts', ADDRESS_INTERNAL_TRANSACTION: 'evm_/api/v1?module=account&action=txlistinternal', // address, page, offset ADDRESS_TOKEN_TRANSFER: 'evm_/api/v1?module=account&action=getlisttokentransfers', // address=? diff --git a/components/Card/CardInfo/Components/Decode.tsx b/components/Card/CardInfo/Components/Decode.tsx index a141efab..d8f65d53 100644 --- a/components/Card/CardInfo/Components/Decode.tsx +++ b/components/Card/CardInfo/Components/Decode.tsx @@ -74,7 +74,7 @@ export default function Decode({ methodId, call, items }: DecodeProps) { ) } ]} - rows={items as any[]} + rows={(items as any[]) || []} classes={{ wapper: styles.table }} /> diff --git a/components/Loader/PageLoader.tsx b/components/Loader/PageLoader.tsx index 555ec36c..2ad058fd 100644 --- a/components/Loader/PageLoader.tsx +++ b/components/Loader/PageLoader.tsx @@ -11,7 +11,10 @@ function PageLoader() { useEffect(() => { const handleStart = url => url !== router.asPath && setLoading(true) - const handleComplete = url => url?.includes(router.asPath) && setLoading(false) + const handleComplete = url => { + if (!url) return setLoading(false) + return url?.includes(router.asPath) && setLoading(false) + } router.events.on('routeChangeStart', handleStart) router.events.on('routeChangeComplete', handleComplete) diff --git a/next.config.js b/next.config.js index b11327ef..cef175a6 100644 --- a/next.config.js +++ b/next.config.js @@ -2,7 +2,7 @@ const nextConfig = { reactStrictMode: false, env: { - NEXT_PUBLIC_COSMOS_API: 'http://128.199.238.171:8080/api/v1', + NEXT_PUBLIC_COSMOS_API: 'http://128.199.238.171:8080', NEXT_PUBLIC_EVM_API: 'https://explorer.astranaut.dev', NEXT_PUBLIC_BLOCK_INTERVAL: '5000', NEXT_PUBLIC_TRANSACTION_INTERVAL: '5000', diff --git a/pages/tx/[tx].tsx b/pages/tx/[tx].tsx index acb093ff..31b02d55 100644 --- a/pages/tx/[tx].tsx +++ b/pages/tx/[tx].tsx @@ -65,18 +65,19 @@ export async function getServerSideProps({ query }) { /** * @todo nhap65 hash vao tu chuyen trang */ - const { tx } = query as TransactionQuery + const { tx, type } = query as TransactionQuery + let evmHash = '' let cosmosHash = '' try { let data: TransactionDetail = {} //evm - if (tx.startsWith('0x')) { - evmHash = tx + if (tx.startsWith('0x') || type == 'evm') { data = await evmTransactionDetail(tx) + evmHash = tx.startsWith('0x') ? tx : data.evmHash } else { // get detail from cosmos hash - const cosmosDetailRes = await cosmosApi.get(`${API_LIST.TRANSACTIONS}${tx}`) + const cosmosDetailRes = await cosmosApi.get(`${API_LIST.TRANSACTIONS}/${tx}`) let _data = cosmosDetailRes?.data?.result const type = _data?.messages[0]?.type cosmosHash = _data.hash diff --git a/types/transactions.d.ts b/types/transactions.d.ts index 18900b85..51c41d81 100644 --- a/types/transactions.d.ts +++ b/types/transactions.d.ts @@ -69,6 +69,7 @@ interface EvmLog { } interface EVMTransactionDetail { blockNumber: string + blockTime: string confirmations: string from: string gasLimit: string @@ -116,6 +117,14 @@ interface InternalTransactionReponse { status: string } +interface TransactionRawTraceResponse { + message: string + result: { + rawTrace: any[] + } + status: string +} + interface EvmTransactionDetailFromCosmosHashResponse { message: string result: { diff --git a/utils/helper.ts b/utils/helper.ts index a00155fd..a9bbd9dd 100644 --- a/utils/helper.ts +++ b/utils/helper.ts @@ -48,10 +48,10 @@ export function formatCurrencyValue(value: number | string | undefined, symbol = export function formatGasValue(value) { if (isNaN(value) || isUndefined(value)) return 'NaN' if (value === 0 || value === '0') return `0` - if (value <= 1000) return `${numeral(value).format('0,0')} GWEI` + if (value <= 1000) return `${numeral(value).format('0,0')} NanoAstra` // if (value <= 1000) return `${numeral(value).format('0,0')} MWEI` - if (value <= 1000000) return `${numeral(value / 10 ** 3).format('0,0')} KWEI` - if (value <= 1000000000) return `${numeral(value / 10 ** 6).format('0,0')} WEI` + if (value <= 1000000) return `${numeral(value / 10 ** 3).format('0,0')} MicroAstra` + if (value <= 1000000000) return `${numeral(value / 10 ** 6).format('0,0')} Astra` return `${numeral(value).format('0,0')}` } @@ -85,7 +85,7 @@ export class LinkMaker { * @returns */ static transaction(hash?: string, query: string = '') { - hash = hash ? `/${hash}${query}` : '' + hash = hash ? `/${hash}?${query}` : '' return `/tx${hash}` } diff --git a/views/transactions/DecodeInput.tsx b/views/transactions/DecodeInput.tsx index 9410e716..27026cbb 100644 --- a/views/transactions/DecodeInput.tsx +++ b/views/transactions/DecodeInput.tsx @@ -21,9 +21,6 @@ type DecodeInputProps = { } export default function DecodeInput({ dataInput, address, evmHash }: DecodeInputProps) { - if (!dataInput || !address) { - return null - } const [load, setLoad] = useState(false) const [items, setItems] = useState() @@ -64,28 +61,34 @@ export default function DecodeInput({ dataInput, address, evmHash }: DecodeInput if (Array.isArray(abi)) { abiDecoder.addABI(abi) const inputObj = abiDecoder.decodeMethod(dataInput) as AbiItemDecode - const name = inputObj.name + const name = inputObj?.name const interfaceItem = abi.find(item => item.name === name) - const params = interfaceItem.inputs - const call = `${interfaceItem.name}(${interfaceItem.inputs - .map(input => `${input.type} ${input.indexed ? 'indexed' : ''} ${input.name}`) - .join(', ')})` - item.call = call - item.callRow = call - for (let para of params) { - const input = inputObj?.params.find(input => input.name === para.name) - if (input) { - input.indexed = para.indexed + if (interfaceItem) { + const params = interfaceItem.inputs + const call = `${interfaceItem.name}(${interfaceItem.inputs + .map(input => `${input.type} ${input.indexed ? 'indexed' : ''} ${input.name}`) + .join(', ')})` + item.call = call + item.callRow = call + for (let para of params) { + const input = inputObj?.params.find(input => input.name === para.name) + if (input) { + input.indexed = para.indexed + } } } - item.methodParams = inputObj.params + item.methodParams = inputObj?.params } setItems(items) } setLoad(true) } data() - }, [dataInput]) + }, [address, dataInput]) + + if (!dataInput || !address) { + return null + } return (
diff --git a/views/transactions/TransactionRowContentMobile.tsx b/views/transactions/TransactionRowContentMobile.tsx index be7924eb..bc6c4853 100644 --- a/views/transactions/TransactionRowContentMobile.tsx +++ b/views/transactions/TransactionRowContentMobile.tsx @@ -32,7 +32,7 @@ export default function TransactionRowContentMobile({
diff --git a/views/transactions/TransactionTabs.tsx b/views/transactions/TransactionTabs.tsx index 771f160e..609cd738 100644 --- a/views/transactions/TransactionTabs.tsx +++ b/views/transactions/TransactionTabs.tsx @@ -4,6 +4,7 @@ import Empty from 'components/Typography/Empty' import { useState } from 'react' import { isEmptyRawInput } from 'utils/evm' import useInternalTransactions from './hook/useInternalTransactions' +import useTxRawTrace from './hook/useTxRawTrace' import Log from './Log' import RawTrace from './RawTrace' import TransactionRow, { TransactionRowProps } from './TransactionRow' @@ -45,6 +46,8 @@ export default function TransactionTabs({ const { rows: internalTransactionRows } = useInternalTransactions({ hash: hashInternalTransactions ? evmHash : null }) + + const rawTrace = useTxRawTrace(evmHash, type) const _tabChange = (tabId: string) => { setTabId(tabId) } @@ -55,23 +58,7 @@ export default function TransactionTabs({ ] const contents = { log: , - trace: ( - - ) + trace: } if (type === 'cosmos') { diff --git a/views/transactions/hook/useTxRawTrace.ts b/views/transactions/hook/useTxRawTrace.ts new file mode 100644 index 00000000..f4e1599e --- /dev/null +++ b/views/transactions/hook/useTxRawTrace.ts @@ -0,0 +1,26 @@ +import API_LIST from 'api/api_list' +import { useEffect, useState } from 'react' +import useSWR from 'swr' + +export default function useTxRawTrace(txhash: string, type: 'evm' | 'cosmos') { + const [hookData, setState] = useState({ result: '' }) + + const _fetchCondition = () => { + if (type === 'cosmos') return '' + + return [ + `${API_LIST.TRANSACTION_RAW_TRACE}`, + { + txhash + } + ] + } + const { data } = useSWR(_fetchCondition()) + + useEffect(() => { + if (data) { + setState({ result: data.result.rawTrace }) + } + }, [data]) + return hookData.result +} diff --git a/views/transactions/utils.ts b/views/transactions/utils.ts index 16303867..4e657a0c 100644 --- a/views/transactions/utils.ts +++ b/views/transactions/utils.ts @@ -2,6 +2,7 @@ import { astraToEth } from '@astradefi/address-converter' import { formatNumber } from '@astraprotocol/astra-ui' import { cosmosApi, evmApi } from 'api' import API_LIST from 'api/api_list' +import dayjs from 'dayjs' import { formatEther, formatUnits } from 'ethers/lib/utils' import numeral from 'numeral' import { TransacionTypeEnum } from 'utils/constants' @@ -108,7 +109,7 @@ export const evmTransactionDetail = async (evmHash?: string, cosmosHash?: string } if (cosmosHash) { const cosmosDetailRes = await cosmosApi.get( - `${API_LIST.TRANSACTIONS}${cosmosHash}?type=evm` + `${API_LIST.TRANSACTIONS}/${cosmosHash}?type=evm` ) const result = cosmosDetailRes.data.result data.evmHash = result.hash @@ -148,8 +149,9 @@ export const evmTransactionDetail = async (evmHash?: string, cosmosHash?: string result.blockHeight ) data.logs = result.logs - } else { + } else if (evmHash.startsWith('0x')) { const evmRes = await evmApi.get(`${API_LIST.EVM_TRANSACTION_DETAIL}${evmHash}`) + const result = evmRes.data.result data.evmHash = result.hash // data.cosmosHash = undefined @@ -172,6 +174,32 @@ export const evmTransactionDetail = async (evmHash?: string, cosmosHash?: string // data.nonce = undefined data.rawInput = isEmptyRawInput(result.input) ? undefined : result.input // data.tokenTransfers = result?.tokenTransfers + } else { + const evmRes = await cosmosApi.get( + `${API_LIST.EVM_TRANSACTION_DETAIL_WITH_COSMOSHASH}/${evmHash}?type=evm` + ) + const result = evmRes.data.result + data.evmHash = result.hash + // data.cosmosHash = undefined + data.result = result.success ? 'Success' : 'Error' + data.confirmations = result.confirmations + data.blockHeight = result.blockNumber + data.time = dayjs(result.blockTime).valueOf() + data.from = result.from + data.to = result.to + // data.tokenTransfer = [] + data.value = formatEther(result.value) + data.fee = undefined + data.gasPrice = formatUnits(result.gasPrice, 9) + ' NanoAstra' + data.gasLimit = formatNumber(result.gasLimit, 0) + data.gasUsed = result.gasUsed + // data.maxFeePerGas = undefined + // data.maxPriorityFeePerGas = undefined + // data.priorityFeePerGas = undefined + // data.gasUsedByTransaction = undefined + // data.nonce = undefined + data.rawInput = isEmptyRawInput(result.input) ? undefined : result.input + // data.tokenTransfers = result?.tokenTransfers } return data