Merge pull request #276 from ArtemKolodko/improve_tx_loading

Improve tx loading; remove default "0" value for fee and gasPrice
pull/277/head
Artem 2 years ago committed by GitHub
commit 412ed1223a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      src/components/transaction/TransactionDetails.tsx
  2. 11
      src/components/ui/utils.tsx
  3. 2
      src/pages/StackingTransactionPage/index.tsx
  4. 170
      src/pages/TransactionPage/index.tsx

@ -68,7 +68,7 @@ type TransactionDetailsProps = {
stakingData?: boolean; stakingData?: boolean;
logs?: Log[]; logs?: Log[];
errorMsg: string | undefined; errorMsg: string | undefined;
shorMoreHide?: boolean; hideShowMore?: boolean;
}; };
type tableEntry = { type tableEntry = {
@ -108,7 +108,7 @@ export const TransactionDetails: FunctionComponent<TransactionDetailsProps> = ({
type, type,
logs = [], logs = [],
errorMsg, errorMsg,
shorMoreHide, hideShowMore,
stakingData, stakingData,
internalTxs = [], internalTxs = [],
inputSignature inputSignature
@ -197,7 +197,7 @@ export const TransactionDetails: FunctionComponent<TransactionDetailsProps> = ({
}} }}
/> />
</Box> </Box>
{shorMoreHide ? null : ( {hideShowMore ? null : (
<Box align="center" justify="center" style={{ userSelect: "none" }}> <Box align="center" justify="center" style={{ userSelect: "none" }}>
<Anchor <Anchor
onClick={() => setShowDetails(!showDetails)} onClick={() => setShowDetails(!showDetails)}

@ -2,6 +2,7 @@ import Big from "big.js";
import React from "react"; import React from "react";
import { useONEExchangeRate } from "src/hooks/useONEExchangeRate"; import { useONEExchangeRate } from "src/hooks/useONEExchangeRate";
import { calculateFee } from "../../utils/fee"; import { calculateFee } from "../../utils/fee";
import {RPCStakingTransactionHarmony, RPCTransactionHarmony} from "../../types";
export function formatNumber( export function formatNumber(
num: number, num: number,
@ -33,6 +34,10 @@ Big.PE = 15;
export function CalculateFee(transaction: any) { export function CalculateFee(transaction: any) {
const { lastPrice } = useONEExchangeRate(); const { lastPrice } = useONEExchangeRate();
if(!(transaction && transaction.gasPrice)) {
return ''
}
const fee = isNaN(transaction.gasPrice) const fee = isNaN(transaction.gasPrice)
? 0 ? 0
: Number(transaction.gasPrice) / 10 ** 14 / 10000; : Number(transaction.gasPrice) / 10 ** 14 / 10000;
@ -67,9 +72,13 @@ export function CalculateFee(transaction: any) {
); );
} }
export function CalculateTransactionFee(transaction: any) { export function CalculateTransactionFee(transaction: RPCTransactionHarmony | RPCStakingTransactionHarmony) {
const { lastPrice: price } = useONEExchangeRate(); const { lastPrice: price } = useONEExchangeRate();
if(!(transaction && transaction.gas)) {
return ''
}
const fee = calculateFee(transaction.gas, transaction.gasPrice) const fee = calculateFee(transaction.gas, transaction.gasPrice)
const bi = const bi =

@ -97,7 +97,7 @@ export const StakingTransactionPage = () => {
type={subTypeMap[tx.type] || ""} type={subTypeMap[tx.type] || ""}
stakingData stakingData
errorMsg={""} errorMsg={""}
shorMoreHide={true} hideShowMore={true}
/> />
</BasePage> </BasePage>
); );

@ -29,6 +29,29 @@ const extractError = (err: any) => {
return errorMessage || err; return errorMessage || err;
}; };
const getTxInputSignature = async (trx: RPCTransactionHarmony) => {
let signature
try {
const signatures = await getByteCodeSignatureByHash([trx.input.slice(0, 10)])
if(signatures && signatures.length > 0) {
signature = signatures[0]
}
} catch (e) {
console.error('Cannot get tx input signature: ', (e as Error).message)
}
return signature
}
const getTransactionErrorMessage = (txHash: string, tx: RPCTransactionHarmony) => {
if(txHash.length !== 66) {
return 'Invalid Txn hash'
}
if(!tx || !tx.hash) {
return 'Unable to locate this TxnHash'
}
return ''
}
export const TransactionPage = () => { export const TransactionPage = () => {
const history = useHistory(); const history = useHistory();
const { id } = useParams<{id: string}>(); const { id } = useParams<{id: string}>();
@ -40,27 +63,13 @@ export const TransactionPage = () => {
const [txReceipt, setTxReceipt] = useState<TxReceipt>(); const [txReceipt, setTxReceipt] = useState<TxReceipt>();
const [trxs, setTrxs] = useState<InternalTransaction[]>([]); const [trxs, setTrxs] = useState<InternalTransaction[]>([]);
const [logs, setLogs] = useState<any[]>([]); const [logs, setLogs] = useState<any[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState(false);
const [txrsLoading, setTxrsLoading] = useState<boolean>(true);
const [activeIndex, setActiveIndex] = useState(+activeTab); const [activeIndex, setActiveIndex] = useState(+activeTab);
const [inputSignature, setInputSignature] = useState<IHexSignature>() const [inputSignature, setInputSignature] = useState<IHexSignature>()
const { availableShards } = config const { availableShards } = config
useEffect(() => { useEffect(() => {
const getTxInputSignature = async (trx: RPCTransactionHarmony) => {
let signature
try {
const signatures = await getByteCodeSignatureByHash([trx.input.slice(0, 10)])
if(signatures && signatures.length > 0) {
signature = signatures[0]
}
} catch (e) {
console.error('Cannot get tx input signature: ', (e as Error).message)
}
return signature
}
const getTx = async () => { const getTx = async () => {
let trx; let trx;
let trxInputSignature; let trxInputSignature;
@ -98,19 +107,16 @@ export const TransactionPage = () => {
} }
} }
setTx((trx || {}) as RPCTransactionHarmony); const txData = trx || {}
setTx(txData as RPCTransactionHarmony);
setInputSignature(trxInputSignature) setInputSignature(trxInputSignature)
return txData
}; };
getTx();
}, [id]);
useEffect(() => {
const getInternalTxs = async () => { const getInternalTxs = async () => {
if (tx.hash && tx.shardID === 0) { if (tx.hash && tx.shardID === 0) {
try { //@ts-ignore
//@ts-ignore const txs = await getInternalTransactionsByField([
const txs = await getInternalTransactionsByField([
0, 0,
"transaction_hash", "transaction_hash",
tx.hash, tx.hash,
@ -118,76 +124,70 @@ export const TransactionPage = () => {
// need to track fallback // need to track fallback
tx.blockNumber tx.blockNumber
); );
const methodSignatures = await Promise.all( const methodSignatures = await Promise.all(
txs.map((tx) => { txs.map((tx) => {
return tx.input && tx.input.length > 10 return tx.input && tx.input.length > 10
? getByteCodeSignatureByHash([tx.input.slice(0, 10)]) ? getByteCodeSignatureByHash([tx.input.slice(0, 10)])
: Promise.resolve([]); : Promise.resolve([]);
}) })
); );
const txsWithSignatures = txs.map((l, i) => ({ const txsWithSignatures = txs.map((l, i) => ({
...l, ...l,
signatures: methodSignatures[i], signatures: methodSignatures[i],
})); }));
setTrxs(txsWithSignatures as InternalTransaction[]); setTrxs(txsWithSignatures as InternalTransaction[]);
setTxrsLoading(false);
} catch (err) {
console.log(err);
}
} else { } else {
setTrxs([]); setTrxs([]);
} }
}; };
getInternalTxs();
}, [tx.hash]);
useEffect(() => {
const getLogs = async () => { const getLogs = async () => {
//
const contractShardID = process.env.REACT_APP_CONTRACT_SHARD ? (process.env.REACT_APP_CONTRACT_SHARD || 0) : 0 const contractShardID = process.env.REACT_APP_CONTRACT_SHARD ? (process.env.REACT_APP_CONTRACT_SHARD || 0) : 0
if (tx.hash && [0, contractShardID].includes(tx.shardID)) { if (tx.hash && [0, contractShardID].includes(tx.shardID)) {
//@ts-ignore
const logs: any[] = await getTransactionLogsByField([
0,
"transaction_hash",
tx.hash,
]);
// const SevenDaysBlock = 60 * 60 * 24 * 7 / 2 const logsSignatures = await Promise.all(
// const txDate = new Date(tx.timestamp).getTime() logs.map((l) => getByteCodeSignatureByHash([l.topics[0]]))
// const now = Date.now() );
//
// if (now - txDate > SevenDaysBlock) {
// console.log('no logs served')
// return
// }
try {
//@ts-ignore
const logs: any[] = await getTransactionLogsByField([
0,
"transaction_hash",
tx.hash,
]);
const logsSignatures = await Promise.all(
logs.map((l) => getByteCodeSignatureByHash([l.topics[0]]))
);
const logsWithSignatures = logs.map((l, i) => ({ const logsWithSignatures = logs.map((l, i) => ({
...l, ...l,
signatures: logsSignatures[i], signatures: logsSignatures[i],
})); }));
setLogs(logsWithSignatures as any); setLogs(logsWithSignatures as any);
setIsLoading(false);
} catch (err) {
console.log(err);
}
} else { } else {
setLogs([]); setLogs([]);
} }
}; };
getLogs(); const loadTxData = async () => {
}, [tx]); let tx = {}
try {
setIsLoading(true)
tx = await getTx()
} catch (e) {
console.log('Cannot load tx data:', e)
} finally {
setIsLoading(false)
}
if(tx) {
try {
await Promise.allSettled([getLogs(), getInternalTxs()])
} catch (e) {
console.log('Cannot load transaction logs:', e)
}
}
}
loadTxData()
}, [tx.hash]);
if (isLoading) { if (isLoading) {
return ( return (
@ -197,15 +197,14 @@ export const TransactionPage = () => {
); );
} }
const internalErrorMsg = txrsLoading const txErrorMsg = isLoading ? '' : getTransactionErrorMessage(id, tx)
? undefined
: trxs.length const internalErrorMsg = trxs
? trxs .map((t) => t.error)
.map((t) => t.error) .filter((_) => _)
.filter((_) => _) .map(extractError)
.map(extractError) .join(",")
.join(",")
: ""
const txReceiptErrorMsg = txReceipt && txReceipt.status === 0 const txReceiptErrorMsg = txReceipt && txReceipt.status === 0
? 'Failed (from receipt)' ? 'Failed (from receipt)'
: '' : ''
@ -235,7 +234,8 @@ export const TransactionPage = () => {
logs={logs} logs={logs}
internalTxs={trxs} internalTxs={trxs}
inputSignature={inputSignature} inputSignature={inputSignature}
errorMsg={internalErrorMsg || txReceiptErrorMsg} errorMsg={txErrorMsg || internalErrorMsg || txReceiptErrorMsg}
hideShowMore={isLoading || Boolean(txErrorMsg)}
/> />
</Tab> </Tab>
{trxs.length ? ( {trxs.length ? (

Loading…
Cancel
Save