# Code Snippets

Below are minimal examples demonstrating how to connect and subscribe to native WebSocket streams. These snippets are intended as starting points for integration and are not production-ready.

:::info
For Python developers, the Python SDK offers a streamlined approach to WebSocket subscriptions. Refer to the [Python SDK](/developer-guides/trading-api/sdk#official-sdk) documentation for more information.
:::

## WebSocket Examples

Below is an example using the `ws` TypeScript library.

```typescript
import WebSocket from 'ws'

const API_URL = 'https://api.ethereal.trade/v1'

type Product = {
  id: string
  ticker: string
}

type ProductResponse = {
  data: Product[]
}

const getProducts = async () => {
  const res = await fetch(`${API_URL}/product`)
  if (!res.ok) throw new Error(`Failed to fetch products: ${res.status}`)

  const body = (await res.json()) as ProductResponse
  return body.data
}

const main = async () => {
  const url = 'wss://ws2.ethereal.trade/v1/stream'
  const ws = new WebSocket(url)
  console.log(`Connecting to ws gateway ${url}`)

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

    const products = await getProducts()

    products.forEach((product) => {
      const l2BookSubscriptionMessage = {
        event: 'subscribe',
        data: { type: 'L2Book', symbol: product.ticker }
      }
      ws.send(JSON.stringify(l2BookSubscriptionMessage))
      console.log(`Subscribed L2Book:${product.ticker}`)

      const tickerSubscriptionMessage = {
        event: 'subscribe',
        data: { type: 'Ticker', symbol: product.ticker }
      }
      ws.send(JSON.stringify(tickerSubscriptionMessage))
      console.log(`Subscribed Ticker:${product.ticker}`)
    })
  })

  ws.on('close', () => console.log('Disconnected'))
  ws.on('error', (err) => console.log('Error encountered', err))

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

  ws.on('message', (data) => {
    const message = JSON.parse(data.toString())
    switch (message.e) {
      case 'L2Book':
        console.log(`[L2Book] Received ${data.toString()}`)
        break
      case 'Ticker':
        console.log(`[Ticker] Received ${data.toString()}`)
        break
    }
  })
}

void main()
```

Another example using Rust with `tungstenite` to listen on a few feeds.

```rust
use futures_util::{SinkExt, StreamExt};
use serde::{Deserialize, Serialize};
use tokio_tungstenite::{connect_async, tungstenite::Message};

const BASE_URL: &str = "https://api.ethereal.trade/v1";
const WS_URL: &str = "wss://ws2.ethereal.trade/v1/stream";

#[derive(Debug, Deserialize)]
struct ProductPage {
    data: Vec<Product>,
}

#[derive(Debug, Deserialize)]
struct Product {
    ticker: String,
}

#[derive(Serialize)]
struct WsMessage {
    event: &'static str,
    data: SubscriptionData,
}

#[derive(Serialize)]
struct SubscriptionData {
    r#type: &'static str,
    symbol: String,
}

async fn get_products() -> Vec<Product> {
    let url = format!("{}/product", BASE_URL);
    reqwest::get(&url)
        .await
        .unwrap()
        .json::<ProductPage>()
        .await
        .unwrap()
        .data
}

fn subscribe_msg(kind: &'static str, symbol: String) -> Message {
    let msg = WsMessage {
        event: "subscribe",
        data: SubscriptionData {
            r#type: kind,
            symbol,
        },
    };
    Message::Text(serde_json::to_string(&msg).unwrap().into())
}

#[tokio::main]
async fn main() {
    let products = get_products().await;

    let (ws_stream, _) = connect_async(WS_URL).await.unwrap();
    let (mut write, mut read) = ws_stream.split();

    for p in &products {
        for kind in ["L2Book", "Ticker"] {
            write
                .send(subscribe_msg(kind, p.ticker.clone()))
                .await
                .unwrap();
            println!("Subscribed {kind}:{}", p.ticker);
        }
    }

    while let Some(Ok(msg)) = read.next().await {
        match msg {
            Message::Text(text) => println!("{text}"),
            Message::Ping(data) => {
                let _ = write.send(Message::Pong(data)).await;
            }
            Message::Close(_) => break,
            _ => {}
        }
    }
}
```
