1048 lines
33 KiB
HTML
1048 lines
33 KiB
HTML
|
|
<!DOCTYPE html>
|
||
|
|
<!--
|
||
|
|
================================================================================
|
||
|
|
TEMPL MIGRATION GUIDE: asset.html → views/asset.templ
|
||
|
|
================================================================================
|
||
|
|
|
||
|
|
PAGE OVERVIEW:
|
||
|
|
- Asset detail page showing comprehensive information about a single crypto asset
|
||
|
|
- Hero section: Asset logo, name, symbol, current price, 24h change, action buttons
|
||
|
|
- Key stats: Market Cap, Volume 24h, Circulating Supply, All-Time High
|
||
|
|
- Price chart: Interactive area chart with timeframe selector (1D, 1W, 1M, 1Y, ALL)
|
||
|
|
- About section: Asset description, links to official resources
|
||
|
|
- Recent news: Table of latest news articles related to the asset
|
||
|
|
- Similar to Coinbase/CoinGecko asset detail pages
|
||
|
|
|
||
|
|
MAIN TEMPL COMPONENT:
|
||
|
|
templ AssetPage(asset AssetData) {
|
||
|
|
@layouts.DashboardLayout("tokens") {
|
||
|
|
@AssetHero(asset.Info, asset.Price)
|
||
|
|
@AssetStatsGrid(asset.Stats)
|
||
|
|
@PriceChartCard(asset.PriceHistory)
|
||
|
|
<div class="wa-grid">
|
||
|
|
@AboutCard(asset.About)
|
||
|
|
@NewsCard(asset.News)
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
HTMX INTEGRATION:
|
||
|
|
- Timeframe selection: hx-get="/api/asset/{symbol}/chart?timeframe=1w" hx-target="#price-chart"
|
||
|
|
- Buy/Sell/Swap buttons: hx-get="/drawers/swap?token={symbol}" hx-target="#drawer-container"
|
||
|
|
- News pagination: hx-get="/api/asset/{symbol}/news?page=2" hx-target="#news-tbody" hx-swap="beforeend"
|
||
|
|
- Price refresh: hx-get="/api/asset/{symbol}/price" hx-trigger="every 30s" hx-target="#price-display"
|
||
|
|
- Watchlist toggle: hx-post="/api/watchlist/toggle" hx-vals='{"symbol":"ETH"}'
|
||
|
|
|
||
|
|
SUB-COMPONENTS TO EXTRACT:
|
||
|
|
- AssetHero(info AssetInfo, price PriceData)
|
||
|
|
- AssetLogo(symbol string, color string, size string)
|
||
|
|
- PriceDisplay(price float64, change24h float64, changePercent float64)
|
||
|
|
- AssetStatsGrid(stats AssetStats)
|
||
|
|
- StatItem(label string, value string, tooltip string)
|
||
|
|
- PriceChartCard(history []PricePoint, timeframe string)
|
||
|
|
- TimeframeSelector(selected string)
|
||
|
|
- AboutCard(about AboutData)
|
||
|
|
- ResourceLinks(links []Link)
|
||
|
|
- NewsCard(articles []NewsArticle)
|
||
|
|
- NewsRow(article NewsArticle)
|
||
|
|
|
||
|
|
STATE/PROPS:
|
||
|
|
type AssetData struct {
|
||
|
|
Info AssetInfo
|
||
|
|
Price PriceData
|
||
|
|
Stats AssetStats
|
||
|
|
PriceHistory []PricePoint
|
||
|
|
About AboutData
|
||
|
|
News []NewsArticle
|
||
|
|
}
|
||
|
|
|
||
|
|
type AssetInfo struct {
|
||
|
|
Symbol string
|
||
|
|
Name string
|
||
|
|
Color string
|
||
|
|
Network string
|
||
|
|
ContractAddr string
|
||
|
|
Rank int
|
||
|
|
}
|
||
|
|
|
||
|
|
type PriceData struct {
|
||
|
|
Current float64
|
||
|
|
Change24h float64
|
||
|
|
ChangePercent float64
|
||
|
|
High24h float64
|
||
|
|
Low24h float64
|
||
|
|
}
|
||
|
|
|
||
|
|
type AssetStats struct {
|
||
|
|
MarketCap float64
|
||
|
|
MarketCapRank int
|
||
|
|
Volume24h float64
|
||
|
|
CirculatingSupply float64
|
||
|
|
TotalSupply float64
|
||
|
|
MaxSupply float64
|
||
|
|
AllTimeHigh float64
|
||
|
|
AllTimeHighDate time.Time
|
||
|
|
AllTimeLow float64
|
||
|
|
AllTimeLowDate time.Time
|
||
|
|
}
|
||
|
|
|
||
|
|
type PricePoint struct {
|
||
|
|
Date time.Time
|
||
|
|
Value float64
|
||
|
|
}
|
||
|
|
|
||
|
|
type AboutData struct {
|
||
|
|
Description string
|
||
|
|
Website string
|
||
|
|
Whitepaper string
|
||
|
|
Explorer string
|
||
|
|
Twitter string
|
||
|
|
Discord string
|
||
|
|
Github string
|
||
|
|
}
|
||
|
|
|
||
|
|
type NewsArticle struct {
|
||
|
|
Title string
|
||
|
|
Source string
|
||
|
|
URL string
|
||
|
|
Timestamp time.Time
|
||
|
|
Sentiment string // "positive", "negative", "neutral"
|
||
|
|
}
|
||
|
|
|
||
|
|
HTMX PATTERNS:
|
||
|
|
// Timeframe selection
|
||
|
|
<wa-radio-group hx-on:wa-change="
|
||
|
|
htmx.ajax('GET', '/api/asset/eth/chart?tf=' + event.target.value, '#price-chart-container')
|
||
|
|
">
|
||
|
|
|
||
|
|
// Price auto-refresh
|
||
|
|
<div id="price-display" hx-get="/api/asset/eth/price" hx-trigger="every 30s">
|
||
|
|
@PriceDisplay(price)
|
||
|
|
</div>
|
||
|
|
|
||
|
|
// News infinite scroll
|
||
|
|
<tr hx-get="/api/asset/eth/news?page={nextPage}"
|
||
|
|
hx-trigger="revealed"
|
||
|
|
hx-swap="afterend">
|
||
|
|
|
||
|
|
// Action buttons
|
||
|
|
<wa-button hx-get="/drawers/swap?from=eth" hx-target="#drawer-container">
|
||
|
|
Buy
|
||
|
|
</wa-button>
|
||
|
|
================================================================================
|
||
|
|
-->
|
||
|
|
<html lang="en" class="wa-cloak">
|
||
|
|
<head>
|
||
|
|
<meta charset="utf-8">
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
|
|
<title>Ethereum (ETH) - 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;
|
||
|
|
--asset-color: #627eea;
|
||
|
|
}
|
||
|
|
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Asset Hero Section */
|
||
|
|
.asset-hero {
|
||
|
|
display: flex;
|
||
|
|
flex-wrap: wrap;
|
||
|
|
justify-content: space-between;
|
||
|
|
align-items: flex-start;
|
||
|
|
gap: var(--wa-space-xl);
|
||
|
|
margin-bottom: var(--wa-space-xl);
|
||
|
|
padding: var(--wa-space-xl);
|
||
|
|
background: var(--wa-color-surface);
|
||
|
|
border-radius: var(--wa-radius-l);
|
||
|
|
}
|
||
|
|
|
||
|
|
.asset-identity {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: var(--wa-space-l);
|
||
|
|
}
|
||
|
|
|
||
|
|
.asset-logo {
|
||
|
|
width: 72px;
|
||
|
|
height: 72px;
|
||
|
|
border-radius: 50%;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
font-size: 28px;
|
||
|
|
font-weight: 700;
|
||
|
|
color: white;
|
||
|
|
background: var(--asset-color);
|
||
|
|
}
|
||
|
|
|
||
|
|
.asset-name-block {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
gap: var(--wa-space-2xs);
|
||
|
|
}
|
||
|
|
|
||
|
|
.asset-badges {
|
||
|
|
display: flex;
|
||
|
|
gap: var(--wa-space-xs);
|
||
|
|
margin-top: var(--wa-space-2xs);
|
||
|
|
}
|
||
|
|
|
||
|
|
.price-block {
|
||
|
|
text-align: right;
|
||
|
|
}
|
||
|
|
|
||
|
|
.current-price {
|
||
|
|
font-size: var(--wa-font-size-3xl);
|
||
|
|
font-weight: 700;
|
||
|
|
line-height: 1.1;
|
||
|
|
}
|
||
|
|
|
||
|
|
.price-change {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: flex-end;
|
||
|
|
gap: var(--wa-space-xs);
|
||
|
|
margin-top: var(--wa-space-2xs);
|
||
|
|
}
|
||
|
|
|
||
|
|
.price-change.positive { color: var(--wa-color-success); }
|
||
|
|
.price-change.negative { color: var(--wa-color-danger); }
|
||
|
|
|
||
|
|
.price-range {
|
||
|
|
display: flex;
|
||
|
|
gap: var(--wa-space-l);
|
||
|
|
margin-top: var(--wa-space-m);
|
||
|
|
padding-top: var(--wa-space-m);
|
||
|
|
border-top: 1px solid var(--wa-color-neutral-100);
|
||
|
|
font-size: var(--wa-font-size-xs);
|
||
|
|
color: var(--wa-color-neutral-500);
|
||
|
|
}
|
||
|
|
|
||
|
|
.hero-actions {
|
||
|
|
display: flex;
|
||
|
|
gap: var(--wa-space-s);
|
||
|
|
width: 100%;
|
||
|
|
margin-top: var(--wa-space-l);
|
||
|
|
padding-top: var(--wa-space-l);
|
||
|
|
border-top: 1px solid var(--wa-color-neutral-100);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Stats Grid */
|
||
|
|
.stats-grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||
|
|
gap: var(--wa-space-m);
|
||
|
|
margin-bottom: var(--wa-space-xl);
|
||
|
|
}
|
||
|
|
|
||
|
|
.stat-item {
|
||
|
|
background: var(--wa-color-surface);
|
||
|
|
padding: var(--wa-space-m);
|
||
|
|
border-radius: var(--wa-radius-m);
|
||
|
|
}
|
||
|
|
|
||
|
|
.stat-label {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: var(--wa-space-2xs);
|
||
|
|
font-size: var(--wa-font-size-xs);
|
||
|
|
color: var(--wa-color-neutral-500);
|
||
|
|
margin-bottom: var(--wa-space-2xs);
|
||
|
|
}
|
||
|
|
|
||
|
|
.stat-value {
|
||
|
|
font-size: var(--wa-font-size-m);
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
|
||
|
|
.stat-sub {
|
||
|
|
font-size: var(--wa-font-size-xs);
|
||
|
|
color: var(--wa-color-neutral-400);
|
||
|
|
margin-top: var(--wa-space-3xs);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Chart Card */
|
||
|
|
.chart-card {
|
||
|
|
margin-bottom: var(--wa-space-xl);
|
||
|
|
}
|
||
|
|
|
||
|
|
.chart-header {
|
||
|
|
display: flex;
|
||
|
|
justify-content: space-between;
|
||
|
|
align-items: center;
|
||
|
|
margin-bottom: var(--wa-space-l);
|
||
|
|
}
|
||
|
|
|
||
|
|
.chart-container {
|
||
|
|
height: 320px;
|
||
|
|
position: relative;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Content Grid */
|
||
|
|
.content-grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 1fr 1fr;
|
||
|
|
gap: var(--wa-space-xl);
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (max-width: 1024px) {
|
||
|
|
.content-grid {
|
||
|
|
grid-template-columns: 1fr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* About Section */
|
||
|
|
.about-description {
|
||
|
|
font-size: var(--wa-font-size-s);
|
||
|
|
line-height: 1.7;
|
||
|
|
color: var(--wa-color-neutral-700);
|
||
|
|
margin-bottom: var(--wa-space-l);
|
||
|
|
}
|
||
|
|
|
||
|
|
.about-description p {
|
||
|
|
margin: 0 0 var(--wa-space-m) 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.resource-links {
|
||
|
|
display: flex;
|
||
|
|
flex-wrap: wrap;
|
||
|
|
gap: var(--wa-space-s);
|
||
|
|
}
|
||
|
|
|
||
|
|
.resource-link {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: var(--wa-space-2xs);
|
||
|
|
padding: var(--wa-space-xs) var(--wa-space-s);
|
||
|
|
background: var(--wa-color-surface-alt);
|
||
|
|
border-radius: var(--wa-radius-s);
|
||
|
|
font-size: var(--wa-font-size-xs);
|
||
|
|
color: var(--wa-color-neutral-600);
|
||
|
|
text-decoration: none;
|
||
|
|
transition: background 0.15s, color 0.15s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.resource-link:hover {
|
||
|
|
background: var(--wa-color-primary-subtle);
|
||
|
|
color: var(--wa-color-primary);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* News Table */
|
||
|
|
.news-table {
|
||
|
|
width: 100%;
|
||
|
|
border-collapse: collapse;
|
||
|
|
}
|
||
|
|
|
||
|
|
.news-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);
|
||
|
|
}
|
||
|
|
|
||
|
|
.news-table td {
|
||
|
|
padding: var(--wa-space-m);
|
||
|
|
border-bottom: 1px solid var(--wa-color-neutral-100);
|
||
|
|
font-size: var(--wa-font-size-s);
|
||
|
|
vertical-align: top;
|
||
|
|
}
|
||
|
|
|
||
|
|
.news-table tr:hover td {
|
||
|
|
background: var(--wa-color-surface-alt);
|
||
|
|
}
|
||
|
|
|
||
|
|
.news-table tr:last-child td {
|
||
|
|
border-bottom: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.news-title {
|
||
|
|
font-weight: 500;
|
||
|
|
color: var(--wa-color-neutral-900);
|
||
|
|
text-decoration: none;
|
||
|
|
display: block;
|
||
|
|
margin-bottom: var(--wa-space-2xs);
|
||
|
|
}
|
||
|
|
|
||
|
|
.news-title:hover {
|
||
|
|
color: var(--wa-color-primary);
|
||
|
|
}
|
||
|
|
|
||
|
|
.news-meta {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: var(--wa-space-s);
|
||
|
|
font-size: var(--wa-font-size-xs);
|
||
|
|
color: var(--wa-color-neutral-500);
|
||
|
|
}
|
||
|
|
|
||
|
|
.sentiment-badge {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: var(--wa-space-3xs);
|
||
|
|
padding: var(--wa-space-3xs) var(--wa-space-xs);
|
||
|
|
border-radius: var(--wa-radius-s);
|
||
|
|
font-size: var(--wa-font-size-xs);
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sentiment-badge.positive {
|
||
|
|
background: var(--wa-color-success-subtle);
|
||
|
|
color: var(--wa-color-success);
|
||
|
|
}
|
||
|
|
|
||
|
|
.sentiment-badge.negative {
|
||
|
|
background: var(--wa-color-danger-subtle);
|
||
|
|
color: var(--wa-color-danger);
|
||
|
|
}
|
||
|
|
|
||
|
|
.sentiment-badge.neutral {
|
||
|
|
background: var(--wa-color-neutral-100);
|
||
|
|
color: var(--wa-color-neutral-600);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Back link */
|
||
|
|
.back-link {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: var(--wa-space-xs);
|
||
|
|
color: var(--wa-color-neutral-500);
|
||
|
|
text-decoration: none;
|
||
|
|
font-size: var(--wa-font-size-s);
|
||
|
|
margin-bottom: var(--wa-space-m);
|
||
|
|
transition: color 0.15s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.back-link:hover {
|
||
|
|
color: var(--wa-color-primary);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Your Holdings Card */
|
||
|
|
.holdings-card {
|
||
|
|
background: linear-gradient(135deg, var(--asset-color) 0%, color-mix(in srgb, var(--asset-color) 80%, black) 100%);
|
||
|
|
color: white;
|
||
|
|
margin-bottom: var(--wa-space-xl);
|
||
|
|
}
|
||
|
|
|
||
|
|
.holdings-card wa-card::part(base) {
|
||
|
|
background: transparent;
|
||
|
|
}
|
||
|
|
|
||
|
|
.holdings-label {
|
||
|
|
opacity: 0.8;
|
||
|
|
font-size: var(--wa-font-size-xs);
|
||
|
|
}
|
||
|
|
|
||
|
|
.holdings-value {
|
||
|
|
font-size: var(--wa-font-size-2xl);
|
||
|
|
font-weight: 700;
|
||
|
|
}
|
||
|
|
|
||
|
|
.holdings-usd {
|
||
|
|
opacity: 0.7;
|
||
|
|
font-size: var(--wa-font-size-s);
|
||
|
|
}
|
||
|
|
</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">
|
||
|
|
<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" class="active">
|
||
|
|
<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">
|
||
|
|
<a href="tokens.html" class="back-link">
|
||
|
|
<wa-icon name="arrow-left"></wa-icon>
|
||
|
|
Back to Tokens
|
||
|
|
</a>
|
||
|
|
|
||
|
|
<!-- Asset Hero -->
|
||
|
|
<div class="asset-hero">
|
||
|
|
<div class="asset-identity">
|
||
|
|
<div class="asset-logo" id="asset-logo">E</div>
|
||
|
|
<div class="asset-name-block">
|
||
|
|
<span class="wa-heading-2xl" id="asset-name">Ethereum</span>
|
||
|
|
<span class="wa-caption-m" style="color: var(--wa-color-neutral-500);" id="asset-symbol">ETH</span>
|
||
|
|
<div class="asset-badges">
|
||
|
|
<wa-badge variant="neutral" pill>Rank #2</wa-badge>
|
||
|
|
<wa-badge variant="neutral" pill>
|
||
|
|
<wa-icon name="circle" variant="solid" style="font-size: 6px; color: #627eea;"></wa-icon>
|
||
|
|
Ethereum
|
||
|
|
</wa-badge>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="price-block">
|
||
|
|
<div class="current-price" id="current-price">
|
||
|
|
<wa-format-number type="currency" currency="USD" value="2345.67" lang="en-US"></wa-format-number>
|
||
|
|
</div>
|
||
|
|
<div class="price-change positive" id="price-change">
|
||
|
|
<wa-icon name="arrow-trend-up" style="font-size: 16px;"></wa-icon>
|
||
|
|
<span>+$75.32 (3.31%)</span>
|
||
|
|
<span style="color: var(--wa-color-neutral-400); font-size: var(--wa-font-size-xs);">24h</span>
|
||
|
|
</div>
|
||
|
|
<div class="price-range">
|
||
|
|
<span>24h Low: <strong>$2,298.20</strong></span>
|
||
|
|
<span>24h High: <strong>$2,412.50</strong></span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="hero-actions">
|
||
|
|
<wa-button variant="brand" id="buy-btn">
|
||
|
|
<wa-icon slot="start" name="plus"></wa-icon>
|
||
|
|
Buy
|
||
|
|
</wa-button>
|
||
|
|
<wa-button variant="neutral" appearance="outlined" id="sell-btn">
|
||
|
|
<wa-icon slot="start" name="minus"></wa-icon>
|
||
|
|
Sell
|
||
|
|
</wa-button>
|
||
|
|
<wa-button variant="neutral" appearance="outlined" id="swap-btn">
|
||
|
|
<wa-icon slot="start" name="arrow-right-arrow-left"></wa-icon>
|
||
|
|
Swap
|
||
|
|
</wa-button>
|
||
|
|
<wa-button variant="neutral" appearance="outlined" id="send-btn">
|
||
|
|
<wa-icon slot="start" name="paper-plane"></wa-icon>
|
||
|
|
Send
|
||
|
|
</wa-button>
|
||
|
|
<div style="flex: 1;"></div>
|
||
|
|
<wa-tooltip content="Add to Watchlist">
|
||
|
|
<wa-icon-button name="star" variant="regular" label="Add to watchlist" id="watchlist-btn"></wa-icon-button>
|
||
|
|
</wa-tooltip>
|
||
|
|
<wa-tooltip content="Share">
|
||
|
|
<wa-icon-button name="share-nodes" label="Share"></wa-icon-button>
|
||
|
|
</wa-tooltip>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Your Holdings -->
|
||
|
|
<wa-card class="holdings-card">
|
||
|
|
<div class="wa-flank">
|
||
|
|
<div class="wa-stack wa-gap-xs">
|
||
|
|
<span class="holdings-label">Your Holdings</span>
|
||
|
|
<span class="holdings-value">2.847 ETH</span>
|
||
|
|
<span class="holdings-usd">$6,682.04</span>
|
||
|
|
</div>
|
||
|
|
<div class="wa-stack wa-gap-xs" style="text-align: right;">
|
||
|
|
<span class="holdings-label">Avg. Buy Price</span>
|
||
|
|
<span style="font-size: var(--wa-font-size-l); font-weight: 600;">$2,180.50</span>
|
||
|
|
<span style="opacity: 0.8; font-size: var(--wa-font-size-xs);">
|
||
|
|
<wa-icon name="arrow-trend-up" style="font-size: 12px;"></wa-icon>
|
||
|
|
+7.58% Profit
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</wa-card>
|
||
|
|
|
||
|
|
<!-- Stats Grid -->
|
||
|
|
<div class="stats-grid">
|
||
|
|
<div class="stat-item">
|
||
|
|
<div class="stat-label">
|
||
|
|
Market Cap
|
||
|
|
<wa-tooltip content="Total value of all circulating coins">
|
||
|
|
<wa-icon name="circle-info" style="font-size: 12px; cursor: help;"></wa-icon>
|
||
|
|
</wa-tooltip>
|
||
|
|
</div>
|
||
|
|
<div class="stat-value">$282.1B</div>
|
||
|
|
<div class="stat-sub">#2 by market cap</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="stat-item">
|
||
|
|
<div class="stat-label">
|
||
|
|
24h Volume
|
||
|
|
<wa-tooltip content="Trading volume in the last 24 hours">
|
||
|
|
<wa-icon name="circle-info" style="font-size: 12px; cursor: help;"></wa-icon>
|
||
|
|
</wa-tooltip>
|
||
|
|
</div>
|
||
|
|
<div class="stat-value">$12.4B</div>
|
||
|
|
<div class="stat-sub">4.4% of market cap</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="stat-item">
|
||
|
|
<div class="stat-label">
|
||
|
|
Circulating Supply
|
||
|
|
<wa-tooltip content="Coins currently in circulation">
|
||
|
|
<wa-icon name="circle-info" style="font-size: 12px; cursor: help;"></wa-icon>
|
||
|
|
</wa-tooltip>
|
||
|
|
</div>
|
||
|
|
<div class="stat-value">120.2M ETH</div>
|
||
|
|
<div class="stat-sub">No max supply</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="stat-item">
|
||
|
|
<div class="stat-label">
|
||
|
|
All-Time High
|
||
|
|
<wa-tooltip content="Highest price ever recorded">
|
||
|
|
<wa-icon name="circle-info" style="font-size: 12px; cursor: help;"></wa-icon>
|
||
|
|
</wa-tooltip>
|
||
|
|
</div>
|
||
|
|
<div class="stat-value">$4,878.26</div>
|
||
|
|
<div class="stat-sub">Nov 10, 2021 (-51.9%)</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="stat-item">
|
||
|
|
<div class="stat-label">
|
||
|
|
All-Time Low
|
||
|
|
<wa-tooltip content="Lowest price ever recorded">
|
||
|
|
<wa-icon name="circle-info" style="font-size: 12px; cursor: help;"></wa-icon>
|
||
|
|
</wa-tooltip>
|
||
|
|
</div>
|
||
|
|
<div class="stat-value">$0.432</div>
|
||
|
|
<div class="stat-sub">Oct 20, 2015 (+542,617%)</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="stat-item">
|
||
|
|
<div class="stat-label">
|
||
|
|
Fully Diluted Valuation
|
||
|
|
<wa-tooltip content="Market cap if max supply was in circulation">
|
||
|
|
<wa-icon name="circle-info" style="font-size: 12px; cursor: help;"></wa-icon>
|
||
|
|
</wa-tooltip>
|
||
|
|
</div>
|
||
|
|
<div class="stat-value">$282.1B</div>
|
||
|
|
<div class="stat-sub">Same as market cap</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Price Chart -->
|
||
|
|
<wa-card class="chart-card">
|
||
|
|
<div class="chart-header">
|
||
|
|
<div class="wa-stack wa-gap-2xs">
|
||
|
|
<span class="wa-heading-m">Price Chart</span>
|
||
|
|
<span class="wa-caption-xs" style="color: var(--wa-color-neutral-500);">ETH to USD</span>
|
||
|
|
</div>
|
||
|
|
<wa-radio-group value="1m" orientation="horizontal" id="chart-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 appearance="button" value="all">ALL</wa-radio>
|
||
|
|
</wa-radio-group>
|
||
|
|
</div>
|
||
|
|
<div id="price-chart-container" class="chart-container"></div>
|
||
|
|
</wa-card>
|
||
|
|
|
||
|
|
<!-- Content Grid: About & News -->
|
||
|
|
<div class="content-grid">
|
||
|
|
<!-- About Section -->
|
||
|
|
<wa-card>
|
||
|
|
<div slot="header">
|
||
|
|
<span class="wa-heading-m">About Ethereum</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="about-description">
|
||
|
|
<p>
|
||
|
|
Ethereum is a decentralized, open-source blockchain platform that enables the creation of smart contracts and decentralized applications (dApps). Founded by Vitalik Buterin in 2015, Ethereum introduced programmable blockchain technology, allowing developers to build applications that run exactly as programmed without downtime, censorship, or third-party interference.
|
||
|
|
</p>
|
||
|
|
<p>
|
||
|
|
ETH is the native cryptocurrency of the Ethereum network, used to pay for transaction fees (gas) and computational services. Following "The Merge" in September 2022, Ethereum transitioned from Proof-of-Work to Proof-of-Stake consensus, significantly reducing energy consumption by ~99.95%.
|
||
|
|
</p>
|
||
|
|
<p>
|
||
|
|
As the leading smart contract platform, Ethereum hosts the majority of DeFi protocols, NFT marketplaces, and Layer 2 scaling solutions, making it the backbone of Web3 infrastructure.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<wa-divider></wa-divider>
|
||
|
|
|
||
|
|
<div class="wa-stack wa-gap-m" style="margin-top: var(--wa-space-m);">
|
||
|
|
<span class="wa-caption-s" style="color: var(--wa-color-neutral-500);">Resources</span>
|
||
|
|
<div class="resource-links">
|
||
|
|
<a href="https://ethereum.org" target="_blank" class="resource-link">
|
||
|
|
<wa-icon name="globe"></wa-icon>
|
||
|
|
Website
|
||
|
|
</a>
|
||
|
|
<a href="https://ethereum.org/whitepaper" target="_blank" class="resource-link">
|
||
|
|
<wa-icon name="file-lines"></wa-icon>
|
||
|
|
Whitepaper
|
||
|
|
</a>
|
||
|
|
<a href="https://etherscan.io" target="_blank" class="resource-link">
|
||
|
|
<wa-icon name="magnifying-glass"></wa-icon>
|
||
|
|
Explorer
|
||
|
|
</a>
|
||
|
|
<a href="https://twitter.com/ethereum" target="_blank" class="resource-link">
|
||
|
|
<wa-icon name="x-twitter" family="brands"></wa-icon>
|
||
|
|
Twitter
|
||
|
|
</a>
|
||
|
|
<a href="https://discord.gg/ethereum-org" target="_blank" class="resource-link">
|
||
|
|
<wa-icon name="discord" family="brands"></wa-icon>
|
||
|
|
Discord
|
||
|
|
</a>
|
||
|
|
<a href="https://github.com/ethereum" target="_blank" class="resource-link">
|
||
|
|
<wa-icon name="github" family="brands"></wa-icon>
|
||
|
|
GitHub
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</wa-card>
|
||
|
|
|
||
|
|
<!-- Recent News -->
|
||
|
|
<wa-card>
|
||
|
|
<div slot="header" class="wa-flank">
|
||
|
|
<span class="wa-heading-m">Recent News</span>
|
||
|
|
<wa-button appearance="plain" size="small">View All</wa-button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<table class="news-table">
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th>Article</th>
|
||
|
|
<th style="width: 100px;">Sentiment</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody id="news-tbody">
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<a href="#" class="news-title">Ethereum ETF Sees Record $500M Inflows as Institutional Interest Surges</a>
|
||
|
|
<div class="news-meta">
|
||
|
|
<span>CoinDesk</span>
|
||
|
|
<span>•</span>
|
||
|
|
<span>2 hours ago</span>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
<td>
|
||
|
|
<span class="sentiment-badge positive">
|
||
|
|
<wa-icon name="arrow-trend-up" style="font-size: 10px;"></wa-icon>
|
||
|
|
Bullish
|
||
|
|
</span>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<a href="#" class="news-title">Vitalik Buterin Proposes New EIP for Account Abstraction Improvements</a>
|
||
|
|
<div class="news-meta">
|
||
|
|
<span>The Block</span>
|
||
|
|
<span>•</span>
|
||
|
|
<span>5 hours ago</span>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
<td>
|
||
|
|
<span class="sentiment-badge positive">
|
||
|
|
<wa-icon name="arrow-trend-up" style="font-size: 10px;"></wa-icon>
|
||
|
|
Bullish
|
||
|
|
</span>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<a href="#" class="news-title">Ethereum Gas Fees Drop to Yearly Low Amid Layer 2 Adoption</a>
|
||
|
|
<div class="news-meta">
|
||
|
|
<span>Decrypt</span>
|
||
|
|
<span>•</span>
|
||
|
|
<span>8 hours ago</span>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
<td>
|
||
|
|
<span class="sentiment-badge positive">
|
||
|
|
<wa-icon name="arrow-trend-up" style="font-size: 10px;"></wa-icon>
|
||
|
|
Bullish
|
||
|
|
</span>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<a href="#" class="news-title">DeFi TVL on Ethereum Reaches $50B Milestone</a>
|
||
|
|
<div class="news-meta">
|
||
|
|
<span>DeFi Pulse</span>
|
||
|
|
<span>•</span>
|
||
|
|
<span>12 hours ago</span>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
<td>
|
||
|
|
<span class="sentiment-badge positive">
|
||
|
|
<wa-icon name="arrow-trend-up" style="font-size: 10px;"></wa-icon>
|
||
|
|
Bullish
|
||
|
|
</span>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<a href="#" class="news-title">SEC Delays Decision on Ethereum Options ETF Until Q2</a>
|
||
|
|
<div class="news-meta">
|
||
|
|
<span>Bloomberg</span>
|
||
|
|
<span>•</span>
|
||
|
|
<span>1 day ago</span>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
<td>
|
||
|
|
<span class="sentiment-badge neutral">
|
||
|
|
<wa-icon name="minus" style="font-size: 10px;"></wa-icon>
|
||
|
|
Neutral
|
||
|
|
</span>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr>
|
||
|
|
<td>
|
||
|
|
<a href="#" class="news-title">Ethereum Foundation Sells 100 ETH, Sparking Community Debate</a>
|
||
|
|
<div class="news-meta">
|
||
|
|
<span>CryptoSlate</span>
|
||
|
|
<span>•</span>
|
||
|
|
<span>1 day ago</span>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
<td>
|
||
|
|
<span class="sentiment-badge negative">
|
||
|
|
<wa-icon name="arrow-trend-down" style="font-size: 10px;"></wa-icon>
|
||
|
|
Bearish
|
||
|
|
</span>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
|
||
|
|
<div slot="footer">
|
||
|
|
<a href="#" class="wa-cluster wa-gap-xs wa-caption-s" style="color: var(--wa-color-primary);">
|
||
|
|
<span>Load more news</span>
|
||
|
|
<wa-icon name="arrow-down"></wa-icon>
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
</wa-card>
|
||
|
|
</div>
|
||
|
|
</main>
|
||
|
|
</div>
|
||
|
|
</wa-page>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
// Sample price history data (30 days)
|
||
|
|
const priceHistoryData = [
|
||
|
|
{ date: '2024-12-05', value: 2180 },
|
||
|
|
{ date: '2024-12-06', value: 2210 },
|
||
|
|
{ date: '2024-12-07', value: 2195 },
|
||
|
|
{ date: '2024-12-08', value: 2240 },
|
||
|
|
{ date: '2024-12-09', value: 2285 },
|
||
|
|
{ date: '2024-12-10', value: 2310 },
|
||
|
|
{ date: '2024-12-11', value: 2275 },
|
||
|
|
{ date: '2024-12-12', value: 2320 },
|
||
|
|
{ date: '2024-12-13', value: 2350 },
|
||
|
|
{ date: '2024-12-14', value: 2380 },
|
||
|
|
{ date: '2024-12-15', value: 2340 },
|
||
|
|
{ date: '2024-12-16', value: 2310 },
|
||
|
|
{ date: '2024-12-17', value: 2280 },
|
||
|
|
{ date: '2024-12-18', value: 2250 },
|
||
|
|
{ date: '2024-12-19', value: 2220 },
|
||
|
|
{ date: '2024-12-20', value: 2190 },
|
||
|
|
{ date: '2024-12-21', value: 2210 },
|
||
|
|
{ date: '2024-12-22', value: 2240 },
|
||
|
|
{ date: '2024-12-23', value: 2280 },
|
||
|
|
{ date: '2024-12-24', value: 2310 },
|
||
|
|
{ date: '2024-12-25', value: 2290 },
|
||
|
|
{ date: '2024-12-26', value: 2320 },
|
||
|
|
{ date: '2024-12-27', value: 2350 },
|
||
|
|
{ date: '2024-12-28', value: 2310 },
|
||
|
|
{ date: '2024-12-29', value: 2280 },
|
||
|
|
{ date: '2024-12-30', value: 2310 },
|
||
|
|
{ date: '2024-12-31', value: 2340 },
|
||
|
|
{ date: '2025-01-01', value: 2320 },
|
||
|
|
{ date: '2025-01-02', value: 2290 },
|
||
|
|
{ date: '2025-01-03', value: 2270 },
|
||
|
|
{ date: '2025-01-04', value: 2345 }
|
||
|
|
];
|
||
|
|
|
||
|
|
// Initialize price chart
|
||
|
|
let priceChart = null;
|
||
|
|
|
||
|
|
function initPriceChart() {
|
||
|
|
const container = document.getElementById('price-chart-container');
|
||
|
|
if (container && typeof SemiFilledAreaChart !== 'undefined') {
|
||
|
|
priceChart = new SemiFilledAreaChart(container, {
|
||
|
|
data: priceHistoryData,
|
||
|
|
height: 320,
|
||
|
|
color: {
|
||
|
|
line: '#627eea',
|
||
|
|
areaFrom: 'rgba(98, 126, 234, 0.3)',
|
||
|
|
areaTo: 'rgba(98, 126, 234, 0.05)'
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Timeframe change handler
|
||
|
|
document.getElementById('chart-timeframe').addEventListener('wa-change', function(e) {
|
||
|
|
// In production, this would fetch new data based on timeframe
|
||
|
|
// For now, we just re-render with the same data
|
||
|
|
if (priceChart) {
|
||
|
|
priceChart.setData(priceHistoryData);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
// Watchlist toggle
|
||
|
|
const watchlistBtn = document.getElementById('watchlist-btn');
|
||
|
|
let isWatchlisted = false;
|
||
|
|
|
||
|
|
watchlistBtn.addEventListener('click', function() {
|
||
|
|
isWatchlisted = !isWatchlisted;
|
||
|
|
this.setAttribute('name', isWatchlisted ? 'star' : 'star');
|
||
|
|
this.setAttribute('variant', isWatchlisted ? 'solid' : 'regular');
|
||
|
|
this.style.color = isWatchlisted ? 'var(--wa-color-warning)' : '';
|
||
|
|
});
|
||
|
|
|
||
|
|
// Sidebar navigation
|
||
|
|
document.querySelectorAll('.sidebar-nav a').forEach(link => {
|
||
|
|
link.addEventListener('click', function(e) {
|
||
|
|
if (this.getAttribute('href') === '#') {
|
||
|
|
e.preventDefault();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// Initialize chart on DOM ready
|
||
|
|
document.addEventListener('DOMContentLoaded', () => {
|
||
|
|
setTimeout(initPriceChart, 100);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Action button handlers (placeholder)
|
||
|
|
['buy-btn', 'sell-btn', 'swap-btn', 'send-btn'].forEach(id => {
|
||
|
|
document.getElementById(id)?.addEventListener('click', () => {
|
||
|
|
console.log(`${id} clicked - would open drawer in production`);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|