Show contract calls as "Approve USDT" instead of "0.0000 ETH"
All checks were successful
check / check (push) Successful in 17s
All checks were successful
check / check (push) Successful in 17s
Contract interactions (approve, swap, etc.) now display the method name and token symbol instead of the meaningless 0 ETH value. Blockscout provides the method name and whether the target is a contract — parseTx uses these plus TOKEN_BY_ADDRESS to produce labels like "Approve USDT" or "Swap LINK". Added directionLabel field to parsed transactions so renderers don't need to know about the sent/received/contract distinction. Also: clicking a transaction on the home screen now opens the transaction detail view instead of navigating to the address detail view.
This commit is contained in:
@@ -186,8 +186,10 @@ function renderTransactions(txs) {
|
|||||||
for (const tx of txs) {
|
for (const tx of txs) {
|
||||||
const counterparty = tx.direction === "sent" ? tx.to : tx.from;
|
const counterparty = tx.direction === "sent" ? tx.to : tx.from;
|
||||||
const ensName = ensNameMap.get(counterparty) || null;
|
const ensName = ensNameMap.get(counterparty) || null;
|
||||||
const dirLabel = tx.direction === "sent" ? "Sent" : "Received";
|
const dirLabel = tx.directionLabel;
|
||||||
const amountStr = escapeHtml(tx.value + " " + tx.symbol);
|
const amountStr = tx.value
|
||||||
|
? escapeHtml(tx.value + " " + tx.symbol)
|
||||||
|
: escapeHtml(tx.symbol);
|
||||||
const maxAddr = Math.max(10, 36 - Math.max(0, amountStr.length - 10));
|
const maxAddr = Math.max(10, 36 - Math.max(0, amountStr.length - 10));
|
||||||
const displayAddr = ensName || truncateMiddle(counterparty, maxAddr);
|
const displayAddr = ensName || truncateMiddle(counterparty, maxAddr);
|
||||||
const addrStr = escapeHtml(displayAddr);
|
const addrStr = escapeHtml(displayAddr);
|
||||||
|
|||||||
@@ -211,8 +211,10 @@ function renderTransactions(txs) {
|
|||||||
for (const tx of txs) {
|
for (const tx of txs) {
|
||||||
const counterparty = tx.direction === "sent" ? tx.to : tx.from;
|
const counterparty = tx.direction === "sent" ? tx.to : tx.from;
|
||||||
const ensName = ensNameMap.get(counterparty) || null;
|
const ensName = ensNameMap.get(counterparty) || null;
|
||||||
const dirLabel = tx.direction === "sent" ? "Sent" : "Received";
|
const dirLabel = tx.directionLabel;
|
||||||
const amountStr = escapeHtml(tx.value + " " + tx.symbol);
|
const amountStr = tx.value
|
||||||
|
? escapeHtml(tx.value + " " + tx.symbol)
|
||||||
|
: escapeHtml(tx.symbol);
|
||||||
const maxAddr = Math.max(10, 36 - Math.max(0, amountStr.length - 10));
|
const maxAddr = Math.max(10, 36 - Math.max(0, amountStr.length - 10));
|
||||||
const displayAddr = ensName || truncateMiddle(counterparty, maxAddr);
|
const displayAddr = ensName || truncateMiddle(counterparty, maxAddr);
|
||||||
const addrStr = escapeHtml(displayAddr);
|
const addrStr = escapeHtml(displayAddr);
|
||||||
|
|||||||
@@ -134,8 +134,10 @@ function renderHomeTxList(ctx) {
|
|||||||
let i = 0;
|
let i = 0;
|
||||||
for (const tx of homeTxs) {
|
for (const tx of homeTxs) {
|
||||||
const counterparty = tx.direction === "sent" ? tx.to : tx.from;
|
const counterparty = tx.direction === "sent" ? tx.to : tx.from;
|
||||||
const dirLabel = tx.direction === "sent" ? "Sent" : "Received";
|
const dirLabel = tx.directionLabel;
|
||||||
const amountStr = escapeHtml(tx.value + " " + tx.symbol);
|
const amountStr = tx.value
|
||||||
|
? escapeHtml(tx.value + " " + tx.symbol)
|
||||||
|
: escapeHtml(tx.symbol);
|
||||||
const maxAddr = Math.max(10, 36 - Math.max(0, amountStr.length - 10));
|
const maxAddr = Math.max(10, 36 - Math.max(0, amountStr.length - 10));
|
||||||
const displayAddr = truncateMiddle(counterparty, maxAddr);
|
const displayAddr = truncateMiddle(counterparty, maxAddr);
|
||||||
const addrStr = escapeHtml(displayAddr);
|
const addrStr = escapeHtml(displayAddr);
|
||||||
@@ -155,7 +157,7 @@ function renderHomeTxList(ctx) {
|
|||||||
row.addEventListener("click", () => {
|
row.addEventListener("click", () => {
|
||||||
const idx = parseInt(row.dataset.tx, 10);
|
const idx = parseInt(row.dataset.tx, 10);
|
||||||
const tx = homeTxs[idx];
|
const tx = homeTxs[idx];
|
||||||
// Find which wallet/address this tx belongs to and navigate
|
// Set selectedWallet/selectedAddress so back navigation works
|
||||||
for (let wi = 0; wi < state.wallets.length; wi++) {
|
for (let wi = 0; wi < state.wallets.length; wi++) {
|
||||||
for (
|
for (
|
||||||
let ai = 0;
|
let ai = 0;
|
||||||
@@ -169,7 +171,8 @@ function renderHomeTxList(ctx) {
|
|||||||
) {
|
) {
|
||||||
state.selectedWallet = wi;
|
state.selectedWallet = wi;
|
||||||
state.selectedAddress = ai;
|
state.selectedAddress = ai;
|
||||||
ctx.showAddressDetail();
|
state.selectedToken = null;
|
||||||
|
ctx.showTransactionDetail(tx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ function show(tx) {
|
|||||||
isError: tx.isError,
|
isError: tx.isError,
|
||||||
fromEns: tx.fromEns || null,
|
fromEns: tx.fromEns || null,
|
||||||
toEns: tx.toEns || null,
|
toEns: tx.toEns || null,
|
||||||
|
directionLabel: tx.directionLabel || null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
render();
|
render();
|
||||||
@@ -121,7 +122,9 @@ function render() {
|
|||||||
$("tx-detail-hash").innerHTML = txHashHtml(tx.hash);
|
$("tx-detail-hash").innerHTML = txHashHtml(tx.hash);
|
||||||
$("tx-detail-from").innerHTML = txAddressHtml(tx.from, tx.fromEns);
|
$("tx-detail-from").innerHTML = txAddressHtml(tx.from, tx.fromEns);
|
||||||
$("tx-detail-to").innerHTML = txAddressHtml(tx.to, tx.toEns);
|
$("tx-detail-to").innerHTML = txAddressHtml(tx.to, tx.toEns);
|
||||||
$("tx-detail-value").textContent = tx.value + " " + tx.symbol;
|
$("tx-detail-value").textContent = tx.value
|
||||||
|
? tx.value + " " + tx.symbol
|
||||||
|
: tx.directionLabel + " " + tx.symbol;
|
||||||
$("tx-detail-time").textContent =
|
$("tx-detail-time").textContent =
|
||||||
isoDate(tx.timestamp) + " (" + timeAgo(tx.timestamp) + ")";
|
isoDate(tx.timestamp) + " (" + timeAgo(tx.timestamp) + ")";
|
||||||
$("tx-detail-status").textContent = tx.isError ? "Failed" : "Success";
|
$("tx-detail-status").textContent = tx.isError ? "Failed" : "Success";
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
const { formatEther, formatUnits } = require("ethers");
|
const { formatEther, formatUnits } = require("ethers");
|
||||||
const { log, debugFetch } = require("./log");
|
const { log, debugFetch } = require("./log");
|
||||||
const { KNOWN_SYMBOLS } = require("./tokenList");
|
const { KNOWN_SYMBOLS, TOKEN_BY_ADDRESS } = require("./tokenList");
|
||||||
|
|
||||||
function formatTxValue(val) {
|
function formatTxValue(val) {
|
||||||
const parts = val.split(".");
|
const parts = val.split(".");
|
||||||
@@ -22,21 +22,40 @@ function parseTx(tx, addrLower) {
|
|||||||
const to = tx.to?.hash || "";
|
const to = tx.to?.hash || "";
|
||||||
const rawWei = tx.value || "0";
|
const rawWei = tx.value || "0";
|
||||||
const toIsContract = tx.to?.is_contract || false;
|
const toIsContract = tx.to?.is_contract || false;
|
||||||
|
const method = tx.method || null;
|
||||||
|
|
||||||
|
// For contract calls, produce a meaningful label instead of "0.0000 ETH"
|
||||||
|
let symbol = "ETH";
|
||||||
|
let value = formatTxValue(formatEther(rawWei));
|
||||||
|
let direction = from.toLowerCase() === addrLower ? "sent" : "received";
|
||||||
|
let directionLabel = direction === "sent" ? "Sent" : "Received";
|
||||||
|
if (toIsContract && method && method !== "transfer") {
|
||||||
|
const token = TOKEN_BY_ADDRESS.get(to.toLowerCase());
|
||||||
|
if (token) {
|
||||||
|
symbol = token.symbol;
|
||||||
|
}
|
||||||
|
const label = method.charAt(0).toUpperCase() + method.slice(1);
|
||||||
|
direction = "contract";
|
||||||
|
directionLabel = label;
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hash: tx.hash,
|
hash: tx.hash,
|
||||||
blockNumber: tx.block_number,
|
blockNumber: tx.block_number,
|
||||||
timestamp: Math.floor(new Date(tx.timestamp).getTime() / 1000),
|
timestamp: Math.floor(new Date(tx.timestamp).getTime() / 1000),
|
||||||
from: from,
|
from: from,
|
||||||
to: to,
|
to: to,
|
||||||
value: formatTxValue(formatEther(rawWei)),
|
value: value,
|
||||||
valueGwei: Math.floor(Number(BigInt(rawWei) / BigInt(1000000000))),
|
valueGwei: Math.floor(Number(BigInt(rawWei) / BigInt(1000000000))),
|
||||||
symbol: "ETH",
|
symbol: symbol,
|
||||||
direction: from.toLowerCase() === addrLower ? "sent" : "received",
|
direction: direction,
|
||||||
|
directionLabel: directionLabel,
|
||||||
isError: tx.status !== "ok",
|
isError: tx.status !== "ok",
|
||||||
contractAddress: null,
|
contractAddress: null,
|
||||||
holders: null,
|
holders: null,
|
||||||
isContractCall: toIsContract,
|
isContractCall: toIsContract,
|
||||||
method: tx.method || null,
|
method: method,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +64,7 @@ function parseTokenTransfer(tt, addrLower) {
|
|||||||
const to = tt.to?.hash || "";
|
const to = tt.to?.hash || "";
|
||||||
const decimals = parseInt(tt.total?.decimals || "18", 10);
|
const decimals = parseInt(tt.total?.decimals || "18", 10);
|
||||||
const rawValue = tt.total?.value || "0";
|
const rawValue = tt.total?.value || "0";
|
||||||
|
const direction = from.toLowerCase() === addrLower ? "sent" : "received";
|
||||||
return {
|
return {
|
||||||
hash: tt.transaction_hash,
|
hash: tt.transaction_hash,
|
||||||
blockNumber: tt.block_number,
|
blockNumber: tt.block_number,
|
||||||
@@ -54,7 +74,8 @@ function parseTokenTransfer(tt, addrLower) {
|
|||||||
value: formatTxValue(formatUnits(rawValue, decimals)),
|
value: formatTxValue(formatUnits(rawValue, decimals)),
|
||||||
valueGwei: null,
|
valueGwei: null,
|
||||||
symbol: tt.token?.symbol || "?",
|
symbol: tt.token?.symbol || "?",
|
||||||
direction: from.toLowerCase() === addrLower ? "sent" : "received",
|
direction: direction,
|
||||||
|
directionLabel: direction === "sent" ? "Sent" : "Received",
|
||||||
isError: false,
|
isError: false,
|
||||||
contractAddress: (
|
contractAddress: (
|
||||||
tt.token?.address_hash ||
|
tt.token?.address_hash ||
|
||||||
|
|||||||
Reference in New Issue
Block a user