const options = { method: "GET", headers: { accept: "application/json" } }; let nextUrl = null; async function transactionHistory(url, address) { try { const response = await fetch(url, options); const data = await response.json(); const historyDiv = document.getElementById("historyOutput"); historyDiv.innerHTML = ""; if (data && data.data) { console.log(data.data); data.data.forEach((tx) => { const hash = tx.txID; const block = tx.blockNumber; const age = new Date(tx.block_timestamp).toLocaleString(); const type = tx.raw_data.contract[0].type; let from = ""; let to = ""; let amount = ""; let extraContractLine = ""; if (type === "TransferContract") { const v = tx.raw_data.contract[0].parameter.value; from = tronWeb.address.fromHex(v.owner_address); to = tronWeb.address.fromHex(v.to_address); amount = v.amount / 1e6 + " TRX"; } else if (type === "TriggerSmartContract") { const v = tx.raw_data.contract[0].parameter.value; from = tronWeb.address.fromHex(v.owner_address); const contractBase58 = tronWeb.address.fromHex(v.contract_address); extraContractLine = `
Contract: ${contractBase58}
`; const input = (v.data || "").startsWith("0x") ? v.data.slice(2) : v.data || ""; const method = input.slice(0, 8).toLowerCase(); if (method === "a9059cbb" && input.length >= 8 + 64 + 64) { const addrSlot = input.slice(8, 8 + 64); const amountSlot = input.slice(8 + 64, 8 + 64 + 64); const evmAddrHex = addrSlot.slice(24); const tronHex = "41" + evmAddrHex.toLowerCase(); to = tronWeb.address.fromHex(tronHex); const raw = BigInt("0x" + amountSlot); amount = Number(raw) / 1e6 + " USDT"; } else { to = "—"; amount = "—"; } } const result = tx.ret?.[0]?.contractRet || "UNKNOWN"; const statusColor = result === "SUCCESS" ? "green" : "red"; // create card const card = document.createElement("div"); card.className = "tx-card"; card.innerHTML = `Hash: ${truncate(hash)}
Block: ${block}
Age: ${age}
Type: ${type}
From: ${from}
To: ${to}
${extraContractLine}Amount: ${amount}
Status: ${result}
`; historyDiv.appendChild(card); }); // save nextUrl for pagination if (data.meta && data.meta.fingerprint) { nextUrl = `https://api.shasta.trongrid.io/v1/accounts/${address}/transactions?limit=10&fingerprint=${encodeURIComponent( data.meta.fingerprint )}`; } else { nextUrl = null; } } } catch (error) { console.error(error); } } function fetchNext(address) { if (nextUrl) { transactionHistory(nextUrl, address); } } function truncate(str, len = 12) { if (!str) return ""; return str.length > len ? str.slice(0, 6) + "..." + str.slice(-6) : str; } function copyToClipboard(text) { navigator.clipboard.writeText(text).then(() => { alert("Copied: " + text); }); } // State for filtering and pagination let __nextUrl = null; let __prevUrls = []; let __currentAddress = ""; let __currentTxs = []; let __currentFilter = "all"; // all | received | sent let __currentPage = 1; let __currentUrl = null; let __perPage = 10; const __origTransactionHistory = transactionHistory; transactionHistory = async function (url, address) { try { if (typeof notify === "function") notify("Loading transactions...", "success", 1500); const response = await fetch(url, { method: "GET", headers: { accept: "application/json" }, }); const data = await response.json(); const section = document.getElementById("transactionSection"); if (section) section.style.display = "block"; __currentAddress = address; __currentUrl = url; window.lastUsedUrl = url; if (data && data.data) { __currentTxs = data.data; // track current per-page from url const m = url.match(/limit=(\d+)/); if (m) __perPage = parseInt(m[1], 10) || __perPage; __renderTransactions(); if (data.meta && data.meta.fingerprint) { __nextUrl = `https://api.shasta.trongrid.io/v1/accounts/${address}/transactions?limit=${__perPage}&fingerprint=${encodeURIComponent( data.meta.fingerprint )}`; } else { __nextUrl = null; } __updatePagination(); } return data; } catch (e) { console.error(e); if (typeof __origTransactionHistory === "function") { __origTransactionHistory(url, address); } throw e; } }; function __renderTransactions() { const list = document.getElementById("txList"); const legacy = document.getElementById("historyOutput"); if (!list) { if (legacy) legacy.innerHTML = ""; return; } list.innerHTML = ""; const filtered = __currentTxs.filter((tx) => { const type = tx.raw_data?.contract?.[0]?.type || ""; let from = ""; let to = ""; if (type === "TransferContract") { const v = tx.raw_data.contract[0].parameter.value; from = tronWeb.address.fromHex(v.owner_address); to = tronWeb.address.fromHex(v.to_address); } else if (type === "TriggerSmartContract") { const v = tx.raw_data.contract[0].parameter.value; from = tronWeb.address.fromHex(v.owner_address); const input = (v.data || "").startsWith("0x") ? v.data.slice(2) : v.data || ""; const method = input.slice(0, 8).toLowerCase(); if (method === "a9059cbb" && input.length >= 8 + 64 + 64) { const addrSlot = input.slice(8, 8 + 64); const evmAddrHex = addrSlot.slice(24); const tronHex = "41" + evmAddrHex.toLowerCase(); to = tronWeb.address.fromHex(tronHex); } } if (__currentFilter === "sent") return from === __currentAddress; if (__currentFilter === "received") return to === __currentAddress; return true; }); if (filtered.length === 0) { list.innerHTML = '