# Code Snippets

These minimal examples connect and subscribe to native WebSocket streams. Add reconnection, validation, and error handling before you use them in production.

The examples use testnet hosts. For mainnet, replace `api.meridiantest.net` with `api.meridian.xyz` and `ws.meridiantest.net` with `ws.meridian.xyz`. See [API Hosts](/protocol-reference/api-hosts).

:::info
The Python SDK provides WebSocket subscription helpers. See the [Python SDK](/developer-guides/trading-api/sdk#python-sdk).
:::

## WebSocket Examples

This example uses the `ws` TypeScript library.

```typescript
import WebSocket from 'ws'

const API_URL = 'https://api.meridiantest.net/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://ws.meridiantest.net/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()
```

This Rust example uses `tungstenite` to listen to selected streams.

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

const BASE_URL: &str = "https://api.meridiantest.net/v1";
const WS_URL: &str = "wss://ws.meridiantest.net/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,
            _ => {}
        }
    }
}
```
