Ethereal Docs
  • Introduction
    • What is Ethereal?
  • Public Testnet
  • Trading
    • Perpetual Futures
      • Margining
      • Order Types
      • Positions
      • Funding Rates
      • Market Specifications
      • Liquidations
      • Auto Deleveraging
      • Subaccounts
      • Price Oracles
  • Points
    • Staking sENA
    • Season Zero
  • developer-guides
    • Trading API
      • Quick Start
      • Message Signing
      • Accounts & Signers
      • Order Placement
      • System Limits
      • Products
      • Token Transfers
      • Supported Tokens
      • Websocket Gateway
    • Python SDK
  • Protocol Reference
    • API Hosts
    • Contracts
    • Audits
Powered by GitBook
On this page
  • Overview
  • Socket.IO
  • Subscription Streams
  • Subscribe
  • Unsubscribing
  • An example ws-subscription.ts script
  1. developer-guides
  2. Trading API

Websocket Gateway

Overview

The gateway ws subscription allow users to listen to data streams in real-time data, delivering instant trading updates directly from the Ethereal exchange platform. To interact with the subscription gateway API, send websocket messages after connecting to wss://ws.etherealtest.net/v1/stream.

Socket.IO

Ethereal uses Socket.IO, a library that extends the standard WebSocket protocol. Socket.IO provides ready-made client libraries in multiple languages with automatic reconnection handling and built-in ping/pong frames to maintain stable connections, saving developers from implementing these basic features themselves.

Refer to Socket.IO for language specific client implementations.

The team is evaluating a transition from SocketIO to native WebSockets for enhanced performance. While this change may be implemented soon, the interface is expected to remain consistent, however, the connection string and namespace will likely be updated.

If you are using the Python SDK, the transition should be seamless aside from a future upgrade requirement.

Subscription Streams

Subscribe

The WebSocket gateway offers the following subscription streams:

BOOK_DEPTH - Provides order book depth updates for a specific product

{
  type: "BookDepth",
  productId: string
}
{
  "timestamp": number,
  "previousTimestamp": number,
  "productId": string,
  "asks": [[price: string, quantity: string]],
  "bids": [[price: string, quantity: string]]
}
  • BookDepth events are emitted on a configurable fixed interval (currently configured to be once every 100ms).

  • previousTimestamp is in milliseconds and represents the last time the BookDepth emitted

  • timestamp also in milliseconds and the system timestamp of when this BookDepthwas emitted. Using both the previousTimestamp and timestamp you can infer whether or not any events were missed during connection or during consumption.

  • asks an array of price/quantity tuples representing asks.

  • bids an array of price/quantity tuples representing bids.

  • A BookDepth of the current book is also emitted back on initial connection.

MARKET_PRICE - Delivers real-time market price updates for a specified product

{
  type: "MarketPrice",
  productId: string
}
  • MarketPrice events are emitted on a configurable fixed interval (currently configured to be once every 1000ms).

Refer to response type of /v1/product/market-price (except as a single object without dataas this only ws only supports subscription to a single product).

ORDER_FILL - Notifies when orders are filled for a specific subaccount

{
  type: "OrderFill",
  subaccountId: string
}
  • OrderFill events are emitted in real-time.

Refer to the response type of /v1/order/fill (without pagination properties)

ORDER_UPDATE - Provides updates about order status changes for a specific subaccount

{
  type: "OrderUpdate",
  subaccountId: string
}
  • OrderUpdate events are emitted in real-time.

Refer to the response type of /v1/order/{id}

SUBACCOUNT_LIQUIDATION - Provides an update when a subaccount is liquidated

{
  type: "SubaccountLiquidation",
  subaccountId: string
}
{
  subaccountId: string,
  liquidatedAt: number
}
  • SubaccountLiquidation events are emitted in real-time.

  • subaccountId the subaccount that has been liquidated.

  • liquidatedAt the time (in ms, since the Unix epoch) when the liquidation occurred.

TOKEN_TRANSFER - Updates on token transfers (deposits/withdrawals) for a specific subaccount

{
  type: "TokenTransfer",
  subaccountId: string
}
  • TokenTransfer events are emitted in real-time.

Refer to the response type of /v1/token/transfer (without pagination properties)

Each subscription requires specific parameters as shown in the format above. To subscribe to these streams, emit a 'subscribe' event to the socket with the appropriate subscription message.

During connection establishment ensure websocket is the only configured transport (transports: ['websocket']).

Unsubscribing

To stop receiving data from a previously established subscription, you can unsubscribe using the same payload format as your original subscription. Simply emit an unsubscribe event to the socket with the identical payload structure you used when subscribing.

An example ws-subscription.ts script

import { io } from 'socket.io-client';
import axios from 'axios';
import { getEtherealTestnetAPI } from './generated/api.sdk';

axios.defaults.baseURL = 'https://api.etherealtest.net';
const api = getEtherealTestnetAPI(); // Generated SDK using Orval

const getProducts = async () => {
  const res = await api.productControllerList();
  return res.data.data;
};

const main = async () => {
  const url = 'wss://ws.etherealtest.net/v1/stream';
  const ws = io(url, { transports: ['websocket'], autoConnect: false });
  console.log(`Connecting to ws gateway ${url}`);

  ws.on('connect', async () => {
    console.log(`Connected to ${url}`);

    const products = await getProducts();

    products.forEach((product) => {
      const bookDepthSubscriptionMessage = {
        type: 'BookDepth',
        productId: product.id,
      };
      ws.emit('subscribe', bookDepthSubscriptionMessage);
      console.log(`Subscribed BookDepth:${product.id}`);

      const marketPriceSubscriptionMessage = {
        type: 'MarketPrice',
        productId: product.id,
      };
      ws.emit('subscribe', marketPriceSubscriptionMessage);
      console.log(`Subscribed MarketPrice:${product.id}`);
    });
  });

  ws.on('connecting', () => console.log('Attempting connection...'));
  ws.on('disconnect', () => console.log('Disconnected'));
  ws.on('error', (err) => console.log('Error encountered', err));
  ws.on('exception', (err) => console.log('Caught exception', err));
  ws.on('reconnect_attempt', () => console.log('Attempting to reconnect...'));

  // --- Subscription stream handlers --- //

  ws.on('BookDepth', async (message) => console.log(`[BookDepth] Received ${message}`));
  ws.on('MarketPrice', async (message) => console.log(`[MarketPrice] Received ${message}`));

  // Explicitly connect to ws stream _after_ binding message callbacks.
  ws.connect();
};

void main();

For Python developers, our Python SDK offers a streamlined approach to WebSocket subscriptions Refer to the Python SDK documentation for more information.

PreviousSupported TokensNextPython SDK

Last updated 3 days ago

Page cover image