Real-Time Multi-Exchange Order Book Depth for an ERC-20 Token
This tutorial shows how to build a small Node.js app that streams real-time order book updates for the same ERC-20 token across multiple exchanges using the CoinAPI Market Data WebSocket.
By the end, the app will:
- connect to the WebSocket feed
- subscribe to
bookupdates for one token pair across several exchanges - maintain the latest order book for each symbol in memory
- handle both full snapshots and incremental updates
- display:
- top of book per exchange
- aggregated top of book across exchanges
- aggregated top 5 bid and ask levels
This is useful for demos involving:
- liquidity comparison across venues
- synthetic aggregated depth
- exchange filtering
- cross-venue monitoring for the same asset
In the stream, some messages provide a full snapshot of the current book, while others contain only updates to specific levels. For example, your GATEIO sample is a snapshot with is_snapshot: true, sequence: 1, and a full set of bid and ask levels for GATEIO_SPOT_LINK_USDT.
What you will build
For this tutorial, the app will subscribe to these symbols:
GATEIO_SPOT_LINK_USDTBINANCE_SPOT_LINK_USDTOKEX_SPOT_LINK_USDTBYBITSPOT_SPOT_LINK_USDT
You can replace them later with other ERC-20 USDT symbols if needed.
How book messages are handled
Each incoming book message belongs to one symbol_id.
There are two message types to handle:
Snapshot message
When is_snapshot is true:
- clear the stored bids and asks for that symbol
- insert all levels from the message
- store the sequence number
Incremental update
When is_snapshot is false:
- keep the existing stored book
- update only the price levels present in the message
- remove a price level if its incoming
sizeis0 - store the new sequence number
This lets the application maintain the latest book state for each symbol over time.
Prerequisites
You need:
- Node.js installed
- a CoinAPI API key
- terminal access
This tutorial uses the Market Data WebSocket endpoint:
Step 1 — Create the project folder
Open your terminal and run:
Step 2 — Create package.json
Create a new file named package.json and paste this into it:
Save the file.
Step 3 — Install dependencies
Run:
This installs:
wsfor the WebSocket clientdotenvfor loading your API key from a.envfile
Step 4 — Create .env
Create a new file named .env and paste this into it:
Replace YOUR_API_KEY_HERE with your actual API key, then save the file.
Step 5 — Create index.js
Create a new file named index.js and paste the full script below.
Save the file.
Step 6 — Run the script
Run:
Step 7 — What happens when the script runs
The script will:
- connect to the Market Data WebSocket
- subscribe to the configured symbols
- receive
bookmessages in real time - rebuild the latest order book for each symbol in memory
- print:
- top of book per exchange
- aggregated best bid and best ask
- aggregated top 5 bids and asks
If file logging is enabled, it will also append periodic snapshots to orderbook_snapshots.jsonl.
Step 8 — Sample terminal output
Because this is live data, your output will differ. A sample output might look like this:
Step 9 — Where the data comes from
You do not need to copy JSON into files manually.
The script receives live messages directly from the WebSocket stream in this handler:
Those messages are processed in memory as they arrive.
Step 10 — Where the data is saved
There are two outputs:
Terminal output
The latest view is printed in the terminal continuously.
Optional file output
If SAVE_SNAPSHOTS_TO_FILE is set to true, the script also saves snapshots to:
Each line in that file is a JSON object.
If you do not want file output, change:
to:
Step 11 — How to stop the script
The script runs continuously because it listens to a live WebSocket stream.
To stop it, press:
Step 13 — Change the symbols later
To test a different ERC-20 asset, edit this block in index.js:
For example, to use UNI instead:
Then save the file and run.
Step 14 — Change which exchanges are included in aggregation
To exclude an exchange from the aggregated output, edit this line:
For example:
This will keep the script subscribed to all configured symbols, but the aggregated output will only include the exchanges listed here.
Step 15 — Troubleshooting
Missing API key
If you see:
check that:
- the file name is
.env - the key is written as
COINAPI_KEY=... - the file is saved
No book output appears
Possible reasons:
- one or more symbol IDs are not active
- the symbols are not covered in your environment
- there have not been recent updates yet
Try a different base asset such as UNI or CRV.
A side of the book looks empty
This can happen briefly at startup before both sides have been initialized for all symbols. Once snapshot and update messages arrive, the book should fill in.
Old values overwrite new ones
This script avoids that by checking the sequence number and ignoring older or duplicate messages.
See It in Action
Below is a short example of the script running with two exchanges.
This shows how order book updates arrive in real time and how the aggregated view updates continuously.
Note: For demonstration purposes, the video uses 2 symbols only to keep updates readable.
Congratulations!
You now have a working, real-time, multi-exchange order book depth application.
In this tutorial, you were able to:
- connect to the CoinAPI Market Data WebSocket
- subscribe to live
bookupdates across multiple exchanges - handle both snapshot and incremental messages correctly
- maintain a continuously updated order book in memory per symbol
- compute and display top-of-book per exchange
- build an aggregated view of bid/ask depth across venues
- optionally persist snapshots for further analysis
This setup reflects how real-world systems consume and process streaming market data. Instead of relying on static responses, your application continuously updates its state based on incoming events, allowing you to monitor liquidity and pricing across exchanges in real time.
From here, you can extend this further by:
- visualizing depth with charts
- tracking spread differences across exchanges
- detecting arbitrage opportunities
- estimating slippage for different trade sizes
- storing historical snapshots in a database
You now have a solid foundation for building more advanced market data applications on top of real-time streams.