(function() { const divTicker = document.getElementById("ticker"); const divTickerTimestamp = document.getElementById("ticker-date"); const decimals = 2; let formatThousandsNoRounding = function(n, dp){ var e = '', s = e+n, l = s.length, b = n < 0 ? 1 : 0, i = s.lastIndexOf('.'), j = i == -1 ? l : i, r = e, d = s.substr(j+1, dp); while ( (j-=3) > b ) { r = ',' + s.substr(j, 3) + r; } return s.substr(0, j + 3) + r + (dp ? '.' + d + ( d.length < dp ? ('00000').substr(0, dp - d.length):e):e); }; let currentPrice = undefined; let newPrice = undefined; let countUpInstance = undefined; let showTimestamp = (dt) => { let formatDatePart = (part) => { part = part + ""; if (part.length < 2) { part = "0" + part; } return part; } let yearString = dt.getFullYear(); let monthString = formatDatePart(dt.getMonth() + 1); let dateString = formatDatePart(dt.getDate()); let hourString = formatDatePart(dt.getHours()); let minuteString = formatDatePart(dt.getMinutes()); let secondsString = formatDatePart(dt.getSeconds()); divTickerTimestamp.innerHTML = dateString + "/" + monthString + "/" + yearString + " - " + "" + hourString + ":" + minuteString + ":" + secondsString + ""; }; let applyPriceUpdate = () => { try { if (currentPrice === newPrice) { return; } let direction = undefined; if (currentPrice !== undefined) { if (newPrice > currentPrice) { direction = "up"; } else if (newPrice < currentPrice) { direction = "down"; } } currentPrice = newPrice; countUpInstance.update(newPrice); if (direction !== undefined) { divTicker.classList.add("direction-" + direction); setTimeout(() => { divTicker.classList.remove("direction-up"); divTicker.classList.remove("direction-down"); }, 300); } } catch (e) { console.error(e); } }; window.simulatePrice = (price) => { newPrice = price; } let handlePriceTick = (midPriceDecimal) => { const price = new Decimal(16000000).dividedBy(midPriceDecimal); let isFirstPrice = newPrice === undefined; newPrice = price.toFixed(decimals) * 1; if (isFirstPrice) { countUpInstance = new countUp.CountUp("ticker-value", 0, { decimalPlaces: decimals, startVal: 0, duration: 4, useGrouping: true, }); document.getElementById("ticker-container").classList.add("show"); applyPriceUpdate(); setInterval(() => applyPriceUpdate(), 4500); setInterval(() => { showTimestamp(new Date()); }, 1000); } }; let xbtGbpChannel = undefined; let handleWsMessage = (msg) => { try { const data = JSON.parse(msg.data); if (Array.isArray(data)) { if (xbtGbpChannel !== undefined && data[0] === xbtGbpChannel && data[2] === "spread") { const bidString = data[1][0]; const askString = data[1][1]; if (askString && bidString) { const askDecimal = new Decimal(askString); const bidDecimal = new Decimal(bidString); const midDecimal = bidDecimal.plus(askDecimal.minus(bidDecimal).dividedBy(2)); console.log("TICK " + bidString + "/" + askString); handlePriceTick(midDecimal); } } } else if (data.event === "subscriptionStatus" && data.status === "subscribed") { if (data.pair === "XBT/GBP") { xbtGbpChannel = data.channelID; } } } catch(e) { console.error(e); } }; let reconnectWs; reconnectWs = () => { const ws = new WebSocket("wss://ws.kraken.com"); ws.onerror = function(err) { console.error('Socket error: ', err.message, 'Closing socket'); ws.close(); }; ws.onmessage = handleWsMessage; ws.onopen = () => { ws.send(JSON.stringify( { "event": "subscribe", "pair": [ "XBT/GBP" ], "subscription": { "name": "spread" } } )); }; ws.onclose = function(e) { console.log('Socket is closed. Reconnect in 1 second.', e.reason); setTimeout(function() { reconnectWs(); }, 1000); }; }; reconnectWs(); console.log("Init done"); })();