tronwallet/index.html
void-57 825560cbd6 Refactor Tron Wallet UI: Merge Balance and Transaction History Pages, Enhance Transaction Search Functionality, and Update URL Management
- Merged balance checking and transaction history into a single Transactions page.
- Updated navigation links and icons for improved user experience.
- Added search type selection for balance and transaction details.
- Implemented URL management for sharing balance and transaction links.
- Enhanced transaction search
- Improved loading states and notifications for user actions.
2025-08-30 20:53:41 +05:30

1149 lines
45 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tron Wallet</title>
<link rel="shortcut icon" href="favicon.svg" type="image/x-icon" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
/>
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<header class="header">
<div class="header-content">
<div id="logo" class="app-brand">
<svg id="main_logo" class="icon" viewBox="0 0 27.25 32">
<title>RanchiMall</title>
<path
d="M27.14,30.86c-.74-2.48-3-4.36-8.25-6.94a20,20,0,0,1-4.2-2.49,6,6,0,0,1-1.25-1.67,4,4,0,0,1,0-2.26c.37-1.08.79-1.57,3.89-4.55a11.66,11.66,0,0,0,3.34-4.67,6.54,6.54,0,0,0,.05-2.82C20,3.6,18.58,2,16.16.49c-.89-.56-1.29-.64-1.3-.24a3,3,0,0,1-.3.72l-.3.55L13.42.94C13,.62,12.4.26,12.19.15c-.4-.2-.73-.18-.72.05a9.39,9.39,0,0,1-.61,1.33s-.14,0-.27-.13C8.76.09,8-.27,8,.23A11.73,11.73,0,0,1,6.76,2.6C4.81,5.87,2.83,7.49.77,7.49c-.89,0-.88,0-.61,1,.22.85.33.92,1.09.69A5.29,5.29,0,0,0,3,8.33c.23-.17.45-.29.49-.26a2,2,0,0,1,.22.63A1.31,1.31,0,0,0,4,9.34a5.62,5.62,0,0,0,2.27-.87L7,8l.13.55c.19.74.32.82,1,.65a7.06,7.06,0,0,0,3.46-2.47l.6-.71-.06.64c-.17,1.63-1.3,3.42-3.39,5.42L6.73,14c-3.21,3.06-3,5.59.6,8a46.77,46.77,0,0,0,4.6,2.41c.28.13,1,.52,1.59.87,3.31,2,4.95,3.92,4.95,5.93a2.49,2.49,0,0,0,.07.77h0c.09.09,0,.1.9-.14a2.61,2.61,0,0,0,.83-.32,3.69,3.69,0,0,0-.55-1.83A11.14,11.14,0,0,0,17,26.81a35.7,35.7,0,0,0-5.1-2.91C9.37,22.64,8.38,22,7.52,21.17a3.53,3.53,0,0,1-1.18-2.48c0-1.38.71-2.58,2.5-4.23,2.84-2.6,3.92-3.91,4.67-5.65a3.64,3.64,0,0,0,.42-2A3.37,3.37,0,0,0,13.61,5l-.32-.74.29-.48c.17-.27.37-.63.46-.8l.15-.3.44.64a5.92,5.92,0,0,1,1,2.81,5.86,5.86,0,0,1-.42,1.94c0,.12-.12.3-.15.4a9.49,9.49,0,0,1-.67,1.1,28,28,0,0,1-4,4.29C8.62,15.49,8.05,16.44,8,17.78a3.28,3.28,0,0,0,1.11,2.76c.95,1,2.07,1.74,5.25,3.32,3.64,1.82,5.22,2.9,6.41,4.38A4.78,4.78,0,0,1,21.94,31a3.21,3.21,0,0,0,.14.92,1.06,1.06,0,0,0,.43-.05l.83-.22.46-.12-.06-.46c-.21-1.53-1.62-3.25-3.94-4.8a37.57,37.57,0,0,0-5.22-2.82A13.36,13.36,0,0,1,11,21.19a3.36,3.36,0,0,1-.8-4.19c.41-.85.83-1.31,3.77-4.15,2.39-2.31,3.43-4.13,3.43-6a5.85,5.85,0,0,0-2.08-4.29c-.23-.21-.44-.43-.65-.65A2.5,2.5,0,0,1,15.27.69a10.6,10.6,0,0,1,2.91,2.78A4.16,4.16,0,0,1,19,6.16a4.91,4.91,0,0,1-.87,3c-.71,1.22-1.26,1.82-4.27,4.67a9.47,9.47,0,0,0-2.07,2.6,2.76,2.76,0,0,0-.33,1.54,2.76,2.76,0,0,0,.29,1.47c.57,1.21,2.23,2.55,4.65,3.73a32.41,32.41,0,0,1,5.82,3.24c2.16,1.6,3.2,3.16,3.2,4.8a1.94,1.94,0,0,0,.09.76,4.54,4.54,0,0,0,1.66-.4C27.29,31.42,27.29,31.37,27.14,30.86ZM6.1,7h0a3.77,3.77,0,0,1-1.46.45L4,7.51l.68-.83a25.09,25.09,0,0,0,3-4.82A12,12,0,0,1,8.28.76c.11-.12.77.32,1.53,1l.63.58-.57.84A10.34,10.34,0,0,1,6.1,7Zm5.71-1.78A9.77,9.77,0,0,1,9.24,7.18h0a5.25,5.25,0,0,1-1.17.28l-.58,0,.65-.78a21.29,21.29,0,0,0,2.1-3.12c.22-.41.42-.76.44-.79s.5.43.9,1.24L12,5ZM13.41,3a2.84,2.84,0,0,1-.45.64,11,11,0,0,1-.9-.91l-.84-.9.19-.45c.34-.79.39-.8,1-.31A9.4,9.4,0,0,1,13.8,2.33q-.18.34-.39.69Z"
/>
</svg>
<div class="app-name">
<div class="app-name__company">RanchiMall</div>
<h4 class="app-name__title">Tron Wallet</h4>
</div>
</div>
<div class="header-actions">
<button
id="themeToggle"
class="theme-toggle"
title="Toggle dark/light mode"
>
<i class="fas fa-sun" id="themeIcon"></i>
</button>
</div>
</div>
</header>
<div class="container">
<nav class="sidebar" id="sidebar">
<div class="sidebar-header">
<i class="fas fa-wallet"></i>
<h3>Tron Wallet</h3>
</div>
<ul class="sidebar-menu">
<li>
<a href="#" onclick="showPage('walletPage')" class="nav-link active"
><i class="fas fa-wallet"></i>Generate</a
>
</li>
<li>
<a href="#" onclick="showPage('sendPage')" class="nav-link"
><i class="fas fa-paper-plane"></i>Send</a
>
</li>
<li>
<a href="#" onclick="showPage('transactionsPage')" class="nav-link"
><i class="fas fa-arrows-rotate"></i>Transactions</a
>
</li>
<li>
<a href="#" onclick="showPage('recoverPage')" class="nav-link"
><i class="fas fa-key"></i>Recover</a
>
</li>
</ul>
</nav>
<main class="main-content">
<!-- Wallet Page -->
<div id="walletPage" class="page">
<div class="page-header">
<h2>
<i class="fas fa-key"></i> Generate Multi-Blockchain Addresses
</h2>
<p>
Generate addresses for TRON, FLO, and Bitcoin from a single
private key
</p>
</div>
<div class="card">
<div class="generate-wallet-intro">
<div class="intro-content">
<h3>One Key, Multiple Blockchains</h3>
<p>
Generate a single private key that works across TRON, FLO, and
Bitcoin networks. This creates a unified experience across
multiple blockchains.
</p>
</div>
</div>
<div class="generate-actions">
<button
id="generateBtn"
class="btn btn-primary btn-block"
onclick="runWalletTest()"
>
<span class="btn-text"> Generate </span>
<span class="btn-loading" style="display: none">
<i class="fas fa-spinner fa-spin"></i> Generating...
</span>
</button>
</div>
<div id="walletOutput"></div>
</div>
</div>
<!-- Send Page -->
<div id="sendPage" class="page hidden">
<div class="page-header">
<h2><i class="fas fa-paper-plane"></i> Send TRX</h2>
</div>
<div class="send-intro">
<div class="intro-content">
<h3>Send TRX Transaction</h3>
<p>Enter your private key and recipient details to send TRX.</p>
</div>
</div>
<div class="card">
<div class="form-group">
<label
><i class="fas fa-key"></i> Private Key (TRX/FLO/BTC):</label
>
<div class="input-with-actions">
<input
id="privKey"
class="form-input"
type="password"
placeholder="Enter your private key (Tron hex or BTC/FLO WIF)"
/>
<button
type="button"
class="input-action-btn password-toggle"
onclick="togglePrivateKeyVisibility('privKey')"
title="Show/Hide Password"
>
<i class="fas fa-eye"></i>
</button>
<button
type="button"
class="input-action-btn clear-btn"
onclick="clearInput('privKey')"
title="Clear"
>
<i class="fas fa-times"></i>
</button>
</div>
<small class="form-help"
>Your sender address will be automatically derived from this
private key</small
>
</div>
<div class="form-group">
<label><i class="fas fa-map-marker-alt"></i> To Address:</label>
<div class="input-with-actions">
<input
id="toAddr"
class="form-input"
placeholder="Enter recipient Tron address"
/>
<button
type="button"
class="input-action-btn clear-btn"
onclick="clearInput('toAddr')"
title="Clear"
>
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div class="form-group">
<label><i class="fas fa-coins"></i> Amount (TRX):</label>
<div class="input-with-actions">
<input
id="amount"
class="form-input"
type="number"
step="0.000001"
placeholder="Enter amount in TRX"
/>
<button
type="button"
class="input-action-btn clear-btn"
onclick="clearInput('amount')"
title="Clear"
>
<i class="fas fa-times"></i>
</button>
</div>
<small class="form-help">Minimum amount: 0.000001 TRX</small>
</div>
<div class="send-actions">
<button
class="btn btn-primary btn-block"
onclick="openSendConfirm()"
id="sendBtn"
>
<span class="btn-text"
><i class="fas fa-paper-plane"></i> Send TRX</span
>
<span class="btn-loading" style="display: none">
<i class="fas fa-spinner fa-spin"></i> Sending...
</span>
</button>
</div>
<div id="sendOutput"></div>
</div>
</div>
<!-- Transactions Page (Merged Balance + History + TX Search) -->
<div id="transactionsPage" class="page hidden">
<div class="page-header">
<h2><i class="fas fa-arrows-rotate"></i> Transactions</h2>
<p>Check balance, browse history, and search by transaction hash</p>
</div>
<!-- Balance Card -->
<div class="card">
<div class="search-type-section">
<label class="search-type-label">Search Type:</label>
<div class="search-type-buttons">
<button
class="search-type-btn active"
data-type="balance"
onclick="setSearchType('balance')"
>
<i class="fas fa-wallet"></i> Balance & History
</button>
<button
class="search-type-btn"
data-type="transaction"
onclick="setSearchType('transaction')"
>
<i class="fas fa-file-alt"></i> Transaction Details
</button>
</div>
</div>
<div class="form-group">
<label
><i class="fas fa-map-marker-alt"></i> Tron Address / Private
Key (FLO/BTC):</label
>
<div class="input-with-actions">
<input
id="balanceAddr"
class="form-input"
placeholder="Enter Tron address / Private Key"
/>
<button
type="button"
class="input-action-btn clear-btn"
onclick="clearInput('balanceAddr')"
title="Clear"
>
<i class="fas fa-times"></i>
</button>
</div>
<small class="form-help"
>Enter an address, private key (BTC/FLO), or Tron hex to check
balance.</small
>
</div>
<button
class="btn btn-primary btn-block"
onclick="runBalanceCheck()"
id="balanceBtn"
>
<span class="btn-text"
><i class="fas fa-search"></i> Check Balance</span
>
<span class="btn-loading" style="display: none">
<i class="fas fa-spinner fa-spin"></i> Loading...
</span>
</button>
<div id="balanceOutput"></div>
</div>
<!-- TX Search Card -->
<div class="card">
<div class="search-type-section">
<label class="search-type-label">Search Type:</label>
<div class="search-type-buttons">
<button
class="search-type-btn"
data-type="balance"
onclick="setSearchType('balance')"
>
<i class="fas fa-wallet"></i> Balance & History
</button>
<button
class="search-type-btn active"
data-type="transaction"
onclick="setSearchType('transaction')"
>
<i class="fas fa-file-alt"></i> Transaction Details
</button>
</div>
</div>
<div class="form-group">
<label
><i class="fas fa-file-alt"></i> Transaction Hash (TX
ID):</label
>
<div class="input-with-actions">
<input
id="txHash"
class="form-input"
placeholder="Enter transaction hash (TX ID)"
/>
<button
type="button"
class="input-action-btn clear-btn"
onclick="clearInput('txHash')"
title="Clear"
>
<i class="fas fa-times"></i>
</button>
</div>
<small class="form-help"
>Enter a transaction hash to view transaction details.</small
>
</div>
<button
class="btn btn-primary btn-block"
onclick="runTxSearch()"
id="txSearchBtn"
>
<span class="btn-text"
><i class="fas fa-search"></i> View Transaction</span
>
<span class="btn-loading" style="display: none">
<i class="fas fa-spinner fa-spin"></i> Searching...
</span>
</button>
<div id="txOutput"></div>
</div>
<div
id="transactionSection"
class="card transaction-section"
style="display: none"
>
<div id="transactionControls" class="transaction-controls">
<div class="transaction-header">
<h3>Transactions</h3>
<div class="filter-buttons">
<button
class="filter-btn active"
data-filter="all"
onclick="setTransactionFilter('all')"
>
<i class="fas fa-list"></i> All
</button>
<button
class="filter-btn"
data-filter="received"
onclick="setTransactionFilter('received')"
>
<i class="fas fa-arrow-down"></i> Received
</button>
<button
class="filter-btn"
data-filter="sent"
onclick="setTransactionFilter('sent')"
>
<i class="fas fa-arrow-up"></i> Sent
</button>
</div>
</div>
</div>
<div id="txList" class="transaction-list"></div>
<div class="pagination-section">
<div class="pagination-info" id="paginationInfo">
Showing 0 - 0 of 0 transactions
</div>
<div class="pagination-controls">
<button
class="pagination-btn"
id="prevBtn"
onclick="goToPreviousPage()"
disabled
>
<i class="fas fa-chevron-left"></i>
</button>
<div class="page-numbers" id="pageNumbers"></div>
<button
class="pagination-btn"
id="nextBtn"
onclick="goToNextPage()"
disabled
>
<i class="fas fa-chevron-right"></i>
</button>
<select
id="perPageSelect"
class="pagination-btn"
style="min-width: 90px"
>
<option value="10">10 / page</option>
<option value="20">20 / page</option>
<option value="50">50 / page</option>
</select>
</div>
</div>
</div>
</div>
<!-- Recover Page -->
<div id="recoverPage" class="page hidden">
<div class="page-header">
<h2>
<i class="fas fa-key"></i> Recover Multi-Blockchain Addresses
</h2>
<p>
Recover all blockchain addresses (TRON, FLO, Bitcoin) from a
single private key
</p>
</div>
<div class="card">
<div class="form-group">
<label
><i class="fas fa-key"></i> Private Key (TRX/FLO/BTC):</label
>
<div class="input-with-actions">
<input
id="recoveryPrivKey"
class="form-input"
type="password"
placeholder="Enter your private key (Tron hex or BTC/FLO WIF)"
/>
<button
type="button"
class="input-action-btn password-toggle"
onclick="togglePrivateKeyVisibility('recoveryPrivKey')"
title="Show/Hide Password"
>
<i class="fas fa-eye"></i>
</button>
<button
type="button"
class="input-action-btn clear-btn"
onclick="clearInput('recoveryPrivKey')"
title="Clear"
>
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div class="recover-actions">
<button
class="btn btn-primary btn-block"
onclick="runAddressRecovery()"
id="recoverBtn"
>
<span class="btn-text"
><i class="fas fa-search"></i> Recover All Addresses</span
>
<span class="btn-loading" style="display: none">
<i class="fas fa-spinner fa-spin"></i> Recovering...
</span>
</button>
</div>
<div id="recoveryOutput"></div>
</div>
</div>
</main>
</div>
<!-- Confirmation Popup for Send TRX -->
<sm-popup id="sendConfirm">
<div class="modern-popup-container">
<div class="popup-header">
<div class="popup-icon confirm-icon">
<i class="fas fa-shield-alt"></i>
</div>
<h2 class="popup-title">Confirm Transaction</h2>
<p class="popup-subtitle">
Please review the transaction details before sending
</p>
</div>
<div class="transaction-summary">
<div class="summary-item amount-highlight">
<div class="summary-icon"><i class="fas fa-coins"></i></div>
<div class="summary-content">
<span class="summary-label">Amount to Send</span>
<span class="summary-value" id="confirmAmount">0 TRX</span>
</div>
</div>
<div class="summary-item">
<div class="summary-icon"><i class="fas fa-user-minus"></i></div>
<div class="summary-content">
<span class="summary-label">From</span>
<span class="summary-value address-text" id="confirmFrom">-</span>
</div>
</div>
<div class="summary-item">
<div class="summary-icon"><i class="fas fa-user-plus"></i></div>
<div class="summary-content">
<span class="summary-label">To</span>
<span class="summary-value address-text" id="confirmTo">-</span>
</div>
</div>
<div class="summary-item">
<div class="summary-icon"><i class="fas fa-receipt"></i></div>
<div class="summary-content">
<span class="summary-label">Network Fee</span>
<span class="summary-value" id="confirmFee">~0.000001 TRX</span>
</div>
</div>
</div>
<div class="popup-actions modern-actions">
<button onclick="closePopup('sendConfirm')" class="btn btn-cancel">
<i class="fas fa-times"></i><span>Cancel</span>
</button>
<button onclick="confirmSendTrx()" class="btn btn-confirm">
<i class="fas fa-paper-plane"></i><span>Confirm</span>
</button>
</div>
</div>
</sm-popup>
<!-- Success Popup -->
<sm-popup id="transactionSuccess">
<div class="modern-popup-container success-popup">
<div class="popup-header success-header">
<div class="popup-icon success-icon">
<i class="fas fa-check-circle"></i>
</div>
<h2 class="popup-title">Transaction Successful!</h2>
<p class="popup-subtitle">Your TRX has been sent successfully</p>
</div>
<div class="success-details">
<div class="success-summary">
<div class="success-item">
<span class="success-label">Amount Sent</span
><span class="success-value" id="successAmount">0 TRX</span>
</div>
<div class="success-item">
<span class="success-label">Network Fee</span
><span class="success-value" id="successFee">0 TRX</span>
</div>
</div>
<div class="transaction-details">
<div class="detail-row">
<span class="detail-label"
><i class="fas fa-hashtag"></i> Hash</span
><span class="detail-value" id="successHash">-</span>
</div>
<div class="detail-row">
<span class="detail-label"
><i class="fas fa-user-minus"></i> From</span
><span class="detail-value" id="successFrom">-</span>
</div>
<div class="detail-row">
<span class="detail-label"
><i class="fas fa-user-plus"></i> To</span
><span class="detail-value" id="successTo">-</span>
</div>
</div>
</div>
<div class="popup-actions modern-actions">
<button
onclick="closePopup('transactionSuccess')"
class="btn btn-done"
>
<i class="fas fa-check"></i><span>Done</span>
</button>
</div>
</div>
</sm-popup>
<!-- Bottom Navigation (Mobile) -->
<div class="nav-box">
<button
onclick="showPage('walletPage')"
class="nav-btn active"
data-page="walletPage"
>
<i class="fas fa-wallet"></i><span>Generate</span>
</button>
<button
onclick="showPage('sendPage')"
class="nav-btn"
data-page="sendPage"
>
<i class="fas fa-paper-plane"></i><span>Send</span>
</button>
<button
onclick="showPage('transactionsPage')"
class="nav-btn"
data-page="transactionsPage"
>
<i class="fas fa-arrows-rotate"></i><span>Transactions</span>
</button>
<button
onclick="showPage('recoverPage')"
class="nav-btn"
data-page="recoverPage"
>
<i class="fas fa-key"></i><span>Recover</span>
</button>
</div>
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/npm/tronweb@5.3.2/dist/TronWeb.js"></script>
<script src="./scripts/btcwallet_scripts_lib.js"></script>
<script src="./scripts/btcOperator.js"></script>
<script src="./scripts/floCrypto.js"></script>
<script src="./scripts/components.min.js"></script>
<script src="./scripts/genMultichainAddress.js"></script>
<script src="./scripts/transactionHistory.js"></script>
<script src="./scripts/sendTRX.js"></script>
<script src="./scripts/recoverAddress.js"></script>
<script src="./scripts/balance.js"></script>
<script>
// Theme toggle
function initializeTheme() {
const themeToggle = document.getElementById("themeToggle");
const body = document.body;
const savedTheme = localStorage.getItem("theme");
const systemPrefersDark = window.matchMedia(
"(prefers-color-scheme: dark)"
).matches;
let currentTheme = savedTheme || (systemPrefersDark ? "dark" : "light");
body.setAttribute("data-theme", currentTheme);
updateThemeIcon(currentTheme);
if (themeToggle) {
themeToggle.addEventListener("click", () => {
currentTheme = currentTheme === "light" ? "dark" : "light";
body.setAttribute("data-theme", currentTheme);
localStorage.setItem("theme", currentTheme);
updateThemeIcon(currentTheme);
if (typeof notify === "function") {
notify(`Switched to ${currentTheme} mode`, "success");
}
});
}
}
function updateThemeIcon(theme) {
const themeIcon = document.getElementById("themeIcon");
if (!themeIcon) return;
themeIcon.className = theme === "dark" ? "fas fa-sun" : "fas fa-moon";
}
function notify(message, type = "success", durationMs = 3000) {
const drawer = document.getElementById("notification_drawer");
if (!drawer) return;
const note = document.createElement("div");
note.className = `notification ${type}`;
note.style.animation = "slideInRight 250ms ease-out";
note.innerHTML = `<span>${message}</span>`;
drawer.appendChild(note);
const remove = () => {
note.style.animation = "slideOutRight 200ms ease-in forwards";
setTimeout(() => note.remove(), 200);
};
setTimeout(remove, durationMs);
note.addEventListener("click", remove);
}
// Send TRX confirmation flow
function openSendConfirm() {
const privateKey = document.getElementById("privKey").value.trim();
const to = document.getElementById("toAddr").value.trim();
const amount = document.getElementById("amount").value.trim();
if (!privateKey || !to || !amount) {
if (typeof notify === "function") {
notify("Please fill all required fields", "error");
} else {
alert("Please fill Private Key, To Address and Amount");
}
return;
}
// Validate private key format
if (
!/^[0-9a-fA-F]{64}$/.test(privateKey) &&
!/^[5KLc9RQ][1-9A-HJ-NP-Za-km-z]{50,}$/.test(privateKey)
) {
if (typeof notify === "function") {
notify("Invalid private key format", "error");
} else {
alert("Invalid private key format");
}
return;
}
// Derive from address from private key
let fromAddress;
try {
if (/^[5KLc9RQ][1-9A-HJ-NP-Za-km-z]{50,}$/.test(privateKey)) {
// WIF format - convert to hex first
const decoded = coinjs.wif2privkey(privateKey);
if (!decoded || !decoded.privkey) {
if (typeof notify === "function") {
notify("Invalid WIF private key", "error");
} else {
alert("Invalid WIF private key");
}
return;
}
fromAddress = tronWeb.address.fromPrivateKey(decoded.privkey);
} else {
// Hex format
fromAddress = tronWeb.address.fromPrivateKey(privateKey);
}
} catch (error) {
if (typeof notify === "function") {
notify("Error deriving address from private key", "error");
} else {
alert("Error deriving address from private key");
}
return;
}
document.getElementById("confirmFrom").textContent = fromAddress;
document.getElementById("confirmTo").textContent = to;
document.getElementById("confirmAmount").textContent = amount + " TRX";
openPopup("sendConfirm");
}
function confirmSendTrx() {
closePopup("sendConfirm");
// Set loading state
setButtonLoading("sendBtn", true);
// Call existing sender
sendTrx()
.then((receipt) => {
try {
if (receipt && typeof receipt === "object") {
const to = document.getElementById("toAddr").value.trim();
const amount = document.getElementById("amount").value.trim();
const privateKey = document
.getElementById("privKey")
.value.trim();
// Derive from address from private key for confirmation popup
let fromAddress;
if (/^[5KLc9RQ][1-9A-HJ-NP-Za-km-z]{50,}$/.test(privateKey)) {
// WIF format - convert to hex first
const decoded = coinjs.wif2privkey(privateKey);
if (decoded && decoded.privkey) {
fromAddress = tronWeb.address.fromPrivateKey(
decoded.privkey
);
}
} else if (/^[0-9a-fA-F]{64}$/.test(privateKey)) {
// Hex format
fromAddress = tronWeb.address.fromPrivateKey(privateKey);
}
document.getElementById("successAmount").textContent =
amount + " TRX";
document.getElementById("successFee").textContent = "~0 TRX";
document.getElementById("successFrom").textContent =
fromAddress || "—";
document.getElementById("successTo").textContent = to;
document.getElementById("successHash").textContent =
receipt.txid || "—";
openPopup("transactionSuccess");
if (typeof notify === "function")
notify("Transaction broadcasted", "success");
}
} catch (e) {}
})
.catch(() => {})
.finally(() => {
// Clear loading state
setButtonLoading("sendBtn", false);
});
}
function openPopup(id) {
const el = document.getElementById(id);
if (el && el.show) el.show();
else if (el && el.open) el.open();
else if (el) el.setAttribute("open", "");
}
function closePopup(id) {
const el = document.getElementById(id);
if (el && el.hide) el.hide();
else if (el && el.close) el.close();
else if (el) el.removeAttribute("open");
}
function showPage(pageId) {
document
.querySelectorAll(".page")
.forEach((page) => page.classList.add("hidden"));
document.getElementById(pageId).classList.remove("hidden");
document
.querySelectorAll(".sidebar .nav-link")
.forEach((link) => link.classList.remove("active"));
document
.querySelectorAll(".nav-btn")
.forEach((btn) => btn.classList.remove("active"));
const sidebarLink = document.querySelector(
`.sidebar .nav-link[onclick*="${pageId}"]`
);
if (sidebarLink) sidebarLink.classList.add("active");
const navBtn = document.querySelector(
`.nav-btn[data-page="${pageId}"]`
);
if (navBtn) navBtn.classList.add("active");
}
// Wallet generation
async function runWalletTest() {
const out = document.getElementById("walletOutput");
// Set loading state
setButtonLoading("generateBtn", true);
// Show notification
if (typeof notify === "function") {
notify("Generating...", "success", 1500);
}
try {
const tronWallet = await generateTronWallet();
const floWallet = generateFLOFromPrivateKey(tronWallet.privateKey);
const btcWallet = generateBTCFromPrivateKey(tronWallet.privateKey);
out.innerHTML = `
<div class="wallet-generated-success">
<div class="success-header">
<div class="success-icon">
<i class="fas fa-check-circle"></i>
</div>
<h3>Addresses Generated Successfully!</h3>
<p>Your multi-blockchain addresses have been created. All addresses are derived from the same private key.</p>
</div>
</div>
<div class="blockchain-section">
<div class="blockchain-header">
<h4><i class="fas fa-coins"></i> TRON (TRX)</h4>
<div class="blockchain-badge primary">Primary</div>
</div>
<div class="detail-row">
<label><i class="fas fa-map-marker-alt"></i> TRON Address</label>
<div class="value-container">
<code>${tronWallet.address}</code>
<button class="btn-icon" onclick="navigator.clipboard.writeText('${
tronWallet.address
}').then(()=>notify && notify('TRON address copied','success'))" title="Copy TRON Address">
<i class="fas fa-copy"></i>
</button>
</div>
</div>
<div class="detail-row">
<label><i class="fas fa-key"></i> TRON Private Key</label>
<div class="value-container">
<code>${tronWallet.privateKey}</code>
<button class="btn-icon" onclick="navigator.clipboard.writeText('${
tronWallet.privateKey
}').then(()=>notify && notify('Private key copied','success'))" title="Copy Private Key">
<i class="fas fa-copy"></i>
</button>
</div>
</div>
</div>
${
floWallet
? `
<div class="blockchain-section">
<div class="blockchain-header">
<h4><i class="fas fa-coins"></i> FLO</h4>
<div class="blockchain-badge secondary">Secondary</div>
</div>
<div class="detail-row">
<label><i class="fas fa-map-marker-alt"></i> FLO Address</label>
<div class="value-container">
<code>${floWallet.address}</code>
<button class="btn-icon" onclick="navigator.clipboard.writeText('${floWallet.address}').then(()=>notify && notify('FLO address copied','success'))" title="Copy FLO Address">
<i class="fas fa-copy"></i>
</button>
</div>
</div>
<div class="detail-row">
<label><i class="fas fa-key"></i> FLO Private Key</label>
<div class="value-container">
<code>${floWallet.privateKey}</code>
<button class="btn-icon" onclick="navigator.clipboard.writeText('${floWallet.privateKey}').then(()=>notify && notify('Private key copied','success'))" title="Copy Private Key">
<i class="fas fa-copy"></i>
</button>
</div>
</div>
</div>`
: ""
}
${
btcWallet
? `
<div class="blockchain-section">
<div class="blockchain-header">
<h4><i class="fab fa-btc"></i> Bitcoin (BTC)</h4>
<div class="blockchain-badge secondary">Secondary</div>
</div>
<div class="detail-row">
<label><i class="fas fa-map-marker-alt"></i> BTC Address</label>
<div class="value-container">
<code>${btcWallet.address}</code>
<button class="btn-icon" onclick="navigator.clipboard.writeText('${btcWallet.address}').then(()=>notify && notify('BTC address copied','success'))" title="Copy BTC Address">
<i class="fas fa-copy"></i>
</button>
</div>
</div>
<div class="detail-row">
<label><i class="fas fa-key"></i> BTC Private Key</label>
<div class="value-container">
<code>${btcWallet.privateKey}</code>
<button class="btn-icon" onclick="navigator.clipboard.writeText('${btcWallet.privateKey}').then(()=>notify && notify('Private key copied','success'))" title="Copy Private Key">
<i class="fas fa-copy"></i>
</button>
</div>
</div>
</div>`
: ""
}
<div class="wallet-security-notice">
<div class="notice-icon">
<i class="fas fa-shield-alt"></i>
</div>
<div class="notice-content">
<h4>Security Reminder</h4>
<p>Keep your private key safe and secure. Never share it with anyone. Consider backing it up in a secure location.</p>
</div>
</div>
`;
// Show success notification
if (typeof notify === "function") {
notify("Addresses generated successfully!", "success");
}
} catch (err) {
out.innerHTML = `
<div class="error-state">
<div class="error-icon">
<i class="fas fa-exclamation-triangle"></i>
</div>
<h3>Generation Failed</h3>
<p>Error: ${err.message}</p>
<button class="btn btn-secondary" onclick="runWalletTest()">
<i class="fas fa-redo"></i> Try Again
</button>
</div>
`;
// Show error notification
if (typeof notify === "function") {
notify(err.message, "error");
}
} finally {
// Clear loading state
setButtonLoading("generateBtn", false);
}
}
// Loading state management functions
function setButtonLoading(buttonId, isLoading) {
const button = document.getElementById(buttonId);
if (!button) return;
const btnText = button.querySelector(".btn-text");
const btnLoading = button.querySelector(".btn-loading");
if (isLoading) {
button.disabled = true;
if (btnText) btnText.style.display = "none";
if (btnLoading) btnLoading.style.display = "inline";
} else {
button.disabled = false;
if (btnText) btnText.style.display = "inline";
if (btnLoading) btnLoading.style.display = "none";
}
}
// Private key visibility toggle function
function togglePrivateKeyVisibility(inputId) {
const input = document.getElementById(inputId);
const toggleBtn =
input.parentElement.querySelector(".password-toggle i");
if (input.type === "password") {
input.type = "text";
toggleBtn.className = "fas fa-eye-slash";
toggleBtn.parentElement.title = "Hide Password";
} else {
input.type = "password";
toggleBtn.className = "fas fa-eye";
toggleBtn.parentElement.title = "Show Password";
}
}
// Clear input function
function clearInput(inputId) {
const input = document.getElementById(inputId);
input.value = "";
input.focus();
// Clear corresponding output areas based on input field
switch (inputId) {
case "privKey":
case "toAddr":
case "amount":
// Clear send page output
const sendOutput = document.getElementById("sendOutput");
if (sendOutput) sendOutput.innerHTML = "";
break;
case "historyAddr":
// Clear history page output
const transactionSection =
document.getElementById("transactionSection");
if (transactionSection) transactionSection.style.display = "none";
break;
case "recoveryPrivKey":
// Clear recover page output
const recoveryOutput = document.getElementById("recoveryOutput");
if (recoveryOutput) recoveryOutput.innerHTML = "";
break;
case "balanceAddr":
// Clear balance page output
const balanceOutput = document.getElementById("balanceOutput");
if (balanceOutput) balanceOutput.innerHTML = "";
break;
case "txHash":
// Clear tx search output
const txOutput = document.getElementById("txOutput");
if (txOutput) txOutput.innerHTML = "";
break;
}
// Show notification
if (typeof notify === "function") {
notify("Input cleared", "success", 1000);
}
}
// Search type management
let __currentSearchType = "balance";
function setSearchType(type) {
__currentSearchType = type;
document.querySelectorAll(".search-type-btn").forEach((btn) => {
btn.classList.remove("active");
});
document.querySelectorAll(`[data-type="${type}"]`).forEach((btn) => {
btn.classList.add("active");
});
// Show/hide cards based on search type
const balanceCard = document
.querySelector("#balanceOutput")
.closest(".card");
const txCard = document.querySelector("#txOutput").closest(".card");
if (type === "balance") {
if (balanceCard) balanceCard.style.display = "block";
if (txCard) txCard.style.display = "none";
updateURLForPage(
"balance",
document.getElementById("balanceAddr").value.trim()
);
} else {
if (balanceCard) balanceCard.style.display = "none";
if (txCard) txCard.style.display = "block";
updateURLForPage(
"transaction",
document.getElementById("txHash").value.trim()
);
const historyOutput = document.getElementById("historyOutput");
if (historyOutput) historyOutput.innerHTML = "";
const transactionSection =
document.getElementById("transactionSection");
if (transactionSection) transactionSection.style.display = "none";
}
}
// History (auto-load after balance)
let __historyAddress = "";
function loadHistoryFor(address) {
__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 section = document.getElementById("transactionSection");
if (section) section.style.display = "block";
resetHistoryState(limit);
transactionHistory(url, address);
}
// Init theme on load
document.addEventListener("DOMContentLoaded", initializeTheme);
document.addEventListener("DOMContentLoaded", () => {
const txCard = document.querySelector("#txOutput").closest(".card");
if (txCard) txCard.style.display = "none";
});
document.addEventListener("DOMContentLoaded", () => {
const params = new URLSearchParams(window.location.search);
const page = params.get("page");
if (page === "transactions") {
showPage("transactionsPage");
const address = params.get("address");
const tx = params.get("tx");
if (tx) {
setSearchType("transaction");
const txInput = document.getElementById("txHash");
if (txInput) {
txInput.value = tx;
runTxSearch();
}
} else if (address) {
setSearchType("balance");
const input = document.getElementById("balanceAddr");
if (input) {
input.value = address;
runBalanceCheck();
}
}
}
});
const perSel = document.getElementById("perPageSelect");
if (perSel) {
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}`;
resetHistoryState(limit);
transactionHistory(url, __historyAddress);
});
}
</script>
<div id="notification_drawer" class="notification-drawer"></div>
</body>
</html>