fix: update API endpoints to use mainnet instead of testnet and improve transaction history rendering
This commit is contained in:
parent
70331e19f1
commit
e5bbc8f872
@ -1294,7 +1294,7 @@ body {
|
||||
}
|
||||
|
||||
.tx-direction.offer-create {
|
||||
color: #87ceeb;
|
||||
color: #87ceeb;
|
||||
}
|
||||
|
||||
.transaction-card.offer .tx-direction {
|
||||
@ -1331,7 +1331,7 @@ body {
|
||||
}
|
||||
|
||||
.transaction-card.offer .tx-amount {
|
||||
color: #87ceeb;
|
||||
color: #87ceeb;
|
||||
}
|
||||
|
||||
.transaction-card.offer .tx-direction,
|
||||
@ -2763,7 +2763,7 @@ sm-popup::part(popup) {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* Responsive adjustments for balance info */
|
||||
/* Responsive adjustments for balance info */
|
||||
@media (max-width: 480px) {
|
||||
.detail-row {
|
||||
flex-direction: column;
|
||||
@ -2791,7 +2791,39 @@ sm-popup::part(popup) {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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 */
|
||||
@media (max-width: 768px) {
|
||||
.hamburger-btn {
|
||||
@ -4122,7 +4154,6 @@ sm-popup::part(popup) {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 480px) and (max-height: 740px) {
|
||||
sm-popup::part(popup) {
|
||||
max-height: 95vh !important;
|
||||
@ -4202,7 +4233,7 @@ sm-popup::part(popup) {
|
||||
padding: 0.75rem 1rem;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
min-height: 44px;
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
/* Success popup specific adjustments */
|
||||
@ -4426,6 +4457,24 @@ sm-popup::part(popup) {
|
||||
.tx-detail-label {
|
||||
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 */
|
||||
|
||||
@ -1093,7 +1093,7 @@
|
||||
__historyAddress = address;
|
||||
const perPageSelect = document.getElementById("perPageSelect");
|
||||
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");
|
||||
if (section) section.style.display = "block";
|
||||
resetHistoryState(limit);
|
||||
@ -1137,7 +1137,7 @@
|
||||
perSel.addEventListener("change", () => {
|
||||
if (!__historyAddress) return;
|
||||
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);
|
||||
transactionHistory(url, __historyAddress);
|
||||
});
|
||||
|
||||
@ -38,7 +38,7 @@ function shareTxLink(txid) {
|
||||
});
|
||||
}
|
||||
async function getTransactionDetails(txHash) {
|
||||
const url = "https://api.shasta.trongrid.io/wallet/gettransactionbyid";
|
||||
const url = "https://api.trongrid.io/wallet/gettransactionbyid";
|
||||
const headers = {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
@ -64,7 +64,7 @@ async function getTransactionDetails(txHash) {
|
||||
}
|
||||
|
||||
async function getTransactionInfoById(txHash) {
|
||||
const url = "https://api.shasta.trongrid.io/wallet/gettransactioninfobyid";
|
||||
const url = "https://api.trongrid.io/wallet/gettransactioninfobyid";
|
||||
const headers = {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
@ -168,11 +168,14 @@ async function runBalanceCheck() {
|
||||
`;
|
||||
if (typeof notify === "function") notify("Balance loaded", "success");
|
||||
loadHistoryFor(tronAddress);
|
||||
|
||||
|
||||
// Save searched address to IndexedDB
|
||||
if (typeof searchedAddressDB !== 'undefined') {
|
||||
if (typeof searchedAddressDB !== "undefined") {
|
||||
try {
|
||||
await searchedAddressDB.saveSearchedAddress(tronAddress, balance.toLocaleString());
|
||||
await searchedAddressDB.saveSearchedAddress(
|
||||
tronAddress,
|
||||
balance.toLocaleString()
|
||||
);
|
||||
await updateSearchedAddressesList();
|
||||
} catch (dbError) {
|
||||
console.warn("Failed to save address to IndexedDB:", dbError);
|
||||
@ -183,8 +186,7 @@ async function runBalanceCheck() {
|
||||
} else {
|
||||
// Treat as private key (WIF or HEX)
|
||||
const { tronAddress, balance } = await getBalanceByPrivKey(inputVal);
|
||||
|
||||
|
||||
|
||||
let sourceInfo = null;
|
||||
if (/^[5KLc9RQ][1-9A-HJ-NP-Za-km-z]{50,}$/.test(inputVal)) {
|
||||
// This is a BTC/FLO WIF key
|
||||
@ -192,11 +194,10 @@ async function runBalanceCheck() {
|
||||
type: "Private Key",
|
||||
originalKey: inputVal,
|
||||
originalAddress: inputVal, // Store the original private key for toggling
|
||||
blockchain: /^[KL]/.test(inputVal) ? "BTC" : "FLO"
|
||||
blockchain: /^[KL]/.test(inputVal) ? "BTC" : "FLO",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
output.innerHTML = `
|
||||
<div class="card balance-info">
|
||||
<div class="balance-header">
|
||||
@ -225,11 +226,16 @@ async function runBalanceCheck() {
|
||||
`;
|
||||
if (typeof notify === "function") notify("Balance loaded", "success");
|
||||
loadHistoryFor(tronAddress);
|
||||
|
||||
|
||||
// Save searched address to IndexedDB
|
||||
if (typeof searchedAddressDB !== 'undefined') {
|
||||
if (typeof searchedAddressDB !== "undefined") {
|
||||
try {
|
||||
await searchedAddressDB.saveSearchedAddress(tronAddress, balance.toLocaleString(), Date.now(), sourceInfo);
|
||||
await searchedAddressDB.saveSearchedAddress(
|
||||
tronAddress,
|
||||
balance.toLocaleString(),
|
||||
Date.now(),
|
||||
sourceInfo
|
||||
);
|
||||
await updateSearchedAddressesList();
|
||||
} catch (dbError) {
|
||||
console.warn("Failed to save address to IndexedDB:", dbError);
|
||||
@ -247,7 +253,6 @@ async function runBalanceCheck() {
|
||||
}
|
||||
|
||||
async function runTxSearch() {
|
||||
|
||||
const input = document.getElementById("txHash");
|
||||
const output = document.getElementById("txOutput");
|
||||
const txid = (input.value || "").trim();
|
||||
@ -283,102 +288,176 @@ async function runTxSearch() {
|
||||
(tx.raw_data && tx.raw_data.contract && tx.raw_data.contract[0]) || {};
|
||||
const type = contract.type || "TransferContract";
|
||||
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 =
|
||||
tx.raw_data && tx.raw_data.timestamp
|
||||
? new Date(tx.raw_data.timestamp).toLocaleString()
|
||||
: "-";
|
||||
const fee = txInfo.fee ? txInfo.fee / 1000000 : "-";
|
||||
const blockNumber = txInfo.blockNumber || "-";
|
||||
|
||||
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">
|
||||
<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>
|
||||
<div class="tx-detail-row">
|
||||
<span class="tx-detail-label">
|
||||
<i class="fas fa-receipt"></i>
|
||||
Fee:
|
||||
</span>
|
||||
<span class="tx-detail-value">${fee} TRX</span>
|
||||
</div>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
// Extract resources and fees from both transaction objects
|
||||
|
||||
let bandwidth = undefined;
|
||||
if (txInfo.receipt && txInfo.receipt.net_usage) {
|
||||
bandwidth = txInfo.receipt.net_usage;
|
||||
} else if (tx.net_usage) {
|
||||
bandwidth = tx.net_usage;
|
||||
}
|
||||
|
||||
// Check both transaction info and receipt for energy usage
|
||||
let energy = undefined;
|
||||
if (txInfo.receipt && txInfo.receipt.energy_usage) {
|
||||
energy = txInfo.receipt.energy_usage;
|
||||
} else if (tx.energy_usage) {
|
||||
energy = tx.energy_usage;
|
||||
}
|
||||
|
||||
// Check for fees from multiple sources
|
||||
let fee = "-";
|
||||
if (txInfo.receipt && txInfo.receipt.net_fee) {
|
||||
fee = txInfo.receipt.net_fee / 1000000;
|
||||
} else if (txInfo.fee) {
|
||||
fee = txInfo.fee / 1000000;
|
||||
} else if (tx.fee) {
|
||||
fee = tx.fee / 1000000;
|
||||
}
|
||||
|
||||
// Format the resource consumption and fee HTML
|
||||
let resourcesFeeHtml = "";
|
||||
let feeParts = [];
|
||||
if (bandwidth && bandwidth !== "-")
|
||||
feeParts.push(`<div class="resource-item">${bandwidth} Bandwidth</div>`);
|
||||
if (energy && energy !== "-")
|
||||
feeParts.push(`<div class="resource-item">${energy} Energy</div>`);
|
||||
if (fee && fee !== "-")
|
||||
feeParts.push(`<div class="resource-item">${fee} TRX</div>`);
|
||||
|
||||
if (feeParts.length) {
|
||||
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'>${feeParts.join(
|
||||
""
|
||||
)}</span>
|
||||
</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");
|
||||
} catch (err) {
|
||||
|
||||
@ -55,9 +55,9 @@ function generateBTCFromPrivateKey(privateKey) {
|
||||
}
|
||||
|
||||
async function generateTronWallet() {
|
||||
const fullNode = "https://api.shasta.trongrid.io";
|
||||
const solidityNode = "https://api.shasta.trongrid.io";
|
||||
const eventServer = "https://api.shasta.trongrid.io";
|
||||
const fullNode = "https://api.trongrid.io";
|
||||
const solidityNode = "https://api.trongrid.io";
|
||||
const eventServer = "https://api.trongrid.io";
|
||||
|
||||
const tronWeb = new TronWeb(
|
||||
fullNode,
|
||||
|
||||
@ -7,9 +7,9 @@ function isWif(str) {
|
||||
|
||||
async function recoverAllAddressesFromPrivKey(privKey) {
|
||||
const tronWeb = new TronWeb(
|
||||
"https://api.shasta.trongrid.io",
|
||||
"https://api.shasta.trongrid.io",
|
||||
"https://api.shasta.trongrid.io"
|
||||
"https://api.trongrid.io",
|
||||
"https://api.trongrid.io",
|
||||
"https://api.trongrid.io"
|
||||
);
|
||||
|
||||
try {
|
||||
|
||||
@ -125,12 +125,9 @@ class SearchedAddressDB {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const searchedAddressDB = new SearchedAddressDB();
|
||||
|
||||
|
||||
async function displaySearchedAddresses(addresses) {
|
||||
|
||||
let container = document.getElementById("searchedAddressesContainer");
|
||||
const transactionSection = document.getElementById("transactionSection");
|
||||
|
||||
@ -138,7 +135,7 @@ async function displaySearchedAddresses(addresses) {
|
||||
container = document.createElement("div");
|
||||
container.id = "searchedAddressesContainer";
|
||||
container.className = "card searched-addresses-card";
|
||||
|
||||
|
||||
if (transactionSection && transactionSection.parentNode) {
|
||||
const nextSibling = transactionSection.nextSibling;
|
||||
transactionSection.parentNode.insertBefore(container, nextSibling);
|
||||
@ -169,8 +166,7 @@ async function displaySearchedAddresses(addresses) {
|
||||
${addresses
|
||||
.map((addr, index) => {
|
||||
// Check if this was converted from a private key from another blockchain (BTC/FLO)
|
||||
const hasSourceInfo =
|
||||
addr.sourceInfo && addr.sourceInfo.originalKey;
|
||||
const hasSourceInfo = addr.sourceInfo && addr.sourceInfo.originalKey;
|
||||
|
||||
return `
|
||||
<div class="searched-address-item ${
|
||||
@ -292,9 +288,6 @@ async function toggleAddressType(addressIndex, type) {
|
||||
addressItem.sourceInfo?.originalKey || addressItem.address;
|
||||
addressDisplay.textContent = originalKey;
|
||||
addressDisplay.title = originalKey;
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@ -325,7 +318,9 @@ async function copyCurrentAddress(addressIndex) {
|
||||
} else {
|
||||
// Copy the private key for non-Tron selection
|
||||
valueToCopy = addressItem.sourceInfo?.originalKey || addressItem.address;
|
||||
valueLabel = `${addressItem.sourceInfo?.blockchain || "Original"} private key`;
|
||||
valueLabel = `${
|
||||
addressItem.sourceInfo?.blockchain || "Original"
|
||||
} private key`;
|
||||
}
|
||||
|
||||
await copyAddressToClipboard(valueToCopy, valueLabel);
|
||||
@ -347,16 +342,14 @@ async function deleteSearchedAddress(address) {
|
||||
}
|
||||
|
||||
async function clearAllSearchedAddresses() {
|
||||
|
||||
try {
|
||||
await searchedAddressDB.clearAllSearchedAddresses();
|
||||
await updateSearchedAddressesList();
|
||||
notify("All searched addresses cleared", "success");
|
||||
} catch (error) {
|
||||
console.error("Error clearing searched addresses:", error);
|
||||
notify("Failed to clear addresses", "error");
|
||||
}
|
||||
|
||||
try {
|
||||
await searchedAddressDB.clearAllSearchedAddresses();
|
||||
await updateSearchedAddressesList();
|
||||
notify("All searched addresses cleared", "success");
|
||||
} catch (error) {
|
||||
console.error("Error clearing searched addresses:", error);
|
||||
notify("Failed to clear addresses", "error");
|
||||
}
|
||||
}
|
||||
|
||||
async function copyAddressToClipboard(address, label = "Address") {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const fullNode = "https://api.shasta.trongrid.io";
|
||||
const solidityNode = "https://api.shasta.trongrid.io";
|
||||
const eventServer = "https://api.shasta.trongrid.io";
|
||||
const fullNode = "https://api.trongrid.io";
|
||||
const solidityNode = "https://api.trongrid.io";
|
||||
const eventServer = "https://api.trongrid.io";
|
||||
const tronWeb = new TronWeb(fullNode, solidityNode, eventServer);
|
||||
|
||||
async function sendTrx() {
|
||||
@ -45,14 +45,20 @@ async function sendTrx() {
|
||||
// Broadcast transaction
|
||||
const receipt = await tronWeb.trx.sendRawTransaction(signedtxn);
|
||||
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.");
|
||||
}
|
||||
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.");
|
||||
}
|
||||
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 statusColor = receipt.result ? "green" : "red";
|
||||
@ -143,7 +149,7 @@ async function sendTrx() {
|
||||
`;
|
||||
return receipt;
|
||||
} catch (err) {
|
||||
const outputDiv = document.getElementById("sendOutput");
|
||||
const outputDiv = document.getElementById("sendOutput");
|
||||
outputDiv.innerHTML = `<div class="error-state">
|
||||
<div class="error-icon"><i class="fas fa-exclamation-triangle"></i></div>
|
||||
<h3>Transaction Failed</h3>
|
||||
|
||||
@ -1,103 +1,50 @@
|
||||
const options = { method: "GET", headers: { accept: "application/json" } };
|
||||
let nextUrl = null;
|
||||
|
||||
async function transactionHistory(url, address) {
|
||||
const transactionHistory = async function (url, address) {
|
||||
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 historyDiv = document.getElementById("historyOutput");
|
||||
historyDiv.innerHTML = "";
|
||||
const section = document.getElementById("transactionSection");
|
||||
if (section) section.style.display = "block";
|
||||
|
||||
__currentAddress = address;
|
||||
__currentUrl = url;
|
||||
window.lastUsedUrl = url;
|
||||
|
||||
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;
|
||||
__currentTxs = data.data;
|
||||
// track current per-page from url
|
||||
const m = url.match(/limit=(\d+)/);
|
||||
if (m) __perPage = parseInt(m[1], 10) || __perPage;
|
||||
__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) {
|
||||
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
|
||||
)}`;
|
||||
} else {
|
||||
nextUrl = null;
|
||||
__nextUrl = null;
|
||||
}
|
||||
__updatePagination();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (typeof __origTransactionHistory === "function") {
|
||||
__origTransactionHistory(url, address);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function fetchNext(address) {
|
||||
if (nextUrl) {
|
||||
@ -126,50 +73,6 @@ 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");
|
||||
@ -247,10 +150,32 @@ function __renderTransactions() {
|
||||
amountText = Number(raw) / 1e6 + " USDT";
|
||||
}
|
||||
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
|
||||
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";
|
||||
icon = "fa-arrow-up"; // upward arrow for sent
|
||||
} else if (to === __currentAddress) {
|
||||
@ -272,7 +197,11 @@ function __renderTransactions() {
|
||||
<div class="tx-header">
|
||||
<div>
|
||||
<div class="tx-direction">${
|
||||
directionClass === "incoming"
|
||||
directionClass === "delegate-resource"
|
||||
? "Delegate Resources"
|
||||
: directionClass === "reclaim-resource"
|
||||
? "Reclaim Resources"
|
||||
: directionClass === "incoming"
|
||||
? "Received"
|
||||
: directionClass === "outgoing"
|
||||
? "Sent"
|
||||
@ -309,10 +238,22 @@ function __updatePagination() {
|
||||
const prevBtn = document.getElementById("prevBtn");
|
||||
const info = document.getElementById("paginationInfo");
|
||||
const pageNumbers = document.getElementById("pageNumbers");
|
||||
|
||||
if (nextBtn) nextBtn.disabled = !__nextUrl;
|
||||
if (prevBtn) prevBtn.disabled = __prevUrls.length === 0;
|
||||
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) {
|
||||
@ -348,7 +289,9 @@ function goToPreviousPage() {
|
||||
function __renderPageNumbers() {
|
||||
const parts = [];
|
||||
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
|
||||
if (__currentPage === 1) parts.push(push(1, true));
|
||||
else parts.push(push(1, false));
|
||||
@ -372,3 +315,60 @@ function resetHistoryState(perPage) {
|
||||
__nextUrl = null;
|
||||
__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