NEO-TRADE / js /ui.js
diamond-in's picture
Update js/ui.js
1daca0b verified
import { state } from './state.js';
// --- FOOTPRINT / DELTA LOGIC ---
let volBuy = 0;
let volSell = 0;
export function updateDelta(qty, isMaker) {
// Binance API: If isMaker (m) = true, it means Taker SOLD.
if(isMaker) volSell += parseFloat(qty);
else volBuy += parseFloat(qty);
}
export function initFootprint() {
const box = document.getElementById('footprint-box');
// Every 3 seconds, push a new bar
setInterval(() => {
if (volBuy === 0 && volSell === 0) return; // No data, do nothing
const total = volBuy + volSell;
const buyPct = (volBuy / total) * 100;
const sellPct = (volSell / total) * 100;
const bar = document.createElement('div');
// Tailwind classes for a vertical stacked bar
bar.className = "w-2 h-full border-r border-gray-300 shrink-0 flex flex-col-reverse";
bar.innerHTML = `
<div style="height:${buyPct}%" class="bg-[#bef264]" title="Buy: ${volBuy.toFixed(2)}"></div>
<div style="height:${sellPct}%" class="bg-[#fb7185]" title="Sell: ${volSell.toFixed(2)}"></div>
`;
box.appendChild(bar);
// Keep list clean (remove old bars)
if(box.children.length > 50) {
box.removeChild(box.firstChild);
}
// Reset counters for next 3s interval
volBuy = 0;
volSell = 0;
}, 3000);
}
// --- EXISTING UI FUNCTIONS (Keep these) ---
export function updatePrice(price) {
const el = document.getElementById('price-ticker');
if(el) el.innerText = parseFloat(price).toFixed(2);
}
export function detectTimezone() {
const el = document.getElementById('timezone-label');
if(el) el.innerText = Intl.DateTimeFormat().resolvedOptions().timeZone;
}
export function setStatus(text, type) {
const el = document.getElementById('status-text');
if(!el) return;
el.innerText = text;
el.className = type === 'live' ? "text-green-600 blink" : "text-orange-500 font-bold";
}
export function renderDom(bids, asks) {
const domBox = document.getElementById('dom-box');
if(!domBox) return;
const cleanAsks = asks.slice(0, 8).reverse();
const cleanBids = bids.slice(0, 8);
let rows = '';
cleanAsks.forEach(a => rows += makeRow(a[0], a[1], 'ask'));
rows += `<div class="h-6 flex items-center justify-center bg-gray-100 border-y border-black font-bold text-[10px]">SPREAD</div>`;
cleanBids.forEach(b => rows += makeRow(b[0], b[1], 'bid'));
domBox.innerHTML = rows;
}
function makeRow(price, qty, type) {
const color = type === 'bid' ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700';
const align = type === 'bid' ? 'left-0' : 'right-0';
const w = Math.min(parseFloat(qty)*20, 100);
return `<div class="flex items-center relative h-5 overflow-hidden hover:bg-gray-200">
<div class="absolute ${align} top-0 h-full ${color.split(' ')[0]}" style="width:${w}%"></div>
<span class="w-1/3 z-10 pl-2 text-left">${type === 'bid' ? qty : ''}</span>
<span class="w-1/3 z-10 text-center font-bold ${color.split(' ')[1]}">${parseFloat(price).toFixed(2)}</span>
<span class="w-1/3 z-10 pr-2 text-right">${type === 'ask' ? qty : ''}</span>
</div>`;
}
export function spawnBubble(qty, isMaker) {
const box = document.getElementById('bubble-box');
if(!box) return;
const b = document.createElement('div');
b.className = 'bubble';
const size = Math.min(qty * 50 + 20, 100);
b.style.width = size + 'px'; b.style.height = size + 'px';
b.style.left = Math.random() * 80 + '%';
b.style.backgroundColor = isMaker ? '#fb7185' : '#bef264';
b.innerHTML = `<span>${parseFloat(qty).toFixed(3)}</span>`;
box.appendChild(b);
setTimeout(() => b.remove(), 4000);
}