# Socket.io (deprecated)

Ethereal uses [Socket.io](https://socket.io/docs/v4/), 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](https://socket.io/docs/v4/#client-implementations) for language specific client implementations.

{% hint style="warning" %}
Socket.io **has now been replaced with native web sockets and will be removed in a future release**. Ensure you transition to using native websockets to prevent any disruptions in the future.
{% endhint %}

{% hint style="success" %}
**Migration** *Native* WebSockets will be available on testnet first for integrators to test and provide feedback. After mainnet release, both Socket.io and native WebSockets will remain available for a transition period to allow a smooth migration without disruption.
{% endhint %}

<table><thead><tr><th width="370.79296875">URL</th><th>Status</th></tr></thead><tbody><tr><td><code>wss://ws.ethereal.trade/v1/stream</code></td><td>Live - Soon to be deprecated</td></tr></tbody></table>

### WebSockets

Ethereal also offers WebSocket support, which communicates with plain JSON payloads, resulting in lower latency, reduced overhead, and smaller message sizes. This makes it well-suited for latency-sensitive integrations and lightweight clients that don't need the built-in reconnections provided by Socket.io.

Websockets support a subset of the Socket.io feeds. If you require additional data streams, use the Socket.io gateway above which supports the full set of subscription types.

## `Socket.io` Subscription Streams

### Subscribe

The WebSocket gateway offers the following subscription streams:

**`BOOK_DEPTH`** - Provides order book depth updates for a specific product.

{% code expandable="true" %}

```json
// Subscription message payload
{
  "type": "BookDepth",
  "productId": "<uuid>"
}

// Response message
{
  "timestamp": "<epoch>",
  "previousTimestamp": "<epoch>",
  "productId": "<uuid>",
  "asks": [[price: string, quantity: string]],
  "bids": [[price: string, quantity: string]],
  "t": "<epoch>"
}
```

{% endcode %}

* `BookDepth` events are emitted on a configurable fixed interval (as of writing, this is configured to be **once every 200ms**)
* `previousTimestamp` is in milliseconds and represents the last time the `BookDepth` emitted
* `timestamp` also in milliseconds and the system timestamp of when this `BookDepth`was 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
* `t` represents server time when response was published (epoch in miliseconds)

{% hint style="warning" %}
A `BookDepth` message of the current book **(up to 100 price levels per side)** is emitted back on initial connection. Every subsequent message is a price level diff with absolute quantities. A zero quantity price diff indicates that this level has been removed.
{% endhint %}

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

{% code expandable="true" %}

```json
// Subscription message payload
{
  "type": "MarketPrice",
  "productId": "<uuid>"
}

// Response message (same as `/v1/product/market-price`)
// @see: https://api.ethereal.trade/docs#/Product/ProductController_getMarketPrice
{
  "productId": "<uuid>",
  "bestBidPrice": numberString,
  "bestAskPrice": numberString,
  "oraclePrice": numberString,
  "price24hAgo": numberString,
  "t": "<epoch>"
}
```

{% endcode %}

* `MarketPrice` events are emitted on a configurable fixed interval (currently configured to be **once every second**)
* `t` represents server time when response was published (epoch in miliseconds)

**`ORDER_FILL`** - Notifies when orders are filled for a specific subaccount.

{% code expandable="true" %}

```json
// Subscription message payload
{
  "type": "OrderFill",
  "subaccountId": "<uuid>"
}

// Response message (same as `/v1/order/fill`)
// @see: https://api.ethereal.trade/docs#/Order/OrderController_listFillsBySubaccountId
{
  "data": [
      {
        "id": "<uuid>",
        "orderId": "<uuid>",
        "clientOrderId": "string",
        "price": numberString,
        "filled": numberString,
        "type": "LIMIT|MARKET",
        "side": 0|1,
        "reduceOnly": boolean,
        "feeUsd": numberString,
        "isMaker": boolean,
        "productId": "<uuid>",
        "subaccountId": "<uuid>",
        "createdAt": "<epoch>"
      }
    ],
  "t": "<epoch>"
}
```

{% endcode %}

* `OrderFill` events are emitted in real-time as they occur
* `t` represents server time when response was published (epoch in miliseconds)

**`TRADE_FILL`** - Provides a stream of trades that have occurred filtered by product.

{% code expandable="true" %}

```json
// Subscription message payload
{
  "type": "TradeFill",
  "productId": "<uuid>"
}

// Response message
{
  "data": [
    {
      "id": "<uuid>",
      "price": numberString,
      "filled": numberString,
      "takerSide": 0|1,
      "createdAt": "<epoch>"
    }
  ],
  "productId": "<uuid>",
  "t": "<epoch>"
}
```

{% endcode %}

* `TradeFill` events are emitted in real-time as they occur
* `t` represents server time when response was published (epoch in miliseconds)
* Similar to `OrderFill`, an array of trade fills will be emitted in a single message, grouped by the product they were traded on

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

{% code expandable="true" %}

```json
// Subscription message payload
{
  "type": "OrderUpdate",
  "subaccountId": "<uuid>"
}

// Response message (same as `/v1/order`)
// @see https://api.ethereal.trade/docs#/Order/OrderController_listBySubaccountId
{
  "data": [
    {
      "id": "<uuid>",
      "clientOrderId": "string",
      "type": "LIMIT"|"MARKET",
      "availableQuantity": numberString,
      "quantity": numberString,
      "side": 0|1,
      "productId": "<uuid>",
      "subaccountId": "<uuid>",
      "status": "<status>",
      "reduceOnly": boolean,
      "close": booleanue,
      "updatedAt": "<epoch>",
      "createdAt": "<epoch>",
      "sender": "<address>",
      "price": numberString,
      "filled": numberString,
      "stopPrice": numberString,
      "stopType": "<stopType>",
      "stopPriceType": "<stopPriceType>",
      "timeInForce": "<tif>",
      "expiresAt": "<epochInSeconds>",
      "postOnly": boolean,
      "groupContingencyType": "<groupContingencyType>",
      "groupId": "<uuid>"
    }
  ],
  "t": "<epoch>"
}

```

{% endcode %}

* `OrderUpdate` events are emitted in real-time
* `t` represents server time when response was published (epoch in miliseconds)

{% hint style="warning" %}
Only the latest update processed is emitted and intermediary states are omitted.
{% endhint %}

**`SUBACCOUNT_LIQUIDATION`** - Provides an update when a subaccount is liquidated.

{% code expandable="true" %}

```json
// Subscription message payload
{
  "type": "SubaccountLiquidation",
  "subaccountId": "<uuid>"
}

// Response message
{
  "subaccountId": "<uuid>",
  "liquidatedAt": "<epoch>",
  "t": "<epoch>"
}
```

{% endcode %}

* `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
* `t` represents server time when response was published (epoch in miliseconds)

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

{% code expandable="true" %}

```json
// Subscription message payload
{
  "type": "TokenTransfer",
  "subaccountId": "<uuid>"
}

// Response message (same as `/v1/token/transfer` with pagination)
// @see https://api.ethereal.trade/docs#/Token/TokenController_listTransfers
{
  "id": "<uuid>",
  "initiatedBlockNumber": numberString,
  "finalizedBlockNumber": numberString,
  "status": "<status>",
  "subaccountId": "<uuid>",
  "tokenName": "string",
  "tokenAddress": "<address>",
  "type": "WITHDRAW"|"DEPOSIT",
  "amount": numberString,
  "lzDestinationAddress": "<address>",
  "lzDestinationEid": number,
  "fee": numberString,
  "createdAt": "<epoch>",
  "initiatedTransactionHash": "<hex>",
  "finalizedTransactionHash": "<hex>",
  "t": "<epoch>"
}
```

{% endcode %}

* &#x20;`t` represents server time when response was published (epoch in miliseconds)

{% hint style="success" %}
*Each subscription requires specific parameters as shown in the formats above. To subscribe to these streams, emit a 'subscribe' event to the socket with the appropriate subscription message.*
{% endhint %}

{% hint style="warning" %}
During connection establishment ensure `websocket` is the only configured transport (i.e. `transports: ['websocket']`).
{% endhint %}

### Unsubscribe

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.

### Handling `Socket.io` Exceptions

Exceptions are exposed in its own event aptly named "*exception*". Exceptions follow the following shape:

```typescript
{
  pattern: 'order:dryRun',
  status: 'BadRequest',
  error: {
    message: [
      'subaccount is not a valid subaccount',
    ]
  }
}
```

* `pattern` indicates the source event pattern if available e.g. "subscribe"&#x20;
* `status` the error status
* `error` general body of the error its shape changes depending on the status
