fix: update API endpoints to use mainnet instead of testnet and improve transaction history rendering
This commit is contained in:
parent
70331e19f1
commit
e5bbc8f872
@ -2792,6 +2792,38 @@ sm-popup::part(popup) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Resources and fees styling - always display on separate lines */
|
||||||
|
.tx-detail-value.resources-list {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: column !important;
|
||||||
|
align-items: flex-end !important; /* Right-align the resource items */
|
||||||
|
gap: 0.5rem !important;
|
||||||
|
text-align: right !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Special styling for resource rows */
|
||||||
|
.tx-detail-row.resource-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resource-item {
|
||||||
|
display: block !important;
|
||||||
|
padding: 0.25rem 0.5rem !important;
|
||||||
|
background-color: rgba(59, 130, 246, 0.05) !important;
|
||||||
|
border-radius: 0.25rem !important;
|
||||||
|
margin-bottom: 0.375rem !important;
|
||||||
|
font-family: inherit !important;
|
||||||
|
text-align: right !important;
|
||||||
|
width: fit-content !important;
|
||||||
|
margin-left: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resource-item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
/* Responsive Design */
|
/* Responsive Design */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.hamburger-btn {
|
.hamburger-btn {
|
||||||
@ -4122,7 +4154,6 @@ sm-popup::part(popup) {
|
|||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@media (max-width: 480px) and (max-height: 740px) {
|
@media (max-width: 480px) and (max-height: 740px) {
|
||||||
sm-popup::part(popup) {
|
sm-popup::part(popup) {
|
||||||
max-height: 95vh !important;
|
max-height: 95vh !important;
|
||||||
@ -4426,6 +4457,24 @@ sm-popup::part(popup) {
|
|||||||
.tx-detail-label {
|
.tx-detail-label {
|
||||||
min-width: auto;
|
min-width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Resource items on small screens - left aligned */
|
||||||
|
.tx-detail-value.resources-list {
|
||||||
|
align-items: flex-start !important;
|
||||||
|
text-align: left !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resource-item {
|
||||||
|
text-align: left !important;
|
||||||
|
margin-left: 0 !important;
|
||||||
|
width: fit-content !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep resource rows stacked on mobile */
|
||||||
|
.tx-detail-row.resource-row {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate Wallet Page Styles */
|
/* Generate Wallet Page Styles */
|
||||||
|
|||||||
@ -1093,7 +1093,7 @@
|
|||||||
__historyAddress = address;
|
__historyAddress = address;
|
||||||
const perPageSelect = document.getElementById("perPageSelect");
|
const perPageSelect = document.getElementById("perPageSelect");
|
||||||
const limit = perPageSelect ? parseInt(perPageSelect.value, 10) : 10;
|
const limit = perPageSelect ? parseInt(perPageSelect.value, 10) : 10;
|
||||||
const url = `https://api.shasta.trongrid.io/v1/accounts/${address}/transactions?limit=${limit}`;
|
const url = `https://api.trongrid.io/v1/accounts/${address}/transactions?limit=${limit}`;
|
||||||
const section = document.getElementById("transactionSection");
|
const section = document.getElementById("transactionSection");
|
||||||
if (section) section.style.display = "block";
|
if (section) section.style.display = "block";
|
||||||
resetHistoryState(limit);
|
resetHistoryState(limit);
|
||||||
@ -1137,7 +1137,7 @@
|
|||||||
perSel.addEventListener("change", () => {
|
perSel.addEventListener("change", () => {
|
||||||
if (!__historyAddress) return;
|
if (!__historyAddress) return;
|
||||||
const limit = parseInt(perSel.value, 10) || 10;
|
const limit = parseInt(perSel.value, 10) || 10;
|
||||||
const url = `https://api.shasta.trongrid.io/v1/accounts/${__historyAddress}/transactions?limit=${limit}`;
|
const url = `https://api.trongrid.io/v1/accounts/${__historyAddress}/transactions?limit=${limit}`;
|
||||||
resetHistoryState(limit);
|
resetHistoryState(limit);
|
||||||
transactionHistory(url, __historyAddress);
|
transactionHistory(url, __historyAddress);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -38,7 +38,7 @@ function shareTxLink(txid) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function getTransactionDetails(txHash) {
|
async function getTransactionDetails(txHash) {
|
||||||
const url = "https://api.shasta.trongrid.io/wallet/gettransactionbyid";
|
const url = "https://api.trongrid.io/wallet/gettransactionbyid";
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -64,7 +64,7 @@ async function getTransactionDetails(txHash) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getTransactionInfoById(txHash) {
|
async function getTransactionInfoById(txHash) {
|
||||||
const url = "https://api.shasta.trongrid.io/wallet/gettransactioninfobyid";
|
const url = "https://api.trongrid.io/wallet/gettransactioninfobyid";
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -170,9 +170,12 @@ async function runBalanceCheck() {
|
|||||||
loadHistoryFor(tronAddress);
|
loadHistoryFor(tronAddress);
|
||||||
|
|
||||||
// Save searched address to IndexedDB
|
// Save searched address to IndexedDB
|
||||||
if (typeof searchedAddressDB !== 'undefined') {
|
if (typeof searchedAddressDB !== "undefined") {
|
||||||
try {
|
try {
|
||||||
await searchedAddressDB.saveSearchedAddress(tronAddress, balance.toLocaleString());
|
await searchedAddressDB.saveSearchedAddress(
|
||||||
|
tronAddress,
|
||||||
|
balance.toLocaleString()
|
||||||
|
);
|
||||||
await updateSearchedAddressesList();
|
await updateSearchedAddressesList();
|
||||||
} catch (dbError) {
|
} catch (dbError) {
|
||||||
console.warn("Failed to save address to IndexedDB:", dbError);
|
console.warn("Failed to save address to IndexedDB:", dbError);
|
||||||
@ -184,7 +187,6 @@ async function runBalanceCheck() {
|
|||||||
// Treat as private key (WIF or HEX)
|
// Treat as private key (WIF or HEX)
|
||||||
const { tronAddress, balance } = await getBalanceByPrivKey(inputVal);
|
const { tronAddress, balance } = await getBalanceByPrivKey(inputVal);
|
||||||
|
|
||||||
|
|
||||||
let sourceInfo = null;
|
let sourceInfo = null;
|
||||||
if (/^[5KLc9RQ][1-9A-HJ-NP-Za-km-z]{50,}$/.test(inputVal)) {
|
if (/^[5KLc9RQ][1-9A-HJ-NP-Za-km-z]{50,}$/.test(inputVal)) {
|
||||||
// This is a BTC/FLO WIF key
|
// This is a BTC/FLO WIF key
|
||||||
@ -192,11 +194,10 @@ async function runBalanceCheck() {
|
|||||||
type: "Private Key",
|
type: "Private Key",
|
||||||
originalKey: inputVal,
|
originalKey: inputVal,
|
||||||
originalAddress: inputVal, // Store the original private key for toggling
|
originalAddress: inputVal, // Store the original private key for toggling
|
||||||
blockchain: /^[KL]/.test(inputVal) ? "BTC" : "FLO"
|
blockchain: /^[KL]/.test(inputVal) ? "BTC" : "FLO",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
output.innerHTML = `
|
output.innerHTML = `
|
||||||
<div class="card balance-info">
|
<div class="card balance-info">
|
||||||
<div class="balance-header">
|
<div class="balance-header">
|
||||||
@ -227,9 +228,14 @@ async function runBalanceCheck() {
|
|||||||
loadHistoryFor(tronAddress);
|
loadHistoryFor(tronAddress);
|
||||||
|
|
||||||
// Save searched address to IndexedDB
|
// Save searched address to IndexedDB
|
||||||
if (typeof searchedAddressDB !== 'undefined') {
|
if (typeof searchedAddressDB !== "undefined") {
|
||||||
try {
|
try {
|
||||||
await searchedAddressDB.saveSearchedAddress(tronAddress, balance.toLocaleString(), Date.now(), sourceInfo);
|
await searchedAddressDB.saveSearchedAddress(
|
||||||
|
tronAddress,
|
||||||
|
balance.toLocaleString(),
|
||||||
|
Date.now(),
|
||||||
|
sourceInfo
|
||||||
|
);
|
||||||
await updateSearchedAddressesList();
|
await updateSearchedAddressesList();
|
||||||
} catch (dbError) {
|
} catch (dbError) {
|
||||||
console.warn("Failed to save address to IndexedDB:", dbError);
|
console.warn("Failed to save address to IndexedDB:", dbError);
|
||||||
@ -247,7 +253,6 @@ async function runBalanceCheck() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function runTxSearch() {
|
async function runTxSearch() {
|
||||||
|
|
||||||
const input = document.getElementById("txHash");
|
const input = document.getElementById("txHash");
|
||||||
const output = document.getElementById("txOutput");
|
const output = document.getElementById("txOutput");
|
||||||
const txid = (input.value || "").trim();
|
const txid = (input.value || "").trim();
|
||||||
@ -283,102 +288,176 @@ async function runTxSearch() {
|
|||||||
(tx.raw_data && tx.raw_data.contract && tx.raw_data.contract[0]) || {};
|
(tx.raw_data && tx.raw_data.contract && tx.raw_data.contract[0]) || {};
|
||||||
const type = contract.type || "TransferContract";
|
const type = contract.type || "TransferContract";
|
||||||
const parameter = contract.parameter && contract.parameter.value;
|
const parameter = contract.parameter && contract.parameter.value;
|
||||||
const to = (parameter && parameter.to_address) || "-";
|
|
||||||
const owner = (parameter && parameter.owner_address) || "-";
|
|
||||||
const amount =
|
|
||||||
parameter && parameter.amount ? parameter.amount / 1000000 : "-";
|
|
||||||
const timestamp =
|
const timestamp =
|
||||||
tx.raw_data && tx.raw_data.timestamp
|
tx.raw_data && tx.raw_data.timestamp
|
||||||
? new Date(tx.raw_data.timestamp).toLocaleString()
|
? new Date(tx.raw_data.timestamp).toLocaleString()
|
||||||
: "-";
|
: "-";
|
||||||
const fee = txInfo.fee ? txInfo.fee / 1000000 : "-";
|
|
||||||
const blockNumber = txInfo.blockNumber || "-";
|
const blockNumber = txInfo.blockNumber || "-";
|
||||||
|
|
||||||
output.innerHTML = `
|
// Extract resources and fees from both transaction objects
|
||||||
<div class="card transaction-details">
|
|
||||||
<div class="transaction-details-header">
|
let bandwidth = undefined;
|
||||||
<h3><i class="fas fa-receipt"></i> Transaction Details</h3>
|
if (txInfo.receipt && txInfo.receipt.net_usage) {
|
||||||
<button
|
bandwidth = txInfo.receipt.net_usage;
|
||||||
onclick="shareTxLink('${id}')"
|
} else if (tx.net_usage) {
|
||||||
class="btn-icon share-btn"
|
bandwidth = tx.net_usage;
|
||||||
title="Copy Shareable Link"
|
}
|
||||||
>
|
|
||||||
<i class="fas fa-share-alt"></i>
|
// Check both transaction info and receipt for energy usage
|
||||||
</button>
|
let energy = undefined;
|
||||||
</div>
|
if (txInfo.receipt && txInfo.receipt.energy_usage) {
|
||||||
<div class="transaction-details-content">
|
energy = txInfo.receipt.energy_usage;
|
||||||
<div class="tx-detail-card">
|
} else if (tx.energy_usage) {
|
||||||
<div class="tx-detail-row">
|
energy = tx.energy_usage;
|
||||||
<span class="tx-detail-label">
|
}
|
||||||
<i class="fas fa-check-circle"></i>
|
|
||||||
Status:
|
// Check for fees from multiple sources
|
||||||
</span>
|
let fee = "-";
|
||||||
<span class="tx-detail-value success">${ret}</span>
|
if (txInfo.receipt && txInfo.receipt.net_fee) {
|
||||||
</div>
|
fee = txInfo.receipt.net_fee / 1000000;
|
||||||
<div class="tx-detail-row">
|
} else if (txInfo.fee) {
|
||||||
<span class="tx-detail-label">
|
fee = txInfo.fee / 1000000;
|
||||||
<i class="fas fa-exchange-alt"></i>
|
} else if (tx.fee) {
|
||||||
Type:
|
fee = tx.fee / 1000000;
|
||||||
</span>
|
}
|
||||||
<span class="tx-detail-value">${type}</span>
|
|
||||||
</div>
|
// Format the resource consumption and fee HTML
|
||||||
<div class="tx-detail-row">
|
let resourcesFeeHtml = "";
|
||||||
<span class="tx-detail-label">
|
let feeParts = [];
|
||||||
<i class="fas fa-coins"></i>
|
if (bandwidth && bandwidth !== "-")
|
||||||
Amount:
|
feeParts.push(`<div class="resource-item">${bandwidth} Bandwidth</div>`);
|
||||||
</span>
|
if (energy && energy !== "-")
|
||||||
<span class="tx-detail-value amount">${amount} TRX</span>
|
feeParts.push(`<div class="resource-item">${energy} Energy</div>`);
|
||||||
</div>
|
if (fee && fee !== "-")
|
||||||
<div class="tx-detail-row">
|
feeParts.push(`<div class="resource-item">${fee} TRX</div>`);
|
||||||
<span class="tx-detail-label">
|
|
||||||
<i class="fas fa-receipt"></i>
|
if (feeParts.length) {
|
||||||
Fee:
|
resourcesFeeHtml = `
|
||||||
</span>
|
<div class='tx-detail-row resource-row'>
|
||||||
<span class="tx-detail-value">${fee} TRX</span>
|
<span class='tx-detail-label'><i class='fas fa-cogs'></i> Resources Consumed & Fee:</span>
|
||||||
</div>
|
<span class='tx-detail-value resources-list'>${feeParts.join(
|
||||||
</div>
|
""
|
||||||
<div class="tx-detail-card">
|
)}</span>
|
||||||
<div class="tx-detail-row">
|
|
||||||
<span class="tx-detail-label">
|
|
||||||
<i class="fas fa-user-minus"></i>
|
|
||||||
From:
|
|
||||||
</span>
|
|
||||||
<span class="tx-detail-value">${owner}</span>
|
|
||||||
</div>
|
|
||||||
<div class="tx-detail-row">
|
|
||||||
<span class="tx-detail-label">
|
|
||||||
<i class="fas fa-user-plus"></i>
|
|
||||||
To:
|
|
||||||
</span>
|
|
||||||
<span class="tx-detail-value">${to}</span>
|
|
||||||
</div>
|
|
||||||
<div class="tx-detail-row">
|
|
||||||
<span class="tx-detail-label">
|
|
||||||
<i class="fas fa-hashtag"></i>
|
|
||||||
Hash:
|
|
||||||
</span>
|
|
||||||
<span class="tx-detail-value">${id}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tx-detail-card">
|
|
||||||
<div class="tx-detail-row">
|
|
||||||
<span class="tx-detail-label">
|
|
||||||
<i class="fas fa-layer-group"></i>
|
|
||||||
Block:
|
|
||||||
</span>
|
|
||||||
<span class="tx-detail-value">${blockNumber}</span>
|
|
||||||
</div>
|
|
||||||
<div class="tx-detail-row">
|
|
||||||
<span class="tx-detail-label">
|
|
||||||
<i class="fas fa-clock"></i>
|
|
||||||
Date:
|
|
||||||
</span>
|
|
||||||
<span class="tx-detail-value">${timestamp}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
} else {
|
||||||
|
resourcesFeeHtml = `
|
||||||
|
<div class='tx-detail-row resource-row'>
|
||||||
|
<span class='tx-detail-label'><i class='fas fa-cogs'></i> Resources Consumed & Fee:</span>
|
||||||
|
<span class='tx-detail-value resources-list'><span class="resource-item">- No resources consumed</span></span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let detailsHtml = "";
|
||||||
|
let owner = (parameter && parameter.owner_address) || "-";
|
||||||
|
let to = (parameter && parameter.to_address) || "-";
|
||||||
|
let amount =
|
||||||
|
parameter && parameter.amount ? parameter.amount / 1000000 : "-";
|
||||||
|
let tokenInfo = "";
|
||||||
|
let resourceInfo = "";
|
||||||
|
|
||||||
|
if (type === "TriggerSmartContract") {
|
||||||
|
let contractAddr =
|
||||||
|
parameter && parameter.contract_address
|
||||||
|
? parameter.contract_address
|
||||||
|
: "-";
|
||||||
|
let tokenAmount = "-";
|
||||||
|
let tokenSymbol = "USDT";
|
||||||
|
let tokenTo = "-";
|
||||||
|
if (txInfo.log && txInfo.log.length > 0) {
|
||||||
|
const log = txInfo.log[0];
|
||||||
|
if (log.topics && log.topics.length >= 3) {
|
||||||
|
tokenTo = tronWeb.address.fromHex("41" + log.topics[2].slice(-40));
|
||||||
|
tokenAmount = parseInt(log.data, 16) / 1e6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tokenInfo = `<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-coins'></i> Amount:</span><span class='tx-detail-value amount'>${tokenAmount} USDT</span></div>`;
|
||||||
|
detailsHtml = `
|
||||||
|
<div class='tx-detail-card'>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-check-circle'></i> Status:</span><span class='tx-detail-value success'>${ret}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-exchange-alt'></i> Type:</span><span class='tx-detail-value'>${type}</span></div>
|
||||||
|
${tokenInfo}
|
||||||
|
</div>
|
||||||
|
<div class='tx-detail-card'>
|
||||||
|
${resourcesFeeHtml}
|
||||||
|
</div>
|
||||||
|
<div class='tx-detail-card'>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-user-minus'></i> From:</span><span class='tx-detail-value'>${owner}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-user-plus'></i> To:</span><span class='tx-detail-value'>${tokenTo}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-hashtag'></i> Hash:</span><span class='tx-detail-value'>${id}</span></div>
|
||||||
|
</div>
|
||||||
|
<div class='tx-detail-card'>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-layer-group'></i> Block:</span><span class='tx-detail-value'>${blockNumber}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-clock'></i> Date:</span><span class='tx-detail-value'>${timestamp}</span></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else if (
|
||||||
|
type === "DelegateResourceContract" ||
|
||||||
|
type === "UnDelegateResourceContract"
|
||||||
|
) {
|
||||||
|
// Resource delegation/undelegation
|
||||||
|
let resourceType =
|
||||||
|
parameter && parameter.resource ? parameter.resource : "BANDWIDTH";
|
||||||
|
let stakedAmount =
|
||||||
|
amount !== "-" ? `${amount} TRX` : `${parameter.balance / 1e6} TRX`;
|
||||||
|
let resourceTakenFrom =
|
||||||
|
parameter && parameter.receiver_address
|
||||||
|
? parameter.receiver_address
|
||||||
|
: "-";
|
||||||
|
let stakedAssetHtml = "";
|
||||||
|
let delegatedHtml = "";
|
||||||
|
let reclaimedHtml = "";
|
||||||
|
if (type === "DelegateResourceContract") {
|
||||||
|
stakedAssetHtml = `<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-coins'></i> Staked Asset Withheld:</span><span class='tx-detail-value amount'>${stakedAmount} </span></div>`;
|
||||||
|
delegatedHtml = `<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-leaf'></i> Delegated Resources:</span><span class='tx-detail-value'>${resourceType}</span></div>`;
|
||||||
|
} else if (type === "UnDelegateResourceContract") {
|
||||||
|
stakedAssetHtml = `<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-coins'></i> Staked Asset Released:</span><span class='tx-detail-value amount'>${stakedAmount}</span></div>`;
|
||||||
|
reclaimedHtml = `<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-leaf'></i> Reclaimed Resources:</span><span class='tx-detail-value'>${resourceType}</span></div>`;
|
||||||
|
}
|
||||||
|
detailsHtml = `
|
||||||
|
<div class='tx-detail-card'>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-check-circle'></i> Status:</span><span class='tx-detail-value success'>${ret}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-exchange-alt'></i> Type:</span><span class='tx-detail-value'>${type}</span></div>
|
||||||
|
${stakedAssetHtml}
|
||||||
|
${delegatedHtml}
|
||||||
|
${reclaimedHtml}
|
||||||
|
</div>
|
||||||
|
<div class='tx-detail-card'>
|
||||||
|
${resourcesFeeHtml}
|
||||||
|
</div>
|
||||||
|
<div class='tx-detail-card'>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-user-minus'></i> Owner Address:</span><span class='tx-detail-value'>${owner}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-user-plus'></i> Resource Taken From:</span><span class='tx-detail-value'>${resourceTakenFrom}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-hashtag'></i> Hash:</span><span class='tx-detail-value'>${id}</span></div>
|
||||||
|
</div>
|
||||||
|
<div class='tx-detail-card'>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-layer-group'></i> Block:</span><span class='tx-detail-value'>${blockNumber}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-clock'></i> Date:</span><span class='tx-detail-value'>${timestamp}</span></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
// Default rendering (TransferContract, etc)
|
||||||
|
detailsHtml = `
|
||||||
|
<div class='tx-detail-card'>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-check-circle'></i> Status:</span><span class='tx-detail-value success'>${ret}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-exchange-alt'></i> Type:</span><span class='tx-detail-value'>${type}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-coins'></i> Amount:</span><span class='tx-detail-value amount'>${amount} TRX</span></div>
|
||||||
|
${resourcesFeeHtml}
|
||||||
|
</div>
|
||||||
|
<div class='tx-detail-card'>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-user-minus'></i> From:</span><span class='tx-detail-value'>${owner}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-user-plus'></i> To:</span><span class='tx-detail-value'>${to}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-hashtag'></i> Hash:</span><span class='tx-detail-value'>${id}</span></div>
|
||||||
|
</div>
|
||||||
|
<div class='tx-detail-card'>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-layer-group'></i> Block:</span><span class='tx-detail-value'>${blockNumber}</span></div>
|
||||||
|
<div class='tx-detail-row'><span class='tx-detail-label'><i class='fas fa-clock'></i> Date:</span><span class='tx-detail-value'>${timestamp}</span></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
output.innerHTML = `<div class='card transaction-details'><div class='transaction-details-header'><h3><i class='fas fa-receipt'></i> Transaction Details</h3><button onclick="shareTxLink('${id}')" class='btn-icon share-btn' title='Copy Shareable Link'><i class='fas fa-share-alt'></i></button></div><div class='transaction-details-content'>${detailsHtml}</div></div>`;
|
||||||
|
|
||||||
if (typeof notify === "function") notify("Transaction found", "success");
|
if (typeof notify === "function") notify("Transaction found", "success");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@ -55,9 +55,9 @@ function generateBTCFromPrivateKey(privateKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function generateTronWallet() {
|
async function generateTronWallet() {
|
||||||
const fullNode = "https://api.shasta.trongrid.io";
|
const fullNode = "https://api.trongrid.io";
|
||||||
const solidityNode = "https://api.shasta.trongrid.io";
|
const solidityNode = "https://api.trongrid.io";
|
||||||
const eventServer = "https://api.shasta.trongrid.io";
|
const eventServer = "https://api.trongrid.io";
|
||||||
|
|
||||||
const tronWeb = new TronWeb(
|
const tronWeb = new TronWeb(
|
||||||
fullNode,
|
fullNode,
|
||||||
|
|||||||
@ -7,9 +7,9 @@ function isWif(str) {
|
|||||||
|
|
||||||
async function recoverAllAddressesFromPrivKey(privKey) {
|
async function recoverAllAddressesFromPrivKey(privKey) {
|
||||||
const tronWeb = new TronWeb(
|
const tronWeb = new TronWeb(
|
||||||
"https://api.shasta.trongrid.io",
|
"https://api.trongrid.io",
|
||||||
"https://api.shasta.trongrid.io",
|
"https://api.trongrid.io",
|
||||||
"https://api.shasta.trongrid.io"
|
"https://api.trongrid.io"
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -125,12 +125,9 @@ class SearchedAddressDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const searchedAddressDB = new SearchedAddressDB();
|
const searchedAddressDB = new SearchedAddressDB();
|
||||||
|
|
||||||
|
|
||||||
async function displaySearchedAddresses(addresses) {
|
async function displaySearchedAddresses(addresses) {
|
||||||
|
|
||||||
let container = document.getElementById("searchedAddressesContainer");
|
let container = document.getElementById("searchedAddressesContainer");
|
||||||
const transactionSection = document.getElementById("transactionSection");
|
const transactionSection = document.getElementById("transactionSection");
|
||||||
|
|
||||||
@ -169,8 +166,7 @@ async function displaySearchedAddresses(addresses) {
|
|||||||
${addresses
|
${addresses
|
||||||
.map((addr, index) => {
|
.map((addr, index) => {
|
||||||
// Check if this was converted from a private key from another blockchain (BTC/FLO)
|
// Check if this was converted from a private key from another blockchain (BTC/FLO)
|
||||||
const hasSourceInfo =
|
const hasSourceInfo = addr.sourceInfo && addr.sourceInfo.originalKey;
|
||||||
addr.sourceInfo && addr.sourceInfo.originalKey;
|
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="searched-address-item ${
|
<div class="searched-address-item ${
|
||||||
@ -292,9 +288,6 @@ async function toggleAddressType(addressIndex, type) {
|
|||||||
addressItem.sourceInfo?.originalKey || addressItem.address;
|
addressItem.sourceInfo?.originalKey || addressItem.address;
|
||||||
addressDisplay.textContent = originalKey;
|
addressDisplay.textContent = originalKey;
|
||||||
addressDisplay.title = originalKey;
|
addressDisplay.title = originalKey;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -325,7 +318,9 @@ async function copyCurrentAddress(addressIndex) {
|
|||||||
} else {
|
} else {
|
||||||
// Copy the private key for non-Tron selection
|
// Copy the private key for non-Tron selection
|
||||||
valueToCopy = addressItem.sourceInfo?.originalKey || addressItem.address;
|
valueToCopy = addressItem.sourceInfo?.originalKey || addressItem.address;
|
||||||
valueLabel = `${addressItem.sourceInfo?.blockchain || "Original"} private key`;
|
valueLabel = `${
|
||||||
|
addressItem.sourceInfo?.blockchain || "Original"
|
||||||
|
} private key`;
|
||||||
}
|
}
|
||||||
|
|
||||||
await copyAddressToClipboard(valueToCopy, valueLabel);
|
await copyAddressToClipboard(valueToCopy, valueLabel);
|
||||||
@ -347,7 +342,6 @@ async function deleteSearchedAddress(address) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function clearAllSearchedAddresses() {
|
async function clearAllSearchedAddresses() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await searchedAddressDB.clearAllSearchedAddresses();
|
await searchedAddressDB.clearAllSearchedAddresses();
|
||||||
await updateSearchedAddressesList();
|
await updateSearchedAddressesList();
|
||||||
@ -356,7 +350,6 @@ async function clearAllSearchedAddresses() {
|
|||||||
console.error("Error clearing searched addresses:", error);
|
console.error("Error clearing searched addresses:", error);
|
||||||
notify("Failed to clear addresses", "error");
|
notify("Failed to clear addresses", "error");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyAddressToClipboard(address, label = "Address") {
|
async function copyAddressToClipboard(address, label = "Address") {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const fullNode = "https://api.shasta.trongrid.io";
|
const fullNode = "https://api.trongrid.io";
|
||||||
const solidityNode = "https://api.shasta.trongrid.io";
|
const solidityNode = "https://api.trongrid.io";
|
||||||
const eventServer = "https://api.shasta.trongrid.io";
|
const eventServer = "https://api.trongrid.io";
|
||||||
const tronWeb = new TronWeb(fullNode, solidityNode, eventServer);
|
const tronWeb = new TronWeb(fullNode, solidityNode, eventServer);
|
||||||
|
|
||||||
async function sendTrx() {
|
async function sendTrx() {
|
||||||
@ -45,14 +45,20 @@ async function sendTrx() {
|
|||||||
// Broadcast transaction
|
// Broadcast transaction
|
||||||
const receipt = await tronWeb.trx.sendRawTransaction(signedtxn);
|
const receipt = await tronWeb.trx.sendRawTransaction(signedtxn);
|
||||||
console.log(receipt);
|
console.log(receipt);
|
||||||
if (receipt && receipt.result && receipt.result.code === "INSUFFICIENT_BALANCE") {
|
if (
|
||||||
|
receipt &&
|
||||||
|
receipt.result &&
|
||||||
|
receipt.result.code === "INSUFFICIENT_BALANCE"
|
||||||
|
) {
|
||||||
throw new Error("Insufficient balance to send transaction.");
|
throw new Error("Insufficient balance to send transaction.");
|
||||||
}
|
}
|
||||||
if (receipt && receipt.code && receipt.code === 'CONTRACT_VALIDATE_ERROR') {
|
if (receipt && receipt.code && receipt.code === "CONTRACT_VALIDATE_ERROR") {
|
||||||
throw new Error("Insufficient balance to send transaction.");
|
throw new Error("Insufficient balance to send transaction.");
|
||||||
}
|
}
|
||||||
if (receipt && !receipt.result) {
|
if (receipt && !receipt.result) {
|
||||||
throw new Error("Transaction failed: " + (receipt.result.message || "Unknown error"));
|
throw new Error(
|
||||||
|
"Transaction failed: " + (receipt.result.message || "Unknown error")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const status = receipt.result ? "✅ Success" : "❌ Failed";
|
const status = receipt.result ? "✅ Success" : "❌ Failed";
|
||||||
const statusColor = receipt.result ? "green" : "red";
|
const statusColor = receipt.result ? "green" : "red";
|
||||||
|
|||||||
@ -1,103 +1,50 @@
|
|||||||
const options = { method: "GET", headers: { accept: "application/json" } };
|
const options = { method: "GET", headers: { accept: "application/json" } };
|
||||||
let nextUrl = null;
|
let nextUrl = null;
|
||||||
|
|
||||||
async function transactionHistory(url, address) {
|
const transactionHistory = async function (url, address) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url, options);
|
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 data = await response.json();
|
||||||
|
|
||||||
const historyDiv = document.getElementById("historyOutput");
|
const section = document.getElementById("transactionSection");
|
||||||
historyDiv.innerHTML = "";
|
if (section) section.style.display = "block";
|
||||||
|
|
||||||
|
__currentAddress = address;
|
||||||
|
__currentUrl = url;
|
||||||
|
window.lastUsedUrl = url;
|
||||||
|
|
||||||
if (data && data.data) {
|
if (data && data.data) {
|
||||||
console.log(data.data);
|
console.log(data.data);
|
||||||
|
|
||||||
data.data.forEach((tx) => {
|
__currentTxs = data.data;
|
||||||
const hash = tx.txID;
|
// track current per-page from url
|
||||||
const block = tx.blockNumber;
|
const m = url.match(/limit=(\d+)/);
|
||||||
const age = new Date(tx.block_timestamp).toLocaleString();
|
if (m) __perPage = parseInt(m[1], 10) || __perPage;
|
||||||
const type = tx.raw_data.contract[0].type;
|
__renderTransactions();
|
||||||
|
|
||||||
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 = `
|
|
||||||
<p><b>Contract:</b> ${contractBase58}
|
|
||||||
<button onclick="copyToClipboard('${contractBase58}')"><i class="fas fa-copy"></i></button>
|
|
||||||
</p>`;
|
|
||||||
|
|
||||||
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 = `
|
|
||||||
<p><b>Hash:</b> ${truncate(hash)}
|
|
||||||
<button onclick="copyToClipboard('${hash}')"><i class="fas fa-copy"></i></button></p>
|
|
||||||
<p><b>Block:</b> ${block}</p>
|
|
||||||
<p><b>Age:</b> ${age}</p>
|
|
||||||
<p><b>Type:</b> ${type}</p>
|
|
||||||
<p><b>From:</b> ${from}
|
|
||||||
<button onclick="copyToClipboard('${from}')"><i class="fas fa-copy"></i></button></p>
|
|
||||||
<p><b>To:</b> ${to}
|
|
||||||
<button onclick="copyToClipboard('${to}')"><i class="fas fa-copy"></i></button></p>
|
|
||||||
${extraContractLine}
|
|
||||||
<p><b>Amount:</b> <span style="color:#0f0;font-weight:bold">${amount}</span></p>
|
|
||||||
<p><b>Status:</b> <span style="color:${statusColor}">${result}</span></p>
|
|
||||||
`;
|
|
||||||
|
|
||||||
historyDiv.appendChild(card);
|
|
||||||
});
|
|
||||||
|
|
||||||
// save nextUrl for pagination
|
|
||||||
if (data.meta && data.meta.fingerprint) {
|
if (data.meta && data.meta.fingerprint) {
|
||||||
nextUrl = `https://api.shasta.trongrid.io/v1/accounts/${address}/transactions?limit=10&fingerprint=${encodeURIComponent(
|
__nextUrl = `https://api.trongrid.io/v1/accounts/${address}/transactions?limit=${__perPage}&fingerprint=${encodeURIComponent(
|
||||||
data.meta.fingerprint
|
data.meta.fingerprint
|
||||||
)}`;
|
)}`;
|
||||||
} else {
|
} else {
|
||||||
nextUrl = null;
|
__nextUrl = null;
|
||||||
}
|
}
|
||||||
|
__updatePagination();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
return data;
|
||||||
console.error(error);
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
if (typeof __origTransactionHistory === "function") {
|
||||||
|
__origTransactionHistory(url, address);
|
||||||
}
|
}
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function fetchNext(address) {
|
function fetchNext(address) {
|
||||||
if (nextUrl) {
|
if (nextUrl) {
|
||||||
@ -126,50 +73,6 @@ let __currentPage = 1;
|
|||||||
let __currentUrl = null;
|
let __currentUrl = null;
|
||||||
let __perPage = 10;
|
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() {
|
function __renderTransactions() {
|
||||||
const list = document.getElementById("txList");
|
const list = document.getElementById("txList");
|
||||||
const legacy = document.getElementById("historyOutput");
|
const legacy = document.getElementById("historyOutput");
|
||||||
@ -247,10 +150,32 @@ function __renderTransactions() {
|
|||||||
amountText = Number(raw) / 1e6 + " USDT";
|
amountText = Number(raw) / 1e6 + " USDT";
|
||||||
}
|
}
|
||||||
icon = "fa-file-signature";
|
icon = "fa-file-signature";
|
||||||
|
} else if (
|
||||||
|
type === "DelegateResourceContract" ||
|
||||||
|
type === "UnDelegateResourceContract"
|
||||||
|
) {
|
||||||
|
// Handle resource delegation/undelegation
|
||||||
|
const v = tx.raw_data.contract[0].parameter.value;
|
||||||
|
from = tronWeb.address.fromHex(v.owner_address);
|
||||||
|
to = v.receiver_address
|
||||||
|
? tronWeb.address.fromHex(v.receiver_address)
|
||||||
|
: "";
|
||||||
|
amountText =
|
||||||
|
v.balance / 1e6 +
|
||||||
|
" TRX (" +
|
||||||
|
(v.resource ? v.resource : "Bandwidth") +
|
||||||
|
")";
|
||||||
|
directionClass = "resource";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set direction and icon based on transaction direction
|
// Set direction and icon based on transaction direction
|
||||||
if (from === __currentAddress) {
|
if (type === "DelegateResourceContract") {
|
||||||
|
directionClass = "delegate-resource";
|
||||||
|
icon = "fa-exchange-alt"; // custom icon for delegate
|
||||||
|
} else if (type === "UnDelegateResourceContract") {
|
||||||
|
directionClass = "reclaim-resource";
|
||||||
|
icon = "fa-exchange-alt"; // custom icon for undelegate
|
||||||
|
} else if (from === __currentAddress) {
|
||||||
directionClass = "outgoing";
|
directionClass = "outgoing";
|
||||||
icon = "fa-arrow-up"; // upward arrow for sent
|
icon = "fa-arrow-up"; // upward arrow for sent
|
||||||
} else if (to === __currentAddress) {
|
} else if (to === __currentAddress) {
|
||||||
@ -272,7 +197,11 @@ function __renderTransactions() {
|
|||||||
<div class="tx-header">
|
<div class="tx-header">
|
||||||
<div>
|
<div>
|
||||||
<div class="tx-direction">${
|
<div class="tx-direction">${
|
||||||
directionClass === "incoming"
|
directionClass === "delegate-resource"
|
||||||
|
? "Delegate Resources"
|
||||||
|
: directionClass === "reclaim-resource"
|
||||||
|
? "Reclaim Resources"
|
||||||
|
: directionClass === "incoming"
|
||||||
? "Received"
|
? "Received"
|
||||||
: directionClass === "outgoing"
|
: directionClass === "outgoing"
|
||||||
? "Sent"
|
? "Sent"
|
||||||
@ -309,10 +238,22 @@ function __updatePagination() {
|
|||||||
const prevBtn = document.getElementById("prevBtn");
|
const prevBtn = document.getElementById("prevBtn");
|
||||||
const info = document.getElementById("paginationInfo");
|
const info = document.getElementById("paginationInfo");
|
||||||
const pageNumbers = document.getElementById("pageNumbers");
|
const pageNumbers = document.getElementById("pageNumbers");
|
||||||
|
|
||||||
if (nextBtn) nextBtn.disabled = !__nextUrl;
|
if (nextBtn) nextBtn.disabled = !__nextUrl;
|
||||||
if (prevBtn) prevBtn.disabled = __prevUrls.length === 0;
|
if (prevBtn) prevBtn.disabled = __prevUrls.length === 0;
|
||||||
if (info) info.textContent = `Page ${__currentPage} • ${__perPage} / page`;
|
if (info) info.textContent = `Page ${__currentPage} • ${__perPage} / page`;
|
||||||
if (pageNumbers) pageNumbers.innerHTML = __renderPageNumbers();
|
|
||||||
|
if (pageNumbers) {
|
||||||
|
pageNumbers.innerHTML = __renderPageNumbers();
|
||||||
|
|
||||||
|
document.querySelectorAll(".page-number").forEach((button) => {
|
||||||
|
const pageNum = parseInt(button.textContent);
|
||||||
|
if (!isNaN(pageNum)) {
|
||||||
|
button.style.cursor = "pointer";
|
||||||
|
button.addEventListener("click", () => goToPage(pageNum));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTransactionFilter(filter) {
|
function setTransactionFilter(filter) {
|
||||||
@ -348,7 +289,9 @@ function goToPreviousPage() {
|
|||||||
function __renderPageNumbers() {
|
function __renderPageNumbers() {
|
||||||
const parts = [];
|
const parts = [];
|
||||||
const push = (n, active) =>
|
const push = (n, active) =>
|
||||||
`<div class="page-number ${active ? "active" : ""}">${n}</div>`;
|
`<div class="page-number ${
|
||||||
|
active ? "active" : ""
|
||||||
|
}" onclick="goToPage(${n})">${n}</div>`;
|
||||||
// Always show 1
|
// Always show 1
|
||||||
if (__currentPage === 1) parts.push(push(1, true));
|
if (__currentPage === 1) parts.push(push(1, true));
|
||||||
else parts.push(push(1, false));
|
else parts.push(push(1, false));
|
||||||
@ -372,3 +315,60 @@ function resetHistoryState(perPage) {
|
|||||||
__nextUrl = null;
|
__nextUrl = null;
|
||||||
__perPage = perPage || 10;
|
__perPage = perPage || 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to go to a specific page number
|
||||||
|
function goToPage(pageNumber) {
|
||||||
|
if (pageNumber === __currentPage) {
|
||||||
|
return; // Already on the page
|
||||||
|
}
|
||||||
|
|
||||||
|
// If going to page 1, just reset and load initial data
|
||||||
|
if (pageNumber === 1) {
|
||||||
|
__prevUrls = [];
|
||||||
|
__currentPage = 1;
|
||||||
|
const baseUrl = `https://api.trongrid.io/v1/accounts/${__currentAddress}/transactions?limit=${__perPage}`;
|
||||||
|
transactionHistory(baseUrl, __currentAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If trying to go forward
|
||||||
|
if (pageNumber > __currentPage) {
|
||||||
|
// We can only go one page forward at a time due to API pagination limitations
|
||||||
|
if (pageNumber === __currentPage + 1 && __nextUrl) {
|
||||||
|
goToNextPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If trying to go backward
|
||||||
|
if (pageNumber < __currentPage) {
|
||||||
|
// Check if we have the page in our history
|
||||||
|
const targetPrevUrl = __prevUrls.find((prev) => prev.page === pageNumber);
|
||||||
|
if (targetPrevUrl) {
|
||||||
|
// We found the exact page in history
|
||||||
|
while (
|
||||||
|
__prevUrls.length > 0 &&
|
||||||
|
__prevUrls[__prevUrls.length - 1].page >= pageNumber
|
||||||
|
) {
|
||||||
|
__prevUrls.pop();
|
||||||
|
}
|
||||||
|
__currentPage = pageNumber;
|
||||||
|
transactionHistory(targetPrevUrl.url, __currentAddress);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// We need to go back to page 1 and build our way up
|
||||||
|
const baseUrl = `https://api.trongrid.io/v1/accounts/${__currentAddress}/transactions?limit=${__perPage}`;
|
||||||
|
__prevUrls = [];
|
||||||
|
__currentPage = 1;
|
||||||
|
transactionHistory(baseUrl, __currentAddress);
|
||||||
|
|
||||||
|
if (typeof notify === "function") {
|
||||||
|
notify(
|
||||||
|
"Navigating to page 1 due to API pagination limitations",
|
||||||
|
"info",
|
||||||
|
3000
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user