# Kana Perps Python Websocket API

### **Important Note:**

For all the Websocket endpoints below, pass your profile address.

To track your transactions on-chain (e.g., via **Aptos Explorer** or **Aptos Scan**), you must use your **profile address**, as all on-chain trades are executed using this profile address.

To obtain your profile address, use the `/getProfileAddress` endpoint and provide your wallet address as the `userAddress` parameter.

### How to Fetch the Profile Address:

**Example endpoint:**\
<https://perps-tradeapi.kanalabs.io/getProfileAddress?userAddress=0xd01e3a233632a41463bd6d289e99e69e1b50815c7afff710e1c992659a8722f3>\
\
**Example code:**\
[https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-python-rest-api#id-20.-](https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-typescript-rest-api#id-19.-update-stop-loss)get-profile-address

### Testnet Supported Markets

<table data-header-hidden><thead><tr><th></th><th width="282"></th><th></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td><td><strong>Description</strong></td></tr><tr><td>APT-USD</td><td>1338</td><td>Aptos-based trading market.</td></tr><tr><td>BTC-USD</td><td>1339</td><td>Bitcoin-based trading market.</td></tr><tr><td>ETH-USD</td><td>1340</td><td>Ethereum-based trading market.</td></tr><tr><td>SOL-USD</td><td>2387</td><td>Solana-based trading market.</td></tr></tbody></table>

### Mainnet Supported Markets

<table data-header-hidden><thead><tr><th></th><th width="282"></th><th></th></tr></thead><tbody><tr><td><strong>Asset</strong></td><td><strong>Market ID</strong></td><td><strong>Description</strong></td></tr><tr><td>APT-USD</td><td>14</td><td>Aptos-based trading market.</td></tr><tr><td>BTC-USD</td><td>15</td><td>Bitcoin-based trading market.</td></tr><tr><td>ETH-USD</td><td>16</td><td>Ethereum-based trading market.</td></tr><tr><td>SOL-USD</td><td>31</td><td>Solana-based trading market.</td></tr></tbody></table>

**WebSocket URL:**

### ✅ <mark style="color:red;">**Testnet WebSocket URL**</mark>

```typescript
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

### ✅ <mark style="color:red;">**Mainnet WebSocket URL**</mark>

```typescript
wss://perpetuals-indexer-ws.kana.trade/ws/
```

### **Important Note: Profile Address Required**

🔹 You **must** pass your **profile address** for WebSocket endpoints.\
🔹 To get your **profile address**, use the `/getProfileAddress` endpoint.

#### **Profile Address API:**

&#x20;**Endpoint:**

```
https://perps-tradeapi.kanalabs.io/getProfileAddress
```

**Example Request:**

```
https://perps-tradeapi.kanalabs.io/getProfileAddress?userAddress=0xd01e3a233632a41463bd6d289e99e69e1b50815c7afff710e1c992659a8722f3
```

&#x20;**Input Parameter:**

* `userAddress` (your wallet address)

&#x20;**Response Example:**

```typescript
{
  success: true,
  message: 'Profile address fetched successfully',
  data: '0x3c78886aa67752706b3502b12959edf92e68d85ae64b24226783d26ce6efc1e'
}
```

#### WebSocket Client Documentation

**Installation:**

1. **Install Dependencies**: You will need the `websocket-client` library. Install it using pip:

```python
pip install websocket-client
```

### 1. WebSocket Client for Subscribing to Position Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "positions",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is `positions` in this case.
* **address**: The address to track for position updates.

**Example Response:**

After subscribing, you will receive position updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "positions", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","entry_price":"6050","is_long":false,"last_updated":"1739788459","leverage":2,"liq_price":"8853.658536585366","margin":"3025000","market_id":"396","size":"1000","sl":null,"tp":null,"trade_id":"16509835945970048696716","value":"6050000"}],"message":"positions"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to position updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'positions',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 2. WebSocket Client for Subscribing to Order Fills Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "trade_history",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is trade\_history in this case.
* **address**: The address to track for order fills updates.

**Example Response:**

After subscribing, you will receive order fills updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "trade_history", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","fee":"3025","last_updated":"1739788459","market_id":"396","order_type":2,"pnl":"0","price":"6050","size":"1000","timestamp":"1739788459","trade_id":"16509835945970048696716"},"message":"trade_history"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to order fills updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'trade_history',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 3. WebSocket Client for Subscribing to Open Orders Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "open_orders",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is open\_orders in this case.
* **address**: The address to track for open orders updates.

**Example Response:**

After subscribing, you will receive open orders updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "open_orders", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[],"message":"open_orders"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","last_updated":"1739790733","leverage":2,"market_id":"396","order_id":"12907057702855018828273522","order_type":1,"order_value":"6002000","price":"6002","remaining_size":"1000","timestamp":"1739790733","total_size":"1000","trade_id":"16528282690043758248332"}],"message":"open_orders"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to open orders updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'open_orders',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 4. WebSocket Client for Subscribing to Order history Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "order_history",
  "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"
}
```

* **topic**: The topic to subscribe to, which is order\_history in this case.
* **address**: The address to track for order history updates.

**Example Response:**

After subscribing, you will receive order history updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "order_history", "address": "0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770"}
[client] Received message: {"data":[{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","is_market_order":false,"last_updated":"1739790733","leverage":2,"market_id":"396","order_id":"12907057702855018828273522","order_type":1,"order_value":"6002000","price":"6002","size":"1000","status":"Open","timestamp":"1739790733","trade_id":"16528282690043758248332"},{"address":"0x4d6dc68e391e86991e58ab4d548b7e92872430d1f51bc666fe0c206bad7ff770","is_market_order":false,"last_updated":"1739790700","leverage":2,"market_id":"396","order_id":"12906965467445688751095808","order_type":4,"order_value":"6002000","price":"6002","size":"1000","status":"Filled","timestamp":"1739790700","trade_id":"16509835945970048696716"}],"message":"order_history"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to order history updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
address = 'your_address'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'order_history',
        'address': address,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 5. WebSocket Client for Subscribing to Order Book Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "orderbook",
  "market_id": "1338"
}
```

* **topic**: The topic to subscribe to, which is orderbook in this case.
* **address**: The address to track for order book updates.

**Example Response:**

After subscribing, you will receive order book updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "orderbook", "market_id": "1338"}
[client] Received message: {"data":[{"is_ask":true,"last_updated":"1739790988","market_id":"396","price":"6036","size":"169320"},{"is_ask":true,"last_updated":"1739790988","market_id":"396","price":"6037","size":"253735"},{"is_ask":true,"last_updated":"1739790988","market_id":"396","price":"6040","size":"230485"},{"is_ask":true,"last_updated":"1739790996","market_id":"396","price":"6044","size":"255685"},{"is_ask":true,"last_updated":"1739790996","market_id":"396","price":"6051","size":"264082"},{"is_ask":true,"last_updated":"1739790990","market_id":"396","price":"6053","size":"235088"},{"is_ask":true,"last_updated":"1739790996","market_id":"396","price":"6057","size":"230868"},{"is_ask":true,"last_updated":"1739790990","market_id":"396","price":"6059","size":"487477"},{"is_ask":true,"last_updated":"1739758360","market_id":"396","price":"8000","size":"500"},{"is_ask":false,"last_updated":"1739790988","market_id":"396","price":"6031","size":"174998"},{"is_ask":false,"last_updated":"1739790988","market_id":"396","price":"6027","size":"225183"},{"is_ask":false,"last_updated":"1739790988","market_id":"396","price":"6024","size":"244770"},{"is_ask":false,"last_updated":"1739790996","market_id":"396","price":"6019","size":"238312"},{"is_ask":false,"last_updated":"1739790987","market_id":"396","price":"6018","size":"260393"},{"is_ask":false,"last_updated":"1739790996","market_id":"396","price":"6014","size":"267821"},{"is_ask":false,"last_updated":"1739790996","market_id":"396","price":"6011","size":"234869"},{"is_ask":false,"last_updated":"1739790990","market_id":"396","price":"6006","size":"447877"},{"is_ask":false,"last_updated":"1739790990","market_id":"396","price":"6002","size":"1000"},{"is_ask":false,"last_updated":"1739779575","market_id":"396","price":"5800","size":"103303"}],"message":"orderbook"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to order book updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
market_id= 'your_market_id'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'orderbook',
        'market_id': market_id,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()    

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 6. WebSocket Client for Subscribing to Recent Trades Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "recent_trades",
  "market_id": "1338"
}
```

* **topic**: The topic to subscribe to, which is recent\_trades in this case.
* **address**: The address to track for recent trades updates.

**Example Response:**

After subscribing, you will receive recent trades updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "recent_trades", "market_id": "1338"}
[client] Received message: {"data":[{"address":"0x73e73911c0771e4d58f17aea3d0c70980ca2bae32c665b37101d1a18f4ef60f1","fee":"0","last_updated":1746177751,"leverage":2,"market_id":"1338","order_type":1,"order_value":"65.393818","pnl":"0","price":"5.518","size":"11.851","timestamp":1746177750,"trade_id":"176590681017621537621306","transaction_version":6704413443},{"address":"0x85a0d7c3e1f5e243b80055b249d6e4cc4b2db5f599fa7a27b05850af8eccffdd","fee":"0.0326969090000000006806411505","last_updated":1746177751,"leverage":2,"market_id":"1338","order_type":7,"order_value":"65.393818","pnl":"-0.0682499090000000006806411505","price":"5.518","size":"11.851","timestamp":1746177750,"trade_id":"176609127761695247172922","transaction_version":6704413443}]}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to recent trades updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/'

# Address to subscribe to
market_id= '1338'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'recent_trades',
        'market_id': market_id,
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()    

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```

### 7. WebSocket Client for Subscribing to Live Funding Rate Updates

**WebSocket URL:**

```
wss://perpetuals-indexer-ws-develop.kanalabs.io/ws/
```

**Example Request:**

When you connect to the WebSocket server, the client will send a subscription message like this:

```json
{
  "topic": "live_funding_rate"
}
```

* **topic**: The topic to subscribe to, which is live\_funding\_rate in this case.

**Example Response:**

After subscribing, you will receive live funding rate updates as a response from the server. The response might look like this:

{% code fullWidth="false" %}

```json
[client] Connected to the server
[client] Sent subscription request: {"topic": "live_funding_rate"}
[client] Received message: {"data":[{"funding_rate":"0","funding_timestamp":0,"last_updated":1747382402,"market_id":"14","transaction_timestamp":1747382400,"transaction_version":2726355750},{"funding_rate":"0","funding_timestamp":0,"last_updated":1747382402,"market_id":"16","transaction_timestamp":1747382400,"transaction_version":2726355754},{"funding_rate":"0","funding_timestamp":0,"last_updated":1747382402,"market_id":"15","transaction_timestamp":1747382400,"transaction_version":2726355752}],"message":"live_funding_rate"}
```

{% endcode %}

#### Example Code to Connect to the WebSocket and Subscribe:

Here’s a Python script that demonstrates how to connect to the WebSocket server and subscribe to live funding rate updates for a specific address.

```python
import websocket
import json
import time
import threading

# WebSocket server URL
WS_URL = 'wss://perpetuals-indexer-ws.kana.trade/ws/'

# Global WebSocket variable
ws = None

# WebSocket event handlers
def on_open(ws):
    print('[client] Connected to the server')
    
    # Send subscription message to the WebSocket server
    subscription_message = json.dumps({
        'topic': 'live_funding_rate',
    })
    ws.send(subscription_message)
    print(f'[client] Sent subscription request: {subscription_message}')

    # Start ping thread to keep the connection alive
    start_ping_thread(ws)

def ping(ws):
    while ws.sock and ws.sock.connected:
        time.sleep(20)  # Send ping every 20 seconds
        try:
            ws.sock.ping()
            print('[client] Sent ping to keep connection alive')
        except Exception as e:
            print(f'[client] Error sending ping: {e}')
            break

def start_ping_thread(ws):
    ping_thread = threading.Thread(target=ping, args=(ws,))
    ping_thread.daemon = True
    ping_thread.start()

def on_message(ws, message):
    print(f'[client] Received message: {message}')

def on_pong(ws, message):
    print('[client] Received pong response')

def on_close(ws, close_status_code, close_msg):
    print('[client] Disconnected from the server')
    reconnect_websocket()

def on_error(ws, error):
    print(f'[client] WebSocket error: {error}')
    ws.close()

# WebSocket connection setup
def connect_websocket():
    global ws
    ws = websocket.WebSocketApp(WS_URL,
                                on_open=on_open,
                                on_message=on_message,
                                on_pong=on_pong,
                                on_close=on_close,
                                on_error=on_error)

    # Run the WebSocket connection
    ws.run_forever()

# Reconnect logic
def reconnect_websocket():
    print('[client] Attempting to reconnect...')
    time.sleep(5)
    connect_websocket()    

# Start WebSocket connection
if __name__ == "__main__":
    connect_websocket()
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.kanalabs.io/perpetual-futures/kana-perps/api-docs/kana-perps-python-websocket-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
