Files
nebula/_migrate/accounts.html

1769 lines
69 KiB
HTML

<!DOCTYPE html>
<!--
================================================================================
TEMPL MIGRATION GUIDE: accounts.html → views/accounts.templ
================================================================================
PAGE OVERVIEW:
- Main wallet dashboard with sidebar navigation
- Stats cards: Total Balance, 24h Change, Assets count, Pending count
- Token balances list with actions (send/receive/swap via dropdown)
- Recent transactions table with copy-hash buttons
- Connected accounts grid with "Create Account" dialog (3-step wizard)
- Slide-out drawers for Send, Receive, and Swap operations
MAIN TEMPL COMPONENT:
templ AccountsPage(wallet WalletData) {
@layouts.DashboardLayout("accounts") {
@PageHeader("Accounts", "Manage your crypto assets")
@QuickActions()
@StatsGrid(wallet.Stats)
<div class="wa-grid">
@TokenBalancesCard(wallet.Tokens)
@RecentTransactionsCard(wallet.Transactions)
</div>
@ConnectedAccountsCard(wallet.Accounts)
}
@ReceiveDrawer()
@SendDrawer()
@SwapDrawer()
@CreateAccountDialog()
}
HTMX INTEGRATION:
- Drawer triggers: hx-get="/drawers/receive" hx-target="#drawer-container" hx-swap="innerHTML"
- Token actions dropdown: hx-get="/drawers/send?token=SNR" hx-target="#drawer-container"
- Transaction copy: Use client-side wa-copy-button (no HTMX needed)
- Create account wizard: hx-post="/accounts/create" with step state
- Network selection: hx-post="/accounts/create/network" hx-vals='{"network":"sonr"}'
- Stats refresh: hx-get="/api/wallet/stats" hx-trigger="every 30s" hx-target="#stats-grid"
SUB-COMPONENTS TO EXTRACT:
- DashboardLayout(activePage string) // Shared sidebar + main content wrapper
- Sidebar(activePage string)
- StatsGrid(stats WalletStats)
- StatCard(icon string, label string, value templ.Component, badge templ.Component)
- TokenBalancesCard(tokens []Token)
- TokenRow(token Token)
- RecentTransactionsCard(txs []Transaction)
- TransactionRow(tx Transaction)
- ConnectedAccountsCard(accounts []Account)
- AccountCard(account Account, isActive bool)
- ReceiveDrawer(selectedToken string)
- SendDrawer(tokens []Token)
- SwapDrawer(tokens []Token)
- CreateAccountDialog(step int, network string)
- NetworkOption(network Network, selected bool)
- DerivationPathSelector(path string)
STATE/PROPS:
type WalletData struct {
Stats WalletStats
Tokens []Token
Transactions []Transaction
Accounts []Account
}
type WalletStats struct {
TotalBalance float64
Change24h float64
ChangePercent float64
AssetCount int
PendingCount int
}
type Token struct {
Symbol string
Name string
Balance float64
ValueUSD float64
IconColor string
}
type Transaction struct {
Type string // "send", "receive", "swap"
Asset string
Amount float64
ValueUSD float64
Date time.Time
Hash string
}
type Account struct {
Label string
Address string
Network string
IsActive bool
}
HTMX PATTERNS:
// Quick action buttons opening drawers via HTMX
<wa-button hx-get="/drawers/receive" hx-target="#drawer-container" hx-swap="innerHTML">
Receive
</wa-button>
// Token row dropdown actions
<wa-dropdown-item hx-get="/drawers/send?token={token.Symbol}" hx-target="#drawer-container">
Send
</wa-dropdown-item>
// Stats grid auto-refresh
<div id="stats-grid" hx-get="/api/wallet/stats" hx-trigger="every 30s" hx-swap="innerHTML">
@StatsGrid(stats)
</div>
// Send form submission
<form hx-post="/api/transactions/send"
hx-target="#send-result"
hx-indicator="#send-spinner">
// Create account wizard step navigation
<wa-button hx-post="/accounts/create/step"
hx-vals='{"step": "2", "network": selectedNetwork}'
hx-target="#dialog-content">
// Drawer container for OOB swaps
<div id="drawer-container"></div>
// Close drawer via OOB
templ CloseDrawer() {
<wa-drawer id="active-drawer" hx-swap-oob="true"></wa-drawer>
}
================================================================================
-->
<html lang="en" class="wa-cloak">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Accounts - Sonr Motr Wallet</title>
<script src="https://cdn.sonr.org/wa/autoloader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script src="charts.js"></script>
<style>
:root {
--wa-color-primary: #17c2ff;
}
html, body {
min-height: 100%;
padding: 0;
margin: 0;
}
.dashboard-layout {
display: grid;
grid-template-columns: 240px 1fr;
min-height: 100vh;
}
@media (max-width: 768px) {
.dashboard-layout {
grid-template-columns: 1fr;
}
.sidebar {
display: none;
}
}
.sidebar {
border-right: 1px solid var(--wa-color-neutral-200);
padding: var(--wa-space-m);
background: var(--wa-color-surface);
}
.sidebar-header {
padding: var(--wa-space-s) var(--wa-space-xs);
margin-bottom: var(--wa-space-m);
}
.sidebar-nav {
list-style: none;
padding: 0;
margin: 0;
}
.sidebar-nav li {
margin-bottom: var(--wa-space-2xs);
}
.sidebar-nav a {
display: flex;
align-items: center;
gap: var(--wa-space-s);
padding: var(--wa-space-s) var(--wa-space-m);
border-radius: var(--wa-radius-m);
text-decoration: none;
color: var(--wa-color-neutral-700);
font-size: var(--wa-font-size-s);
transition: background 0.15s;
}
.sidebar-nav a:hover {
background: var(--wa-color-surface-alt);
}
.sidebar-nav a.active {
background: var(--wa-color-primary-subtle);
color: var(--wa-color-primary);
font-weight: 500;
}
.main-content {
padding: var(--wa-space-xl);
background: var(--wa-color-surface-alt);
overflow-y: auto;
}
.page-header {
margin-bottom: var(--wa-space-xl);
}
.stats-grid {
--min-column-size: 220px;
margin-bottom: var(--wa-space-xl);
}
.stat-card {
background: var(--wa-color-surface);
}
.token-row {
display: flex;
align-items: center;
padding: var(--wa-space-m) 0;
border-bottom: 1px solid var(--wa-color-neutral-100);
}
.token-row:last-child {
border-bottom: none;
}
.token-info {
display: flex;
align-items: center;
gap: var(--wa-space-s);
flex: 1;
}
.token-balance {
text-align: right;
}
.token-actions {
margin-left: var(--wa-space-m);
}
.tx-table {
width: 100%;
border-collapse: collapse;
}
.tx-table th {
text-align: left;
padding: var(--wa-space-s) var(--wa-space-m);
font-size: var(--wa-font-size-xs);
font-weight: 500;
color: var(--wa-color-neutral-500);
text-transform: uppercase;
letter-spacing: 0.05em;
border-bottom: 1px solid var(--wa-color-neutral-200);
}
.tx-table td {
padding: var(--wa-space-m);
border-bottom: 1px solid var(--wa-color-neutral-100);
font-size: var(--wa-font-size-s);
}
.tx-table tr:hover td {
background: var(--wa-color-surface-alt);
}
.tx-type {
display: inline-flex;
align-items: center;
gap: var(--wa-space-xs);
}
.tx-type.send { color: var(--wa-color-danger); }
.tx-type.receive { color: var(--wa-color-success); }
.tx-type.swap { color: var(--wa-color-primary); }
.address-mono {
font-family: var(--wa-font-mono);
font-size: var(--wa-font-size-xs);
}
.quick-actions {
display: flex;
gap: var(--wa-space-s);
}
.empty-state {
text-align: center;
padding: var(--wa-space-3xl) var(--wa-space-xl);
color: var(--wa-color-neutral-500);
}
.drawer-form {
display: flex;
flex-direction: column;
gap: var(--wa-space-l);
height: 100%;
}
.drawer-form-content {
flex: 1;
overflow-y: auto;
}
.qr-container {
display: flex;
flex-direction: column;
align-items: center;
padding: var(--wa-space-xl);
background: var(--wa-color-surface-alt);
border-radius: var(--wa-radius-l);
}
.address-display {
display: flex;
align-items: center;
gap: var(--wa-space-s);
padding: var(--wa-space-m);
background: var(--wa-color-surface-alt);
border-radius: var(--wa-radius-m);
font-family: var(--wa-font-mono);
font-size: var(--wa-font-size-s);
word-break: break-all;
}
.swap-token-box {
padding: var(--wa-space-m);
background: var(--wa-color-surface-alt);
border-radius: var(--wa-radius-m);
border: 1px solid var(--wa-color-neutral-200);
}
.swap-arrow {
display: flex;
justify-content: center;
margin: calc(var(--wa-space-s) * -1) 0;
position: relative;
z-index: 1;
}
.swap-arrow wa-icon-button {
background: var(--wa-color-surface);
border: 1px solid var(--wa-color-neutral-200);
border-radius: 50%;
}
.gas-settings {
padding: var(--wa-space-m);
background: var(--wa-color-surface-alt);
border-radius: var(--wa-radius-m);
}
.preview-row {
display: flex;
justify-content: space-between;
padding: var(--wa-space-xs) 0;
font-size: var(--wa-font-size-s);
}
.preview-row .label {
color: var(--wa-color-neutral-500);
}
.stepper {
display: flex;
justify-content: center;
gap: var(--wa-space-m);
margin-bottom: var(--wa-space-xl);
}
.stepper-item {
display: flex;
align-items: center;
gap: var(--wa-space-xs);
}
.stepper-number {
width: 28px;
height: 28px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: var(--wa-font-size-xs);
font-weight: 600;
background: var(--wa-color-neutral-200);
color: var(--wa-color-neutral-600);
transition: all 0.2s;
}
.stepper-item.active .stepper-number {
background: var(--wa-color-primary);
color: white;
}
.stepper-item.completed .stepper-number {
background: var(--wa-color-success);
color: white;
}
.stepper-label {
font-size: var(--wa-font-size-xs);
color: var(--wa-color-neutral-500);
}
.stepper-item.active .stepper-label {
color: var(--wa-color-primary);
font-weight: 500;
}
.stepper-line {
width: 40px;
height: 2px;
background: var(--wa-color-neutral-200);
}
.stepper-line.completed {
background: var(--wa-color-success);
}
.step-content {
display: none;
}
.step-content.active {
display: block;
}
.network-option {
display: flex;
align-items: center;
gap: var(--wa-space-m);
padding: var(--wa-space-m);
border: 2px solid var(--wa-color-neutral-200);
border-radius: var(--wa-radius-m);
cursor: pointer;
transition: all 0.15s;
}
.network-option:hover {
border-color: var(--wa-color-neutral-300);
background: var(--wa-color-surface-alt);
}
.network-option.selected {
border-color: var(--wa-color-primary);
background: var(--wa-color-primary-subtle);
}
.network-option .network-icon {
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.derivation-preview {
padding: var(--wa-space-m);
background: var(--wa-color-surface-alt);
border-radius: var(--wa-radius-m);
font-family: var(--wa-font-mono);
font-size: var(--wa-font-size-xs);
}
.portfolio-chart-card {
grid-column: span 2;
}
@media (max-width: 900px) {
.portfolio-chart-card {
grid-column: span 1;
}
}
.portfolio-chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--wa-space-m);
}
.chart-container {
min-height: 280px;
}
.asset-allocation-container {
display: flex;
align-items: center;
justify-content: center;
padding: var(--wa-space-l);
}
.chart-dialog-content {
min-height: 400px;
}
.chart-header {
display: flex;
align-items: center;
gap: var(--wa-space-m);
margin-bottom: var(--wa-space-l);
}
.chart-timeframe {
margin-left: auto;
}
.chart-stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: var(--wa-space-m);
margin-top: var(--wa-space-l);
padding-top: var(--wa-space-l);
border-top: 1px solid var(--wa-color-neutral-200);
}
.chart-stat {
text-align: center;
}
.chart-stat-label {
font-size: var(--wa-font-size-xs);
color: var(--wa-color-neutral-500);
margin-bottom: var(--wa-space-2xs);
}
.chart-stat-value {
font-size: var(--wa-font-size-m);
font-weight: 600;
}
</style>
</head>
<body>
<wa-page>
<div class="dashboard-layout">
<aside class="sidebar">
<div class="sidebar-header">
<div class="wa-cluster wa-gap-s">
<wa-avatar initials="S" style="--size: 32px; background: var(--wa-color-primary);"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Sonr Wallet</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">sonr1x9f...7k2m</span>
</div>
</div>
</div>
<nav>
<ul class="sidebar-nav">
<li>
<a href="accounts.html" class="active">
<wa-icon name="wallet"></wa-icon>
Accounts
</a>
</li>
<li>
<a href="transactions.html">
<wa-icon name="arrow-right-arrow-left"></wa-icon>
Transactions
</a>
</li>
<li>
<a href="tokens.html">
<wa-icon name="coins"></wa-icon>
Tokens
</a>
</li>
<li>
<a href="nfts.html">
<wa-icon name="image"></wa-icon>
NFTs
</a>
</li>
<li>
<a href="activity.html">
<wa-icon name="chart-line"></wa-icon>
Activity
</a>
</li>
</ul>
</nav>
<wa-divider style="margin: var(--wa-space-l) 0;"></wa-divider>
<ul class="sidebar-nav">
<li>
<a href="connections.html">
<wa-icon name="plug"></wa-icon>
Connections
</a>
</li>
<li>
<a href="device.html">
<wa-icon name="mobile"></wa-icon>
Devices
</a>
</li>
<li>
<a href="service.html">
<wa-icon name="server"></wa-icon>
Services
</a>
</li>
<li>
<a href="settings.html">
<wa-icon name="gear"></wa-icon>
Settings
</a>
</li>
</ul>
</aside>
<main class="main-content">
<header class="page-header">
<div class="wa-flank">
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-xl">Accounts</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">Manage your crypto assets and balances</span>
</div>
<div class="quick-actions">
<wa-button variant="neutral" appearance="outlined" size="small" id="open-receive-drawer">
<wa-icon slot="start" name="arrow-down"></wa-icon>
Receive
</wa-button>
<wa-button variant="neutral" appearance="outlined" size="small" id="open-send-drawer">
<wa-icon slot="start" name="arrow-up"></wa-icon>
Send
</wa-button>
<wa-button variant="brand" size="small" id="open-swap-drawer">
<wa-icon slot="start" name="arrow-right-arrow-left"></wa-icon>
Swap
</wa-button>
</div>
</div>
</header>
<div class="wa-grid stats-grid">
<wa-card class="stat-card">
<div class="wa-flank">
<wa-avatar shape="rounded" style="background: var(--wa-color-primary-subtle);">
<wa-icon slot="icon" name="wallet" style="color: var(--wa-color-primary);"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-3xs">
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">Total Balance</span>
<span class="wa-cluster wa-gap-xs">
<span class="wa-heading-2xl">
<wa-format-number type="currency" currency="USD" value="12847.32" lang="en-US"></wa-format-number>
</span>
<wa-badge variant="success" pill>+2.4%&nbsp;<wa-icon name="arrow-trend-up"></wa-icon></wa-badge>
</span>
</div>
</div>
</wa-card>
<wa-card class="stat-card">
<div class="wa-flank">
<wa-avatar shape="rounded" style="background: var(--wa-color-success-subtle);">
<wa-icon slot="icon" name="chart-line" style="color: var(--wa-color-success);"></wa-icon>
</wa-avatar>
<div class="wa-stack wa-gap-3xs">
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">24h Change</span>
<span class="wa-cluster wa-gap-xs">
<span class="wa-heading-2xl" style="color: var(--wa-color-success);">+$302.18</span>
</span>
</div>
</div>
</wa-card>
<wa-card class="stat-card portfolio-chart-card">
<div class="portfolio-chart-header">
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-m">Portfolio Performance</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">Asset allocation over time</span>
</div>
<wa-radio-group value="1w" orientation="horizontal" id="portfolio-timeframe">
<wa-radio appearance="button" value="1d">1D</wa-radio>
<wa-radio appearance="button" value="1w">1W</wa-radio>
<wa-radio appearance="button" value="1m">1M</wa-radio>
<wa-radio appearance="button" value="1y">1Y</wa-radio>
</wa-radio-group>
</div>
<div id="portfolio-chart-container" class="chart-container"></div>
</wa-card>
</div>
<div class="wa-grid" style="--min-column-size: 400px; gap: var(--wa-space-xl);">
<wa-card>
<div slot="header" class="wa-flank">
<span class="wa-heading-m">Token Balances</span>
<wa-button appearance="plain" size="small">
<wa-icon name="plus"></wa-icon>
Add Token
</wa-button>
</div>
<div class="token-row">
<div class="token-info">
<wa-avatar initials="S" style="--size: 40px; background: linear-gradient(135deg, #17c2ff, #0090ff);"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Sonr</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">SNR</span>
</div>
</div>
<div class="token-balance">
<div class="wa-stack wa-gap-0" style="align-items: flex-end;">
<span class="wa-heading-s">8,432.50</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">$4,216.25</span>
</div>
</div>
<div class="token-actions">
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="Actions"></wa-icon-button>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-up"></wa-icon>Send</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-down"></wa-icon>Receive</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-right-arrow-left"></wa-icon>Swap</wa-dropdown-item>
<wa-divider></wa-divider>
<wa-dropdown-item><wa-icon slot="icon" name="chart-simple"></wa-icon>View Chart</wa-dropdown-item>
</wa-dropdown>
</div>
</div>
<div class="token-row">
<div class="token-info">
<wa-avatar initials="E" style="--size: 40px; background: #627eea;"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Ethereum</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">ETH</span>
</div>
</div>
<div class="token-balance">
<div class="wa-stack wa-gap-0" style="align-items: flex-end;">
<span class="wa-heading-s">2.847</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">$6,682.04</span>
</div>
</div>
<div class="token-actions">
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="Actions"></wa-icon-button>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-up"></wa-icon>Send</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-down"></wa-icon>Receive</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-right-arrow-left"></wa-icon>Swap</wa-dropdown-item>
</wa-dropdown>
</div>
</div>
<div class="token-row">
<div class="token-info">
<wa-avatar initials="U" style="--size: 40px; background: #2775ca;"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">USD Coin</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">USDC</span>
</div>
</div>
<div class="token-balance">
<div class="wa-stack wa-gap-0" style="align-items: flex-end;">
<span class="wa-heading-s">1,250.00</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">$1,250.00</span>
</div>
</div>
<div class="token-actions">
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="Actions"></wa-icon-button>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-up"></wa-icon>Send</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-down"></wa-icon>Receive</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-right-arrow-left"></wa-icon>Swap</wa-dropdown-item>
</wa-dropdown>
</div>
</div>
<div class="token-row">
<div class="token-info">
<wa-avatar initials="A" style="--size: 40px; background: #e84142;"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Avalanche</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">AVAX</span>
</div>
</div>
<div class="token-balance">
<div class="wa-stack wa-gap-0" style="align-items: flex-end;">
<span class="wa-heading-s">24.83</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">$699.03</span>
</div>
</div>
<div class="token-actions">
<wa-dropdown>
<wa-icon-button slot="trigger" name="ellipsis-vertical" label="Actions"></wa-icon-button>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-up"></wa-icon>Send</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-down"></wa-icon>Receive</wa-dropdown-item>
<wa-dropdown-item><wa-icon slot="icon" name="arrow-right-arrow-left"></wa-icon>Swap</wa-dropdown-item>
</wa-dropdown>
</div>
</div>
<div slot="footer">
<a href="tokens.html" class="wa-cluster wa-gap-xs wa-caption-s" style="color: var(--wa-color-primary);">
<span>View all tokens</span>
<wa-icon name="arrow-right"></wa-icon>
</a>
</div>
</wa-card>
<wa-card>
<div slot="header" class="wa-flank">
<span class="wa-heading-m">Recent Transactions</span>
<wa-button appearance="plain" size="small">View All</wa-button>
</div>
<table class="tx-table">
<thead>
<tr>
<th>Type</th>
<th>Asset</th>
<th>Amount</th>
<th>Date</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<span class="tx-type receive">
<wa-icon name="arrow-down"></wa-icon>
Receive
</span>
</td>
<td>ETH</td>
<td>
<div class="wa-stack wa-gap-0">
<span style="color: var(--wa-color-success);">+0.25 ETH</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">$586.25</span>
</div>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span>Today</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">2:34 PM</span>
</div>
</td>
<td>
<wa-copy-button value="0x8f4a2b1c9e3d5f7a0b2c4d6e8f0a1b3c5d7e9f0a" copy-label="Copy hash" success-label="Copied!"></wa-copy-button>
</td>
</tr>
<tr>
<td>
<span class="tx-type send">
<wa-icon name="arrow-up"></wa-icon>
Send
</span>
</td>
<td>SNR</td>
<td>
<div class="wa-stack wa-gap-0">
<span style="color: var(--wa-color-danger);">-500 SNR</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">$250.00</span>
</div>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span>Yesterday</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">11:22 AM</span>
</div>
</td>
<td>
<wa-copy-button value="0x7d3e2a1b8c4f6e0d9a5b7c3e1f8a2d4c6b0e9f7a" copy-label="Copy hash" success-label="Copied!"></wa-copy-button>
</td>
</tr>
<tr>
<td>
<span class="tx-type swap">
<wa-icon name="arrow-right-arrow-left"></wa-icon>
Swap
</span>
</td>
<td>ETH → USDC</td>
<td>
<div class="wa-stack wa-gap-0">
<span>0.5 ETH</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">→ 1,172.50 USDC</span>
</div>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span>Jan 1</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">9:15 AM</span>
</div>
</td>
<td>
<wa-copy-button value="0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b" copy-label="Copy hash" success-label="Copied!"></wa-copy-button>
</td>
</tr>
<tr>
<td>
<span class="tx-type receive">
<wa-icon name="arrow-down"></wa-icon>
Receive
</span>
</td>
<td>AVAX</td>
<td>
<div class="wa-stack wa-gap-0">
<span style="color: var(--wa-color-success);">+10.00 AVAX</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">$281.50</span>
</div>
</td>
<td>
<div class="wa-stack wa-gap-0">
<span>Dec 30</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">4:48 PM</span>
</div>
</td>
<td>
<wa-copy-button value="0x9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e" copy-label="Copy hash" success-label="Copied!"></wa-copy-button>
</td>
</tr>
</tbody>
</table>
<div slot="footer">
<a href="transactions.html" class="wa-cluster wa-gap-xs wa-caption-s" style="color: var(--wa-color-primary);">
<span>View all transactions</span>
<wa-icon name="arrow-right"></wa-icon>
</a>
</div>
</wa-card>
</div>
<wa-card style="margin-top: var(--wa-space-xl);">
<div slot="header" class="wa-flank">
<span class="wa-heading-m">Connected Accounts</span>
<wa-button appearance="plain" size="small" id="open-create-account">
<wa-icon slot="start" name="plus"></wa-icon>
Create
</wa-button>
</div>
<div class="wa-grid" style="--min-column-size: 280px;">
<div class="wa-flank" style="padding: var(--wa-space-s); background: var(--wa-color-surface-alt); border-radius: var(--wa-radius-m);">
<div class="wa-cluster wa-gap-s">
<wa-avatar initials="M" style="--size: 40px; background: var(--wa-color-primary);"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Main Wallet</span>
<span class="address-mono">sonr1x9f...7k2m</span>
</div>
</div>
<wa-badge variant="success" pill>Active</wa-badge>
</div>
<div class="wa-flank" style="padding: var(--wa-space-s); background: var(--wa-color-surface-alt); border-radius: var(--wa-radius-m);">
<div class="wa-cluster wa-gap-s">
<wa-avatar initials="T" style="--size: 40px; background: var(--wa-color-neutral-400);"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Trading</span>
<span class="address-mono">sonr1k4m...9p3q</span>
</div>
</div>
<wa-icon-button name="ellipsis-vertical" label="Options"></wa-icon-button>
</div>
<div class="wa-flank" style="padding: var(--wa-space-s); background: var(--wa-color-surface-alt); border-radius: var(--wa-radius-m);">
<div class="wa-cluster wa-gap-s">
<wa-avatar initials="S" style="--size: 40px; background: var(--wa-color-neutral-400);"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">Savings</span>
<span class="address-mono">sonr1r7t...2w8x</span>
</div>
</div>
<wa-icon-button name="ellipsis-vertical" label="Options"></wa-icon-button>
</div>
</div>
</wa-card>
</main>
</div>
<wa-drawer label="Receive" placement="end" class="drawer-receive" style="--size: 400px;">
<div class="drawer-form">
<div class="drawer-form-content">
<div class="wa-stack wa-gap-l">
<wa-select label="Select Token" value="snr">
<wa-option value="snr">
<wa-avatar slot="prefix" initials="S" style="--size: 24px; background: linear-gradient(135deg, #17c2ff, #0090ff);"></wa-avatar>
SNR - Sonr
</wa-option>
<wa-option value="eth">
<wa-avatar slot="prefix" initials="E" style="--size: 24px; background: #627eea;"></wa-avatar>
ETH - Ethereum
</wa-option>
<wa-option value="usdc">
<wa-avatar slot="prefix" initials="U" style="--size: 24px; background: #2775ca;"></wa-avatar>
USDC - USD Coin
</wa-option>
<wa-option value="avax">
<wa-avatar slot="prefix" initials="A" style="--size: 24px; background: #e84142;"></wa-avatar>
AVAX - Avalanche
</wa-option>
</wa-select>
<div class="qr-container">
<wa-qr-code value="sonr1x9f4h2k8m3n5p7q2r4s6t8v0w3x5y7z9a1b3c5d7k2m" size="180" radius="0.5"></wa-qr-code>
<span class="wa-caption-s" style="margin-top: var(--wa-space-m); color: var(--wa-color-neutral-500);">Scan to receive tokens</span>
</div>
<div class="wa-stack wa-gap-xs">
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">Your Wallet Address</span>
<div class="address-display">
<span style="flex: 1;">sonr1x9f4h2k8m3n5p7q2r4s6t8v0w3x5y7z9a1b3c5d7k2m</span>
<wa-copy-button value="sonr1x9f4h2k8m3n5p7q2r4s6t8v0w3x5y7z9a1b3c5d7k2m"></wa-copy-button>
</div>
</div>
<wa-callout variant="neutral">
<wa-icon slot="icon" name="circle-info"></wa-icon>
Only send <strong>SNR</strong> tokens to this address. Sending other assets may result in permanent loss.
</wa-callout>
</div>
</div>
<div class="wa-cluster wa-gap-s" style="justify-content: flex-end;">
<wa-button variant="neutral" appearance="outlined" data-drawer="close">Close</wa-button>
<wa-button variant="brand">
<wa-icon slot="start" name="share-nodes"></wa-icon>
Share Address
</wa-button>
</div>
</div>
</wa-drawer>
<wa-drawer label="Send" placement="end" class="drawer-send" style="--size: 420px;">
<div class="drawer-form">
<div class="drawer-form-content">
<div class="wa-stack wa-gap-l">
<wa-select label="From Token" value="snr" id="send-token-select">
<wa-option value="snr">
<wa-avatar slot="prefix" initials="S" style="--size: 24px; background: linear-gradient(135deg, #17c2ff, #0090ff);"></wa-avatar>
SNR - 8,432.50 available
</wa-option>
<wa-option value="eth">
<wa-avatar slot="prefix" initials="E" style="--size: 24px; background: #627eea;"></wa-avatar>
ETH - 2.847 available
</wa-option>
<wa-option value="usdc">
<wa-avatar slot="prefix" initials="U" style="--size: 24px; background: #2775ca;"></wa-avatar>
USDC - 1,250.00 available
</wa-option>
<wa-option value="avax">
<wa-avatar slot="prefix" initials="A" style="--size: 24px; background: #e84142;"></wa-avatar>
AVAX - 24.83 available
</wa-option>
</wa-select>
<wa-input label="Recipient Address" placeholder="sonr1... or ENS name" clearable>
<wa-icon slot="prefix" name="wallet"></wa-icon>
<wa-tooltip slot="suffix" content="Paste from clipboard">
<wa-icon-button name="paste" label="Paste"></wa-icon-button>
</wa-tooltip>
</wa-input>
<div class="wa-stack wa-gap-xs">
<wa-input label="Amount" type="number" placeholder="0.00" id="send-amount">
<span slot="suffix" style="color: var(--wa-color-neutral-500);">SNR</span>
</wa-input>
<div class="wa-flank">
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">≈ $0.00 USD</span>
<wa-button size="small" appearance="plain" style="font-size: var(--wa-font-size-xs);">MAX</wa-button>
</div>
</div>
<wa-textarea label="Memo (Optional)" placeholder="Add a note to this transaction" rows="2"></wa-textarea>
<wa-details summary="Gas Settings">
<div class="gas-settings">
<wa-radio-group label="Transaction Speed" value="standard" orientation="horizontal">
<wa-radio appearance="button" value="slow">Slow</wa-radio>
<wa-radio appearance="button" value="standard">Standard</wa-radio>
<wa-radio appearance="button" value="fast">Fast</wa-radio>
</wa-radio-group>
<div class="preview-row" style="margin-top: var(--wa-space-m);">
<span class="label">Estimated Gas</span>
<span>~0.001 SNR ($0.05)</span>
</div>
</div>
</wa-details>
<wa-divider></wa-divider>
<div class="wa-stack wa-gap-xs">
<div class="preview-row">
<span class="label">Amount</span>
<span>0.00 SNR</span>
</div>
<div class="preview-row">
<span class="label">Network Fee</span>
<span>~0.001 SNR</span>
</div>
<div class="preview-row">
<span class="label" style="font-weight: 500;">Total</span>
<span style="font-weight: 500;">0.001 SNR</span>
</div>
</div>
</div>
</div>
<div class="wa-cluster wa-gap-s" style="justify-content: flex-end;">
<wa-button variant="neutral" appearance="outlined" data-drawer="close">Cancel</wa-button>
<wa-button variant="brand" id="send-confirm-btn">
<wa-icon slot="start" name="paper-plane"></wa-icon>
Review Send
</wa-button>
</div>
</div>
</wa-drawer>
<wa-drawer label="Swap Tokens" placement="end" class="drawer-swap" style="--size: 440px;">
<div class="drawer-form">
<div class="drawer-form-content">
<div class="wa-stack wa-gap-m">
<div class="swap-token-box">
<div class="wa-flank" style="margin-bottom: var(--wa-space-s);">
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">You Pay</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">Balance: 2.847 ETH</span>
</div>
<div class="wa-flank wa-gap-m">
<wa-input type="number" placeholder="0.00" style="flex: 1; --wa-input-border-color: transparent; --wa-input-background-color: transparent;" id="swap-from-amount"></wa-input>
<wa-dropdown>
<wa-button slot="trigger" appearance="outlined" size="small" with-caret>
<wa-avatar slot="prefix" initials="E" style="--size: 20px; background: #627eea;"></wa-avatar>
ETH
</wa-button>
<wa-dropdown-item>
<wa-avatar slot="icon" initials="S" style="--size: 20px; background: linear-gradient(135deg, #17c2ff, #0090ff);"></wa-avatar>
SNR
</wa-dropdown-item>
<wa-dropdown-item>
<wa-avatar slot="icon" initials="U" style="--size: 20px; background: #2775ca;"></wa-avatar>
USDC
</wa-dropdown-item>
<wa-dropdown-item>
<wa-avatar slot="icon" initials="A" style="--size: 20px; background: #e84142;"></wa-avatar>
AVAX
</wa-dropdown-item>
</wa-dropdown>
</div>
<div class="wa-flank" style="margin-top: var(--wa-space-xs);">
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">≈ $0.00</span>
<div class="wa-cluster wa-gap-xs">
<wa-button size="small" appearance="plain" style="font-size: var(--wa-font-size-xs);">25%</wa-button>
<wa-button size="small" appearance="plain" style="font-size: var(--wa-font-size-xs);">50%</wa-button>
<wa-button size="small" appearance="plain" style="font-size: var(--wa-font-size-xs);">MAX</wa-button>
</div>
</div>
</div>
<div class="swap-arrow">
<wa-icon-button name="arrow-down" label="Swap direction" id="swap-direction-btn"></wa-icon-button>
</div>
<div class="swap-token-box">
<div class="wa-flank" style="margin-bottom: var(--wa-space-s);">
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">You Receive</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">Balance: 1,250.00 USDC</span>
</div>
<div class="wa-flank wa-gap-m">
<wa-input type="number" placeholder="0.00" style="flex: 1; --wa-input-border-color: transparent; --wa-input-background-color: transparent;" id="swap-to-amount" readonly></wa-input>
<wa-dropdown>
<wa-button slot="trigger" appearance="outlined" size="small" with-caret>
<wa-avatar slot="prefix" initials="U" style="--size: 20px; background: #2775ca;"></wa-avatar>
USDC
</wa-button>
<wa-dropdown-item>
<wa-avatar slot="icon" initials="S" style="--size: 20px; background: linear-gradient(135deg, #17c2ff, #0090ff);"></wa-avatar>
SNR
</wa-dropdown-item>
<wa-dropdown-item>
<wa-avatar slot="icon" initials="E" style="--size: 20px; background: #627eea;"></wa-avatar>
ETH
</wa-dropdown-item>
<wa-dropdown-item>
<wa-avatar slot="icon" initials="A" style="--size: 20px; background: #e84142;"></wa-avatar>
AVAX
</wa-dropdown-item>
</wa-dropdown>
</div>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500); margin-top: var(--wa-space-xs); display: block;">≈ $0.00</span>
</div>
<wa-details summary="Swap Settings">
<div class="wa-stack wa-gap-m" style="padding-top: var(--wa-space-s);">
<div class="wa-stack wa-gap-xs">
<span class="wa-caption-s">Slippage Tolerance</span>
<wa-radio-group value="0.5" orientation="horizontal">
<wa-radio appearance="button" value="0.1">0.1%</wa-radio>
<wa-radio appearance="button" value="0.5">0.5%</wa-radio>
<wa-radio appearance="button" value="1">1%</wa-radio>
<wa-radio appearance="button" value="custom">Custom</wa-radio>
</wa-radio-group>
</div>
<wa-input label="Transaction Deadline" type="number" value="30" size="small">
<span slot="suffix">minutes</span>
</wa-input>
</div>
</wa-details>
<wa-card style="background: var(--wa-color-surface-alt);">
<div class="wa-stack wa-gap-xs">
<div class="preview-row">
<span class="label">Rate</span>
<span>1 ETH = 2,345.00 USDC</span>
</div>
<div class="preview-row">
<span class="label">Price Impact</span>
<span style="color: var(--wa-color-success);">&lt; 0.01%</span>
</div>
<div class="preview-row">
<span class="label">Minimum Received</span>
<span>0.00 USDC</span>
</div>
<div class="preview-row">
<span class="label">Network Fee</span>
<span>~$2.50</span>
</div>
<div class="preview-row">
<span class="label">Route</span>
<span class="wa-cluster wa-gap-2xs">
ETH
<wa-icon name="arrow-right" style="font-size: 10px;"></wa-icon>
USDC
</span>
</div>
</div>
</wa-card>
<wa-callout variant="warning" style="--padding: var(--wa-space-s);">
<wa-icon slot="icon" name="triangle-alert"></wa-icon>
<span class="wa-caption-s">Price updates in real-time. Review carefully before confirming.</span>
</wa-callout>
</div>
</div>
<div class="wa-cluster wa-gap-s" style="justify-content: flex-end;">
<wa-button variant="neutral" appearance="outlined" data-drawer="close">Cancel</wa-button>
<wa-button variant="brand" id="swap-confirm-btn">
<wa-icon slot="start" name="arrow-right-arrow-left"></wa-icon>
Review Swap
</wa-button>
</div>
</div>
</wa-drawer>
<wa-dialog label="Create New Account" id="create-account-dialog" style="--width: 480px;">
<div class="stepper">
<div class="stepper-item active" data-step="1">
<div class="stepper-number">1</div>
<span class="stepper-label">Network</span>
</div>
<div class="stepper-line"></div>
<div class="stepper-item" data-step="2">
<div class="stepper-number">2</div>
<span class="stepper-label">Details</span>
</div>
<div class="stepper-line"></div>
<div class="stepper-item" data-step="3">
<div class="stepper-number">3</div>
<span class="stepper-label">Confirm</span>
</div>
</div>
<div class="step-content active" data-step="1">
<div class="wa-stack wa-gap-m">
<p class="wa-caption-s" style="color: var(--wa-color-neutral-500); margin: 0;">Select the blockchain network for your new account.</p>
<div class="wa-stack wa-gap-s" id="network-options">
<div class="network-option selected" data-network="sonr">
<div class="network-icon" style="background: linear-gradient(135deg, #17c2ff, #0090ff);">
<wa-icon name="cube" style="color: white;"></wa-icon>
</div>
<div class="wa-stack wa-gap-0" style="flex: 1;">
<span class="wa-heading-s">Sonr Network</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">Native Sonr blockchain accounts</span>
</div>
<wa-icon name="check" style="color: var(--wa-color-primary);"></wa-icon>
</div>
<div class="network-option" data-network="ethereum">
<div class="network-icon" style="background: #627eea;">
<wa-icon name="diamond" style="color: white;"></wa-icon>
</div>
<div class="wa-stack wa-gap-0" style="flex: 1;">
<span class="wa-heading-s">Ethereum</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">EVM-compatible addresses</span>
</div>
</div>
<div class="network-option" data-network="cosmos">
<div class="network-icon" style="background: #2b6cb0;">
<wa-icon name="atom" style="color: white;"></wa-icon>
</div>
<div class="wa-stack wa-gap-0" style="flex: 1;">
<span class="wa-heading-s">Cosmos Hub</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">IBC-enabled accounts</span>
</div>
</div>
<div class="network-option" data-network="bitcoin">
<div class="network-icon" style="background: #f7931a;">
<wa-icon name="bitcoin-sign" style="color: white;"></wa-icon>
</div>
<div class="wa-stack wa-gap-0" style="flex: 1;">
<span class="wa-heading-s">Bitcoin</span>
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">Native SegWit addresses</span>
</div>
</div>
</div>
</div>
</div>
<div class="step-content" data-step="2">
<div class="wa-stack wa-gap-l">
<p class="wa-caption-s" style="color: var(--wa-color-neutral-500); margin: 0;">Enter a label to identify this account.</p>
<wa-input label="Account Label" placeholder="e.g., Trading, Savings, DeFi" id="account-label-input" autofocus>
<wa-icon slot="prefix" name="tag"></wa-icon>
</wa-input>
<wa-select label="Derivation Path" value="default" id="derivation-path-select">
<wa-option value="default">Default (Recommended)</wa-option>
<wa-option value="legacy">Legacy</wa-option>
<wa-option value="custom">Custom Path</wa-option>
</wa-select>
<wa-callout variant="neutral">
<wa-icon slot="icon" name="circle-info"></wa-icon>
<div class="wa-stack wa-gap-2xs">
<span class="wa-heading-xs">Derivation Path</span>
<span class="wa-caption-s">This determines how your account keys are generated from your master seed. Use default unless you have specific requirements.</span>
</div>
</wa-callout>
</div>
</div>
<div class="step-content" data-step="3">
<div class="wa-stack wa-gap-l">
<p class="wa-caption-s" style="color: var(--wa-color-neutral-500); margin: 0;">Review and confirm your new account details.</p>
<wa-card>
<div class="wa-stack wa-gap-m">
<div class="wa-flank">
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">Network</span>
<div class="wa-cluster wa-gap-xs">
<wa-avatar initials="S" style="--size: 20px; background: linear-gradient(135deg, #17c2ff, #0090ff);"></wa-avatar>
<span class="wa-heading-xs" id="confirm-network">Sonr Network</span>
</div>
</div>
<wa-divider></wa-divider>
<div class="wa-flank">
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">Label</span>
<span class="wa-heading-xs" id="confirm-label">New Account</span>
</div>
<wa-divider></wa-divider>
<div class="wa-flank">
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">Path</span>
<span class="wa-heading-xs" id="confirm-path">m/44'/118'/0'/0/3</span>
</div>
<wa-divider></wa-divider>
<div class="wa-stack wa-gap-xs">
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">Preview Address</span>
<div class="derivation-preview" id="confirm-address">
sonr1newaccount7k3m5n8p2q4r6s9t1v3w5x7y9z...
</div>
</div>
</div>
</wa-card>
<wa-callout variant="warning">
<wa-icon slot="icon" name="shield-check"></wa-icon>
<span class="wa-caption-s">This will derive a new account from your existing wallet. Your passkey will be required to confirm.</span>
</wa-callout>
</div>
</div>
<div slot="footer" class="wa-flank" style="width: 100%;">
<wa-button variant="neutral" appearance="outlined" id="step-back-btn" style="visibility: hidden;">
<wa-icon slot="start" name="arrow-left"></wa-icon>
Back
</wa-button>
<div style="flex: 1;"></div>
<wa-button variant="neutral" appearance="outlined" data-dialog="close">Cancel</wa-button>
<wa-button variant="brand" id="step-next-btn">
Next
<wa-icon slot="end" name="arrow-right"></wa-icon>
</wa-button>
</div>
</wa-dialog>
<wa-dialog label="Price Chart" id="chart-dialog" style="--width: 800px;">
<div class="chart-dialog-content">
<div class="chart-header">
<wa-avatar id="chart-token-avatar" initials="E" style="--size: 48px; background: #627eea;"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-l" id="chart-token-name">Ethereum</span>
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);" id="chart-token-symbol">ETH</span>
</div>
<div class="chart-timeframe">
<wa-radio-group value="1d" orientation="horizontal" id="chart-timeframe-select">
<wa-radio appearance="button" value="1h">1H</wa-radio>
<wa-radio appearance="button" value="1d">1D</wa-radio>
<wa-radio appearance="button" value="1w">1W</wa-radio>
<wa-radio appearance="button" value="1m">1M</wa-radio>
</wa-radio-group>
</div>
</div>
<div id="candle-chart-container" style="width: 100%;"></div>
<div class="chart-stats">
<div class="chart-stat">
<div class="chart-stat-label">24h High</div>
<div class="chart-stat-value" id="chart-stat-high">$2,412.50</div>
</div>
<div class="chart-stat">
<div class="chart-stat-label">24h Low</div>
<div class="chart-stat-value" id="chart-stat-low">$2,298.20</div>
</div>
<div class="chart-stat">
<div class="chart-stat-label">24h Volume</div>
<div class="chart-stat-value" id="chart-stat-volume">$12.4B</div>
</div>
<div class="chart-stat">
<div class="chart-stat-label">Market Cap</div>
<div class="chart-stat-value" id="chart-stat-mcap">$282.1B</div>
</div>
</div>
</div>
<div slot="footer" class="wa-cluster wa-gap-s" style="justify-content: flex-end;">
<wa-button variant="neutral" appearance="outlined" data-dialog="close">Close</wa-button>
<wa-button variant="brand">
<wa-icon slot="start" name="arrow-right-arrow-left"></wa-icon>
Trade
</wa-button>
</div>
</wa-dialog>
</wa-page>
<script>
const receiveDrawer = document.querySelector('.drawer-receive');
const sendDrawer = document.querySelector('.drawer-send');
const swapDrawer = document.querySelector('.drawer-swap');
document.getElementById('open-receive-drawer').addEventListener('click', () => {
receiveDrawer.open = true;
});
document.getElementById('open-send-drawer').addEventListener('click', () => {
sendDrawer.open = true;
});
document.getElementById('open-swap-drawer').addEventListener('click', () => {
swapDrawer.open = true;
});
document.querySelectorAll('wa-dropdown-item').forEach(item => {
item.addEventListener('click', (e) => {
const text = item.textContent.trim();
if (text === 'Send') {
sendDrawer.open = true;
} else if (text === 'Receive') {
receiveDrawer.open = true;
} else if (text === 'Swap') {
swapDrawer.open = true;
}
});
});
document.getElementById('swap-direction-btn').addEventListener('click', function() {
this.style.transform = this.style.transform === 'rotate(180deg)' ? '' : 'rotate(180deg)';
});
document.querySelectorAll('.sidebar-nav a').forEach(link => {
link.addEventListener('click', function(e) {
if (this.getAttribute('href') === '#') {
e.preventDefault();
}
document.querySelectorAll('.sidebar-nav a').forEach(l => l.classList.remove('active'));
this.classList.add('active');
});
});
const createAccountDialog = document.getElementById('create-account-dialog');
const stepNextBtn = document.getElementById('step-next-btn');
const stepBackBtn = document.getElementById('step-back-btn');
let currentStep = 1;
let selectedNetwork = 'sonr';
document.getElementById('open-create-account').addEventListener('click', () => {
currentStep = 1;
updateStepper();
createAccountDialog.open = true;
});
document.querySelectorAll('.network-option').forEach(option => {
option.addEventListener('click', () => {
document.querySelectorAll('.network-option').forEach(o => {
o.classList.remove('selected');
o.querySelector('wa-icon[name="check"]')?.remove();
});
option.classList.add('selected');
selectedNetwork = option.dataset.network;
const checkIcon = document.createElement('wa-icon');
checkIcon.setAttribute('name', 'check');
checkIcon.style.color = 'var(--wa-color-primary)';
option.appendChild(checkIcon);
});
});
stepNextBtn.addEventListener('click', () => {
if (currentStep < 3) {
currentStep++;
updateStepper();
} else {
createAccount();
}
});
stepBackBtn.addEventListener('click', () => {
if (currentStep > 1) {
currentStep--;
updateStepper();
}
});
function updateStepper() {
document.querySelectorAll('.stepper-item').forEach(item => {
const step = parseInt(item.dataset.step);
item.classList.remove('active', 'completed');
if (step === currentStep) {
item.classList.add('active');
} else if (step < currentStep) {
item.classList.add('completed');
}
});
document.querySelectorAll('.stepper-line').forEach((line, index) => {
line.classList.toggle('completed', index < currentStep - 1);
});
document.querySelectorAll('.step-content').forEach(content => {
content.classList.toggle('active', parseInt(content.dataset.step) === currentStep);
});
stepBackBtn.style.visibility = currentStep > 1 ? 'visible' : 'hidden';
if (currentStep === 3) {
stepNextBtn.innerHTML = '<wa-icon slot="start" name="plus"></wa-icon>Create Account';
updateConfirmation();
} else {
stepNextBtn.innerHTML = 'Next<wa-icon slot="end" name="arrow-right"></wa-icon>';
}
}
function updateConfirmation() {
const networkNames = {
sonr: 'Sonr Network',
ethereum: 'Ethereum',
cosmos: 'Cosmos Hub',
bitcoin: 'Bitcoin'
};
const networkPrefixes = {
sonr: 'sonr1',
ethereum: '0x',
cosmos: 'cosmos1',
bitcoin: 'bc1q'
};
const paths = {
sonr: "m/44'/118'/0'/0/3",
ethereum: "m/44'/60'/0'/0/3",
cosmos: "m/44'/118'/0'/0/3",
bitcoin: "m/84'/0'/0'/0/3"
};
document.getElementById('confirm-network').textContent = networkNames[selectedNetwork];
document.getElementById('confirm-label').textContent = document.getElementById('account-label-input').value || 'New Account';
document.getElementById('confirm-path').textContent = paths[selectedNetwork];
document.getElementById('confirm-address').textContent = networkPrefixes[selectedNetwork] + 'newaccount7k3m5n8p2q4r6s9t1v3w5x7y9z...';
}
async function createAccount() {
stepNextBtn.loading = true;
stepNextBtn.disabled = true;
await new Promise(resolve => setTimeout(resolve, 1500));
createAccountDialog.open = false;
stepNextBtn.loading = false;
stepNextBtn.disabled = false;
const accountLabel = document.getElementById('account-label-input').value || 'New Account';
const accountsGrid = document.querySelector('.wa-card:last-of-type .wa-grid');
const newAccount = document.createElement('div');
newAccount.className = 'wa-flank';
newAccount.style = 'padding: var(--wa-space-s); background: var(--wa-color-surface-alt); border-radius: var(--wa-radius-m);';
newAccount.innerHTML = `
<div class="wa-cluster wa-gap-s">
<wa-avatar initials="${accountLabel.charAt(0).toUpperCase()}" style="--size: 40px; background: var(--wa-color-primary);"></wa-avatar>
<div class="wa-stack wa-gap-0">
<span class="wa-heading-s">${accountLabel}</span>
<span class="address-mono">sonr1new...xyz9</span>
</div>
</div>
<wa-badge variant="neutral" pill>New</wa-badge>
`;
accountsGrid.appendChild(newAccount);
document.getElementById('account-label-input').value = '';
currentStep = 1;
updateStepper();
}
const chartDialog = document.getElementById('chart-dialog');
let candleChart = null;
let portfolioChart = null;
const portfolioData = [
{ date: "2025-01-25", industry: "ETH", unemployed: 3200 },
{ date: "2025-01-25", industry: "SNR", unemployed: 2100 },
{ date: "2025-01-25", industry: "USDC", unemployed: 1200 },
{ date: "2025-01-25", industry: "AVAX", unemployed: 500 },
{ date: "2025-01-26", industry: "ETH", unemployed: 3350 },
{ date: "2025-01-26", industry: "SNR", unemployed: 2200 },
{ date: "2025-01-26", industry: "USDC", unemployed: 1200 },
{ date: "2025-01-26", industry: "AVAX", unemployed: 520 },
{ date: "2025-01-27", industry: "ETH", unemployed: 3500 },
{ date: "2025-01-27", industry: "SNR", unemployed: 2350 },
{ date: "2025-01-27", industry: "USDC", unemployed: 1200 },
{ date: "2025-01-27", industry: "AVAX", unemployed: 480 },
{ date: "2025-01-28", industry: "ETH", unemployed: 3280 },
{ date: "2025-01-28", industry: "SNR", unemployed: 2400 },
{ date: "2025-01-28", industry: "USDC", unemployed: 1200 },
{ date: "2025-01-28", industry: "AVAX", unemployed: 510 },
{ date: "2025-01-29", industry: "ETH", unemployed: 3450 },
{ date: "2025-01-29", industry: "SNR", unemployed: 2550 },
{ date: "2025-01-29", industry: "USDC", unemployed: 1250 },
{ date: "2025-01-29", industry: "AVAX", unemployed: 530 },
{ date: "2025-01-30", industry: "ETH", unemployed: 3600 },
{ date: "2025-01-30", industry: "SNR", unemployed: 2680 },
{ date: "2025-01-30", industry: "USDC", unemployed: 1250 },
{ date: "2025-01-30", industry: "AVAX", unemployed: 550 },
{ date: "2025-01-31", industry: "ETH", unemployed: 3750 },
{ date: "2025-01-31", industry: "SNR", unemployed: 2800 },
{ date: "2025-01-31", industry: "USDC", unemployed: 1250 },
{ date: "2025-01-31", industry: "AVAX", unemployed: 580 },
{ date: "2025-02-01", industry: "ETH", unemployed: 3680 },
{ date: "2025-02-01", industry: "SNR", unemployed: 2900 },
{ date: "2025-02-01", industry: "USDC", unemployed: 1250 },
{ date: "2025-02-01", industry: "AVAX", unemployed: 600 }
];
const sampleCandleData = [
{ open: 119.31, close: 120.41, high: 120.69, low: 119.22, date: "2025-01-30T16:50:00" },
{ open: 120.37, close: 119.77, high: 120.37, low: 119.47, date: "2025-01-30T17:00:00" },
{ open: 119.78, close: 119.32, high: 120.03, low: 119.26, date: "2025-01-30T17:10:00" },
{ open: 119.33, close: 119.11, high: 119.56, low: 118.94, date: "2025-01-30T17:20:00" },
{ open: 119.11, close: 119.41, high: 119.60, low: 118.93, date: "2025-01-30T17:30:00" },
{ open: 119.39, close: 119.63, high: 119.82, low: 119.33, date: "2025-01-30T17:40:00" },
{ open: 119.62, close: 119.82, high: 120.01, low: 119.62, date: "2025-01-30T17:50:00" },
{ open: 119.82, close: 119.83, high: 119.92, low: 119.17, date: "2025-01-30T18:00:00" },
{ open: 119.82, close: 119.58, high: 119.94, low: 119.50, date: "2025-01-30T18:10:00" },
{ open: 119.59, close: 119.29, high: 119.67, low: 119.08, date: "2025-01-30T18:20:00" },
{ open: 119.30, close: 119.42, high: 119.60, low: 119.20, date: "2025-01-30T18:30:00" },
{ open: 119.42, close: 119.51, high: 119.61, low: 119.32, date: "2025-01-30T18:40:00" },
{ open: 119.51, close: 119.93, high: 120.03, low: 119.37, date: "2025-01-30T18:50:00" },
{ open: 119.95, close: 120.72, high: 120.76, low: 119.82, date: "2025-01-30T19:00:00" },
{ open: 120.71, close: 121.02, high: 121.17, low: 120.69, date: "2025-01-30T19:10:00" },
{ open: 121.03, close: 121.27, high: 121.37, low: 120.82, date: "2025-01-30T19:20:00" },
{ open: 121.27, close: 121.41, high: 121.44, low: 120.81, date: "2025-01-30T19:30:00" },
{ open: 121.43, close: 122.06, high: 122.15, low: 121.17, date: "2025-01-30T19:40:00" },
{ open: 122.06, close: 122.08, high: 122.29, low: 121.80, date: "2025-01-30T19:50:00" },
{ open: 122.09, close: 122.26, high: 122.61, low: 121.71, date: "2025-01-30T20:00:00" },
{ open: 122.25, close: 122.77, high: 122.90, low: 122.19, date: "2025-01-30T20:10:00" },
{ open: 122.77, close: 123.21, high: 123.26, low: 122.70, date: "2025-01-30T20:20:00" },
{ open: 123.22, close: 122.04, high: 123.39, low: 122.04, date: "2025-01-30T20:30:00" },
{ open: 122.06, close: 122.96, high: 123.06, low: 121.76, date: "2025-01-30T20:40:00" },
{ open: 122.62, close: 124.44, high: 124.64, low: 122.54, date: "2025-01-30T20:50:00" },
{ open: 123.50, close: 123.65, high: 124.51, low: 123.04, date: "2025-01-31T14:30:00" },
{ open: 123.70, close: 123.46, high: 124.73, low: 123.37, date: "2025-01-31T14:40:00" },
{ open: 123.54, close: 124.77, high: 124.94, low: 123.43, date: "2025-01-31T14:50:00" },
{ open: 124.87, close: 125.19, high: 126.41, low: 124.85, date: "2025-01-31T15:00:00" },
{ open: 125.17, close: 125.50, high: 125.94, low: 124.86, date: "2025-01-31T15:10:00" }
];
const tokenData = {
ETH: { name: 'Ethereum', color: '#627eea', high: '$2,412.50', low: '$2,298.20', volume: '$12.4B', mcap: '$282.1B' },
SNR: { name: 'Sonr', color: 'linear-gradient(135deg, #17c2ff, #0090ff)', high: '$0.52', low: '$0.47', volume: '$1.2M', mcap: '$50M' },
USDC: { name: 'USD Coin', color: '#2775ca', high: '$1.00', low: '$1.00', volume: '$4.2B', mcap: '$42B' },
AVAX: { name: 'Avalanche', color: '#e84142', high: '$29.50', low: '$27.20', volume: '$892M', mcap: '$10.8B' }
};
function openChartDialog(symbol) {
const token = tokenData[symbol] || tokenData.ETH;
document.getElementById('chart-token-name').textContent = token.name;
document.getElementById('chart-token-symbol').textContent = symbol;
document.getElementById('chart-token-avatar').style.background = token.color;
document.getElementById('chart-token-avatar').setAttribute('initials', symbol.charAt(0));
document.getElementById('chart-stat-high').textContent = token.high;
document.getElementById('chart-stat-low').textContent = token.low;
document.getElementById('chart-stat-volume').textContent = token.volume;
document.getElementById('chart-stat-mcap').textContent = token.mcap;
chartDialog.open = true;
setTimeout(() => {
const container = document.getElementById('candle-chart-container');
if (candleChart) {
candleChart.setData(sampleCandleData);
} else {
candleChart = new CandleChart(container, { data: sampleCandleData });
}
}, 100);
}
document.querySelectorAll('wa-dropdown-item').forEach(item => {
if (item.textContent.includes('View Chart')) {
item.addEventListener('click', function() {
const row = this.closest('.token-row');
if (row) {
const symbol = row.querySelector('.wa-caption-xs').textContent;
openChartDialog(symbol);
}
});
}
});
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
const container = document.getElementById('portfolio-chart-container');
if (container && typeof StackedAreaChart !== 'undefined') {
portfolioChart = new StackedAreaChart(container, {
data: portfolioData,
height: 240,
colors: [
{ from: '#93c5fd', to: '#3b82f6', bg: '#627eea' },
{ from: '#bae6fd', to: '#38bdf8', bg: '#17c2ff' },
{ from: '#c4b5fd', to: '#a855f7', bg: '#2775ca' },
{ from: '#fed7aa', to: '#fb923c', bg: '#e84142' }
]
});
}
}, 200);
});
</script>
</body>
</html>