Skip to content

Commit bae5767

Browse files
committed
feat: add 5 new skills + dropdown nav redesign
New skills: - Yield Radar (DefiLlama BSC yield pools) - Stablecoin Flow (cross-chain stablecoin tracker) - Protocol TVL (BSC protocol rankings) - Market Pulse (CoinGecko global market overview) - Launch Scanner (DexScreener boosts + GoPlus safety) Backend: - DefiLlama proxy (yields, protocols, stablecoins, stablecoin-chains) - CoinGecko /global and /global-defi endpoints - DexScreener /top-boosts endpoint - Warmup tasks for new endpoints Frontend: - Dropdown nav: MEFAI + Markets/Signals/Meme/DeFi/Analytics menus - 2 new layouts: Analytics (4 new panels), Launch (safety-focused) - 42 total panels, 16 layouts - i18n: 12 new keys across 10 languages - Version bump to 1709580000
1 parent c0dc78a commit bae5767

14 files changed

Lines changed: 931 additions & 38 deletions

File tree

frontend/css/main.css

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ body {
8787
}
8888
.logo svg { flex-shrink: 0; }
8989

90-
#layout-nav { display: flex; gap: 0; }
90+
#layout-nav { display: flex; gap: 0; align-items: stretch; }
9191

9292
.layout-btn {
9393
background: none;
@@ -108,6 +108,69 @@ body {
108108
font-weight: 700;
109109
}
110110

111+
/* Dropdown nav */
112+
.nav-dropdown {
113+
position: relative;
114+
display: flex;
115+
align-items: stretch;
116+
}
117+
.nav-dropdown-trigger {
118+
background: none;
119+
border: none;
120+
border-bottom: 2px solid transparent;
121+
color: var(--text-muted);
122+
font-family: var(--font-mono);
123+
font-size: 11px;
124+
padding: 12px 12px 10px;
125+
cursor: pointer;
126+
transition: color 0.15s, border-color 0.15s;
127+
white-space: nowrap;
128+
}
129+
.nav-dropdown-trigger:hover,
130+
.nav-dropdown-trigger.active {
131+
color: var(--accent);
132+
}
133+
.nav-dropdown-trigger.active {
134+
border-bottom-color: var(--accent);
135+
font-weight: 700;
136+
}
137+
.nav-dropdown-menu {
138+
display: none;
139+
position: absolute;
140+
top: 100%;
141+
left: 0;
142+
min-width: 140px;
143+
background: var(--bg-panel);
144+
border: 1px solid var(--border);
145+
border-radius: 6px;
146+
box-shadow: 0 4px 16px rgba(0,0,0,0.4);
147+
z-index: 100;
148+
padding: 4px 0;
149+
}
150+
.nav-dropdown-menu.open { display: block; }
151+
.nav-dropdown-item {
152+
display: block;
153+
width: 100%;
154+
background: none;
155+
border: none;
156+
color: var(--text-muted);
157+
font-family: var(--font-mono);
158+
font-size: 11px;
159+
padding: 7px 14px;
160+
cursor: pointer;
161+
text-align: left;
162+
transition: color 0.1s, background 0.1s;
163+
white-space: nowrap;
164+
}
165+
.nav-dropdown-item:hover {
166+
color: var(--accent);
167+
background: var(--bg-hover);
168+
}
169+
.nav-dropdown-item.active {
170+
color: var(--accent);
171+
font-weight: 700;
172+
}
173+
111174
.header-right button {
112175
background: none;
113176
border: 1px solid var(--accent);

frontend/index.html

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<meta name="theme-color" content="#0b0e11">
99
<title>Binance Skills Terminal</title>
1010
<base href="/superbsc/">
11-
<link rel="stylesheet" href="static/css/main.css?v=1709570000">
11+
<link rel="stylesheet" href="static/css/main.css?v=1709580000">
1212
</head>
1313
<body>
1414
<!-- Inline fallback: ensures globals are available before modules load -->
@@ -150,19 +150,46 @@
150150
</span>
151151
<nav id="layout-nav">
152152
<button class="layout-btn active" data-layout="mefai" data-i18n="nav.mefai">MEFAI</button>
153-
<button class="layout-btn" data-layout="overview" data-i18n="nav.overview">Overview</button>
154-
<button class="layout-btn" data-layout="meme-hunter" data-i18n="nav.memeHunter">Meme Hunter</button>
155-
<button class="layout-btn" data-layout="whale-watcher" data-i18n="nav.whaleWatcher">Whale Watcher</button>
156-
<button class="layout-btn" data-layout="deep-dive" data-i18n="nav.deepDive">Deep Dive</button>
157-
<button class="layout-btn" data-layout="trader" data-i18n="nav.trader">Trader</button>
158-
<button class="layout-btn" data-layout="scanner" data-i18n="nav.scanner">Scanner</button>
159-
<button class="layout-btn" data-layout="alpha" data-i18n="nav.alpha">Alpha</button>
160-
<button class="layout-btn" data-layout="futures" data-i18n="nav.futures">Futures</button>
161-
<button class="layout-btn" data-layout="discovery" data-i18n="nav.discovery">Discovery</button>
162-
<button class="layout-btn" data-layout="intel" data-i18n="nav.intel">Intel</button>
163-
<button class="layout-btn" data-layout="defi" data-i18n="nav.defi">DeFi</button>
164-
<button class="layout-btn" data-layout="risk" data-i18n="nav.risk">Risk</button>
165-
<button class="layout-btn" data-layout="security" data-i18n="nav.security">Security</button>
153+
<div class="nav-dropdown">
154+
<button class="nav-dropdown-trigger" data-i18n="nav.markets">Markets &#9662;</button>
155+
<div class="nav-dropdown-menu">
156+
<button class="nav-dropdown-item" data-layout="overview" data-i18n="nav.overview">Overview</button>
157+
<button class="nav-dropdown-item" data-layout="trader" data-i18n="nav.trader">Trader</button>
158+
<button class="nav-dropdown-item" data-layout="futures" data-i18n="nav.futures">Futures</button>
159+
</div>
160+
</div>
161+
<div class="nav-dropdown">
162+
<button class="nav-dropdown-trigger" data-i18n="nav.signals">Signals &#9662;</button>
163+
<div class="nav-dropdown-menu">
164+
<button class="nav-dropdown-item" data-layout="alpha" data-i18n="nav.alpha">Alpha</button>
165+
<button class="nav-dropdown-item" data-layout="discovery" data-i18n="nav.discovery">Discovery</button>
166+
<button class="nav-dropdown-item" data-layout="intel" data-i18n="nav.intel">Intel</button>
167+
<button class="nav-dropdown-item" data-layout="whale-watcher" data-i18n="nav.whaleWatcher">Whale Watcher</button>
168+
</div>
169+
</div>
170+
<div class="nav-dropdown">
171+
<button class="nav-dropdown-trigger" data-i18n="nav.memeGroup">Meme &#9662;</button>
172+
<div class="nav-dropdown-menu">
173+
<button class="nav-dropdown-item" data-layout="meme-hunter" data-i18n="nav.memeHunter">Meme Hunter</button>
174+
<button class="nav-dropdown-item" data-layout="scanner" data-i18n="nav.scanner">Scanner</button>
175+
<button class="nav-dropdown-item" data-layout="deep-dive" data-i18n="nav.deepDive">Deep Dive</button>
176+
</div>
177+
</div>
178+
<div class="nav-dropdown">
179+
<button class="nav-dropdown-trigger" data-i18n="nav.defiGroup">DeFi &#9662;</button>
180+
<div class="nav-dropdown-menu">
181+
<button class="nav-dropdown-item" data-layout="defi" data-i18n="nav.defi">DeFi</button>
182+
<button class="nav-dropdown-item" data-layout="security" data-i18n="nav.security">Security</button>
183+
<button class="nav-dropdown-item" data-layout="risk" data-i18n="nav.risk">Risk</button>
184+
</div>
185+
</div>
186+
<div class="nav-dropdown">
187+
<button class="nav-dropdown-trigger" data-i18n="nav.analyticsGroup">Analytics &#9662;</button>
188+
<div class="nav-dropdown-menu">
189+
<button class="nav-dropdown-item" data-layout="analytics" data-i18n="nav.analytics">Analytics</button>
190+
<button class="nav-dropdown-item" data-layout="launch" data-i18n="nav.launch">Launch</button>
191+
</div>
192+
</div>
166193
</nav>
167194
</div>
168195
<div class="header-right">
@@ -220,6 +247,8 @@
220247
<button class="hamburger-item" data-layout="defi"><span data-i18n="nav.defi">DeFi</span></button>
221248
<button class="hamburger-item" data-layout="risk"><span data-i18n="nav.risk">Risk</span></button>
222249
<button class="hamburger-item" data-layout="security"><span data-i18n="nav.security">Security</span></button>
250+
<button class="hamburger-item" data-layout="analytics"><span data-i18n="nav.analytics">Analytics</span></button>
251+
<button class="hamburger-item" data-layout="launch"><span data-i18n="nav.launch">Launch</span></button>
223252
</div>
224253
<div class="hamburger-actions">
225254
<button class="hamburger-action" id="mobile-search" data-i18n="btn.search">Search</button>
@@ -301,6 +330,8 @@ <h2>Settings</h2>
301330
<button class="settings-option" data-value="intel">Intel</button>
302331
<button class="settings-option" data-value="defi">DeFi</button>
303332
<button class="settings-option" data-value="risk">Risk</button>
333+
<button class="settings-option" data-value="analytics">Analytics</button>
334+
<button class="settings-option" data-value="launch">Launch</button>
304335
</div>
305336
</div>
306337
<div class="settings-group">
@@ -327,22 +358,22 @@ <h2>Settings</h2>
327358
<div id="toast-container"></div>
328359

329360
<!-- Scripts -->
330-
<script type="module" src="static/js/store.js?v=1709570000"></script>
331-
<script type="module" src="static/js/api.js?v=1709570000"></script>
332-
<script type="module" src="static/js/utils.js?v=1709570000"></script>
333-
<script type="module" src="static/js/components/base-panel.js?v=1709570000"></script>
334-
<script type="module" src="static/js/components/data-table.js?v=1709570000"></script>
335-
<script type="module" src="static/js/components/status-bar.js?v=1709570000"></script>
336-
<script type="module" src="static/js/components/search-bar.js?v=1709570000"></script>
337-
<script type="module" src="static/js/components/command-palette.js?v=1709570000"></script>
338-
<script type="module" src="static/js/components/context-menu.js?v=1709570000"></script>
339-
<script type="module" src="static/js/components/toast.js?v=1709570000"></script>
340-
<script type="module" src="static/js/components/risk-badge.js?v=1709570000"></script>
341-
<script type="module" src="static/js/components/mini-chart.js?v=1709570000"></script>
342-
<script type="module" src="static/js/components/chart.js?v=1709570000"></script>
343-
<script type="module" src="static/js/components/ws-stream.js?v=1709570000"></script>
344-
<script type="module" src="static/js/components/settings.js?v=1709570000"></script>
345-
<script type="module" src="static/js/i18n.js?v=1709570000"></script>
346-
<script type="module" src="static/js/app.js?v=1709570000"></script>
361+
<script type="module" src="static/js/store.js?v=1709580000"></script>
362+
<script type="module" src="static/js/api.js?v=1709580000"></script>
363+
<script type="module" src="static/js/utils.js?v=1709580000"></script>
364+
<script type="module" src="static/js/components/base-panel.js?v=1709580000"></script>
365+
<script type="module" src="static/js/components/data-table.js?v=1709580000"></script>
366+
<script type="module" src="static/js/components/status-bar.js?v=1709580000"></script>
367+
<script type="module" src="static/js/components/search-bar.js?v=1709580000"></script>
368+
<script type="module" src="static/js/components/command-palette.js?v=1709580000"></script>
369+
<script type="module" src="static/js/components/context-menu.js?v=1709580000"></script>
370+
<script type="module" src="static/js/components/toast.js?v=1709580000"></script>
371+
<script type="module" src="static/js/components/risk-badge.js?v=1709580000"></script>
372+
<script type="module" src="static/js/components/mini-chart.js?v=1709580000"></script>
373+
<script type="module" src="static/js/components/chart.js?v=1709580000"></script>
374+
<script type="module" src="static/js/components/ws-stream.js?v=1709580000"></script>
375+
<script type="module" src="static/js/components/settings.js?v=1709580000"></script>
376+
<script type="module" src="static/js/i18n.js?v=1709580000"></script>
377+
<script type="module" src="static/js/app.js?v=1709580000"></script>
347378
</body>
348379
</html>

frontend/js/api.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,21 @@ export const api = {
199199
search: (q, chain) => get('/api/dex/search', { q, chainIds: chain || 'bsc' }, 30000),
200200
token: (addr) => get('/api/dex/token', { address: addr }, 30000),
201201
tokenChain: (chain, addr) => get('/api/dex/token-chain', { chain, address: addr }, 30000),
202+
topBoosts: () => get('/api/dex/top-boosts', {}, 30000),
202203
},
203204
// Skill 11: CoinGecko
204205
coingecko: {
205206
categories: (order) => get('/api/coingecko/categories', { order: order || 'market_cap_desc' }, 120000),
206207
categoryCoins: (cat, n) => get('/api/coingecko/category-coins', { category: cat, per_page: n || 20 }, 120000),
208+
global: () => get('/api/coingecko/global', {}, 60000),
209+
globalDefi: () => get('/api/coingecko/global-defi', {}, 60000),
210+
},
211+
// Skill 13: DefiLlama
212+
defillama: {
213+
yields: () => get('/api/defillama/yields', {}, 120000),
214+
protocols: () => get('/api/defillama/protocols', {}, 300000),
215+
stablecoins: () => get('/api/defillama/stablecoins', {}, 300000),
216+
stablecoinChains: () => get('/api/defillama/stablecoin-chains', {}, 300000),
207217
},
208218
// Skill 12: Etherscan
209219
etherscan: {

frontend/js/app.js

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ const panelRegistry = {
4343
'liquidity-lifecycle': 'liquidity-lifecycle-panel',
4444
'capital-rotation': 'capital-rotation-panel',
4545
'contract-mutation': 'contract-mutation-panel',
46+
'yield-radar': 'yield-radar-panel',
47+
'stablecoin-flow': 'stablecoin-flow-panel',
48+
'protocol-tvl': 'protocol-tvl-panel',
49+
'market-pulse': 'market-pulse-panel',
50+
'launch-scanner': 'launch-scanner-panel',
4651
};
4752

4853
// Layout presets
@@ -117,6 +122,16 @@ const layouts = {
117122
grid: 'grid-2x2',
118123
panels: ['contract-mutation', 'liquidity-lifecycle', 'goplus-scanner', 'capital-rotation'],
119124
},
125+
'analytics': {
126+
name: 'Analytics',
127+
grid: 'grid-2x2',
128+
panels: ['market-pulse', 'protocol-tvl', 'stablecoin-flow', 'yield-radar'],
129+
},
130+
'launch': {
131+
name: 'Launch',
132+
grid: 'grid-2x2',
133+
panels: ['launch-scanner', 'goplus-scanner', 'dex-intel', 'liquidity-lifecycle'],
134+
},
120135
};
121136

122137
const grid = document.getElementById('grid');
@@ -134,10 +149,11 @@ async function loadPanels() {
134149
'whale-intel', 'order-book-intel', 'token-grad',
135150
'liquidation-heatmap', 'dex-intel', 'goplus-scanner', 'multi-chain-wallet',
136151
'liquidity-lifecycle', 'capital-rotation', 'contract-mutation',
152+
'yield-radar', 'stablecoin-flow', 'protocol-tvl', 'market-pulse', 'launch-scanner',
137153
];
138154
await Promise.allSettled(
139155
panelModules.map(name =>
140-
import(`./panels/${name}.js?v=1709570000`).catch(e => console.warn(`Panel ${name} not loaded:`, e.message))
156+
import(`./panels/${name}.js?v=1709580000`).catch(e => console.warn(`Panel ${name} not loaded:`, e.message))
141157
)
142158
);
143159
}
@@ -172,10 +188,19 @@ function setLayout(layoutKey) {
172188
}
173189
});
174190

175-
// Update nav (desktop + mobile + hamburger)
176-
document.querySelectorAll('.layout-btn').forEach(btn => {
191+
// Update nav (desktop + dropdown items + mobile + hamburger)
192+
document.querySelectorAll('.layout-btn[data-layout]').forEach(btn => {
177193
btn.classList.toggle('active', btn.dataset.layout === layoutKey);
178194
});
195+
document.querySelectorAll('.nav-dropdown-item[data-layout]').forEach(item => {
196+
item.classList.toggle('active', item.dataset.layout === layoutKey);
197+
});
198+
// Highlight dropdown trigger if any child layout is active
199+
document.querySelectorAll('.nav-dropdown').forEach(dd => {
200+
const items = dd.querySelectorAll('.nav-dropdown-item[data-layout]');
201+
const hasActive = Array.from(items).some(i => i.dataset.layout === layoutKey);
202+
dd.querySelector('.nav-dropdown-trigger')?.classList.toggle('active', hasActive);
203+
});
179204
document.querySelectorAll('.mobile-nav-btn[data-layout]').forEach(btn => {
180205
btn.classList.toggle('active', btn.dataset.layout === layoutKey);
181206
});
@@ -219,13 +244,14 @@ document.addEventListener('keydown', (e) => {
219244
return;
220245
}
221246

222-
// Escape — close overlays
247+
// Escape — close overlays + dropdowns
223248
if (e.key === 'Escape') {
224249
closeSearch();
225250
closePalette();
226251
document.getElementById('help-overlay')?.classList.add('hidden');
227252
document.getElementById('settings-overlay')?.classList.add('hidden');
228253
document.getElementById('hamburger-drawer')?.classList.add('hidden');
254+
document.querySelectorAll('.nav-dropdown-menu').forEach(m => m.classList.remove('open'));
229255
return;
230256
}
231257

@@ -266,11 +292,39 @@ document.addEventListener('keydown', (e) => {
266292
}
267293
});
268294

269-
// Layout nav clicks (desktop)
270-
document.querySelectorAll('.layout-btn').forEach(btn => {
295+
// Layout nav clicks (desktop — direct buttons and dropdown items)
296+
document.querySelectorAll('.layout-btn[data-layout]').forEach(btn => {
271297
btn.addEventListener('click', () => setLayout(btn.dataset.layout));
272298
});
273299

300+
// Dropdown nav handlers
301+
document.querySelectorAll('.nav-dropdown').forEach(dd => {
302+
const trigger = dd.querySelector('.nav-dropdown-trigger');
303+
const menu = dd.querySelector('.nav-dropdown-menu');
304+
if (!trigger || !menu) return;
305+
306+
// Hover open/close
307+
dd.addEventListener('mouseenter', () => {
308+
document.querySelectorAll('.nav-dropdown-menu').forEach(m => m.classList.remove('open'));
309+
menu.classList.add('open');
310+
});
311+
dd.addEventListener('mouseleave', () => menu.classList.remove('open'));
312+
313+
// Click on dropdown items → select layout + close
314+
menu.querySelectorAll('[data-layout]').forEach(item => {
315+
item.addEventListener('click', (e) => {
316+
e.stopPropagation();
317+
setLayout(item.dataset.layout);
318+
document.querySelectorAll('.nav-dropdown-menu').forEach(m => m.classList.remove('open'));
319+
});
320+
});
321+
});
322+
323+
// Click outside closes all dropdowns
324+
document.addEventListener('click', () => {
325+
document.querySelectorAll('.nav-dropdown-menu').forEach(m => m.classList.remove('open'));
326+
});
327+
274328
// Mobile bottom nav clicks (quick tabs)
275329
document.querySelectorAll('#mobile-nav .mobile-nav-btn[data-layout]').forEach(btn => {
276330
btn.addEventListener('click', () => setLayout(btn.dataset.layout));

0 commit comments

Comments
 (0)