In building web applications, the underlying communication architecture plays a vital role in determining the effectiveness of its functionalities. WebSocket is a TCP/IP communication protocol that allows for a consistent bidirectional(two-way )exchange between the client and the server.
This is in stark contrast to the traditional HTTP protocol that allows for a oneway call and response to the server, there are use cases for certain solutions where data on the server side changes rapidly, for these changes to be appropriately reflected, repeated calls to the server has to be made. This method clearly proves to be inefficient in cases that require fast-changing data such as live video streaming, stock, cryptocurrency trading, etc, WebSocket is the best technology to be implemented.
To demonstrate this, we'll implement the WebSocket API to build a real-time Cryptocurrency Tracker. For real-time data around the prices of certain cryptocurrencies, we would be using the Binance WebSocket API.
Single Currency Example
After initiating the basic variables, we use the WebSocket address to create the connection, the onmessage function listens for a message event which is then parsed to get our price property.
Here is the code sample to get the price stream for ETH to USD
//Web socket ethusd stream
let ws= new WebSocket('wss://stream.binance.com:9443/ws/ethusdt@trade');
let ethUsdt= document.getElementById('eth');
let lastPrice = null;
let price= null;
//Recieves a message event and parses it as a JSON object
ws.onmessage= (event) =>{
let eventData = JSON.parse(event.data);
price=parseFloat(eventData.p).toFixed(2); //parses the price property and rounds it up to two decimal places
ethUsdt.innerText=price;
}
Here it is implemented on Codepen
What of scenarios were we are watching for multiple currencies? From the Binance API guide, the WebSocket address will take this form,
wss://stream.binance.us:9443/stream?streams=<streamName1>/<streamName2>/<streamName3>
where each stream represents a currency pair.
Full Dashboard Integration
We will use a dashboard template to display the price stream for Bitcoin, Ethereum, Ripple, and Litecoin.
The WebSocket connection now streams in the message events for the various currency pairs, we'll create conditions to assign the proper currency events to their respective price variables.
//Binance multicurrency stream
let ws= new WebSocket('wss://stream.binance.com/stream?streams=ethusdt@trade/btcusdt@trade/xrpusdt@trade/ltcusdt@trade');
// we intialize the variables to hold our prices
let ethUsdt= document.getElementById('eth');
let lastPrice = null;
let btcUsdt= document.getElementById('btc');
let btclastPrice = null;
let xrpUsdt= document.getElementById('xrp');
let xrplastPrice = null;
let ltcUsdt= document.getElementById('ltc');
let ltclastPrice = null;
let price= null;
let btcprice= null;
let xrpprice= null;
let ltcprice= null;
let collection = document.getElementsByClassName("bi");
//Recieves a message event and parses it as a JSON object
ws.onmessage= (event) =>{
let eventData = JSON.parse(event.data);
// these conditions assigns the various currency prices based on the currency pair
if (eventData.stream=='ethusdt@trade'){
price=parseFloat(eventData.data.p).toFixed(2);
}
else if(eventData.stream=='btcusdt@trade'){
btcprice=parseFloat(eventData.data.p).toFixed(2);
}
else if(eventData.stream=='xrpusdt@trade'){
xrpprice=parseFloat(eventData.data.p).toFixed(3);
}
else if(eventData.stream=='ltcusdt@trade'){
ltcprice=parseFloat(eventData.data.p).toFixed(2);
}
ethUsdt.innerText=price;
For monitoring the changing prices on the dashboard, we'll use Font Awesome caret up and down icons to give visual indicators about whether the value of the prices is going up or down, an element whose classes are dynamically changed will be used for this purpose.
<div class="row m-t-25">
<div class="col-lg-3">
<div class="card currency-card-rounded">
<div class="card-body rounded bitcoin">
<div class="currency-card--icon pull-right">
<i class="cc BTC-alt" title="BTC"></i>
</div>
<h4>Bitcoin</h4>
<h2>
$<span id="btc">1.765</span> <i class="bi "></i>
</h2>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="card currency-card-rounded">
<div class="card-body rounded ethereum">
<div class="currency-card--icon pull-right">
<i class="cc ETH-alt" title="ETH"></i>
</div>
<h4>Ethereum</h4>
<h2>
$<span id="eth">1.765</span> <i class="bi "></i>
</h2>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="card currency-card-rounded">
<div class="card-body rounded ripple">
<div class="currency-card--icon pull-right">
<i class="cc XRP-alt" title="XRP"></i>
</div>
<h4>Ripple</h4>
<h2>
$<span id="xrp">1.765</span> <i class="bi "></i>
</h2>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="card currency-card-rounded">
<div class="card-body rounded litecoin">
<div class="currency-card--icon pull-right">
<i class="cc LTC-alt" title="LTC"></i>
</div>
<h4>Litecoin</h4>
<h2>
$<span id="ltc">1.765</span> <i class="bi "></i>
</h2>
</div>
</div>
</div>
</div>
We'll then include the rest of the Javascript code that allows for this functionality.
// let ws= new WebSocket('wss://stream.binance.com:9443/ws/ethusdt@trade');
let ws= new WebSocket('wss://stream.binance.com/stream?streams=ethusdt@trade/btcusdt@trade/xrpusdt@trade/ltcusdt@trade');
let ethUsdt= document.getElementById('eth');
let lastPrice = null;
let btcUsdt= document.getElementById('btc');
let btclastPrice = null;
let xrpUsdt= document.getElementById('xrp');
let xrplastPrice = null;
let ltcUsdt= document.getElementById('ltc');
let ltclastPrice = null;
let price= null;
let btcprice= null;
let xrpprice= null;
let ltcprice= null;
let collection = document.getElementsByClassName("bi"); //holds the array of <i> elements
ws.onmessage= (event) =>{
let eventData = JSON.parse(event.data);
if (eventData.stream=='ethusdt@trade'){
price=parseFloat(eventData.data.p).toFixed(2);
}
else if(eventData.stream=='btcusdt@trade'){
btcprice=parseFloat(eventData.data.p).toFixed(2);
}
else if(eventData.stream=='xrpusdt@trade'){
xrpprice=parseFloat(eventData.data.p).toFixed(3);
}
else if(eventData.stream=='ltcusdt@trade'){
ltcprice=parseFloat(eventData.data.p).toFixed(2);
}
ethUsdt.innerText=price;
// conditions to add the caret icons
if (price>lastPrice){
collection[0].classList.remove("bi-caret-down-fill");
collection[0].classList.add( "bi-caret-up-fill" );
collection[0].style.color='green';
}
else if (price<lastPrice){
collection[0].classList.remove("bi-caret-up-fill");
collection[0].classList.add( "bi-caret-down-fill" );
collection[0].style.color='red';
}
lastPrice=price; // after the conditons are fulfilled the value of the lastprice is changed to the current price
btcUsdt.innerText=btcprice;
if (btcprice>btclastPrice){
collection[1].classList.remove("bi-caret-down-fill");
collection[1].classList.add( "bi-caret-up-fill" );
collection[1].style.color='green';
}
else if (btcprice<btclastPrice){
collection[1].classList.remove("bi-caret-up-fill");
collection[1].classList.add( "bi-caret-down-fill" );
collection[1].style.color='red';
}
btclastPrice=btcprice;
xrpUsdt.innerText=xrpprice;
if (xrpprice>xrplastPrice){
collection[2].classList.remove("bi-caret-down-fill");
collection[2].classList.add( "bi-caret-up-fill" );
collection[2].style.color='green';
}
else if (xrpprice<xrplastPrice){
collection[2].classList.remove("bi-caret-up-fill");
collection[2].classList.add( "bi-caret-down-fill" );
collection[2].style.color='red';
}
xrplastPrice=xrpprice;
ltcUsdt.innerText=ltcprice;
if (ltcprice>ltclastPrice){
collection[3].classList.remove("bi-caret-down-fill");
collection[3].classList.add( "bi-caret-up-fill" );
collection[3].style.color='green';
}
else if (ltcprice<ltclastPrice){
collection[3].classList.remove("bi-caret-up-fill");
collection[3].classList.add( "bi-caret-down-fill" );
collection[3].style.color='red';
}
ltclastPrice=ltcprice;
}
And voila! we have our real-time dashboard, the link to the full code is in this repo
Awesome! We have demonstrated the practical use of WebSockets in building a real-time cryptocurrency dashboard, what project ideas do you have that this technology will prove to be valuable? Let me know in the comments section.
Top comments (0)