Classify transactions by decoded calldata in history

Use the shared decodeCalldata module to detect Uniswap swaps,
token approvals, and unknown contract calls in parseTx. Swaps
now show 'Swap TOKEN_A → TOKEN_B' instead of 'Sent'. Unknown
contract calls show 'Contract Call'. Raw input and decoded
data are passed through for the detail view.
This commit is contained in:
2026-02-27 12:05:17 -08:00
parent 93aecc87ef
commit 497d011b3c

View File

@@ -9,6 +9,7 @@
const { formatEther, formatUnits } = require("ethers"); const { formatEther, formatUnits } = require("ethers");
const { log, debugFetch } = require("./log"); const { log, debugFetch } = require("./log");
const { KNOWN_SYMBOLS, TOKEN_BY_ADDRESS } = require("./tokenList"); const { KNOWN_SYMBOLS, TOKEN_BY_ADDRESS } = require("./tokenList");
const { decodeCalldata } = require("./decodeCalldata");
function formatTxValue(val) { function formatTxValue(val) {
const parts = val.split("."); const parts = val.split(".");
@@ -23,6 +24,7 @@ function parseTx(tx, addrLower) {
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; const method = tx.method || null;
const rawInput = tx.raw_input || null;
// For contract calls, produce a meaningful label instead of "0.0000 ETH" // For contract calls, produce a meaningful label instead of "0.0000 ETH"
let symbol = "ETH"; let symbol = "ETH";
@@ -32,14 +34,41 @@ function parseTx(tx, addrLower) {
let rawUnit = "wei"; let rawUnit = "wei";
let direction = from.toLowerCase() === addrLower ? "sent" : "received"; let direction = from.toLowerCase() === addrLower ? "sent" : "received";
let directionLabel = direction === "sent" ? "Sent" : "Received"; let directionLabel = direction === "sent" ? "Sent" : "Received";
if (toIsContract && method && method !== "transfer") { let decoded = null;
const token = TOKEN_BY_ADDRESS.get(to.toLowerCase());
if (token) { if (rawInput && rawInput !== "0x" && rawInput.length >= 10) {
symbol = token.symbol; decoded = decodeCalldata(rawInput, to);
} if (decoded) {
const label = method.charAt(0).toUpperCase() + method.slice(1); // Uniswap swaps: show "Swap" with token pair
if (decoded.name && decoded.name.startsWith("Swap")) {
direction = "contract"; direction = "contract";
directionLabel = label; directionLabel = decoded.name;
value = "";
exactValue = "";
rawAmount = "";
rawUnit = "";
} else if (decoded.name === "Token Approval") {
direction = "contract";
directionLabel = "Approve";
value = "";
exactValue = "";
rawAmount = "";
rawUnit = "";
}
// Token Transfer: keep as Sent/Received (handled by token transfer overlay)
} else if (toIsContract && method && method !== "transfer") {
// Unknown contract call
direction = "contract";
directionLabel = "Contract Call";
value = "";
exactValue = "";
rawAmount = "";
rawUnit = "";
}
} else if (toIsContract && method && method !== "transfer") {
// Contract call without raw input data
direction = "contract";
directionLabel = "Contract Call";
value = ""; value = "";
exactValue = ""; exactValue = "";
rawAmount = ""; rawAmount = "";
@@ -65,6 +94,8 @@ function parseTx(tx, addrLower) {
holders: null, holders: null,
isContractCall: toIsContract, isContractCall: toIsContract,
method: method, method: method,
rawInput: rawInput,
decoded: decoded,
}; };
} }