> For the complete documentation index, see [llms.txt](https://docs.hydromancer.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hydromancer.xyz/readme/websocket/prices-data-and-asset-context/allactiveassetctx.md).

# allActiveAssetCtx

Stream all asset contexts in a single batch message. Requires add-on permission.

Every live data message includes both routing identifiers with the same value:

```json
{"type": "allActiveAssetCtx", "channel": "allActiveAssetCtx"}
```

Other payload fields are omitted above. Existing clients may continue routing on either field.

{% hint style="info" %}
New endpoint - this endpoint is not a part of original Hyperliquid API and is added by us for builder convenience.
{% endhint %}

{% hint style="warning" %}

### ⚠️ This is an add-on endpoint - access has to be purchased separately.

{% endhint %}

Instead of subscribing to `activeAssetCtx` per-coin (N separate subscriptions), `allActiveAssetCtx` sends all asset contexts in a single message per snapshot tick (\~1s).

### Subscribe

```json
{
    "type": "subscribe",
    "subscription": {
        "type": "allActiveAssetCtx",
        "dex": "dex_name" // optional, filters by DEX prefix
    }
}
```

`dex` also accepts a list, so several DEXes can be requested in one subscribe:

```json
{
    "type": "subscribe",
    "subscription": {
        "type": "allActiveAssetCtx",
        "dex": ["main", "hyna"]
    }
}
```

### Unsubscribe

```json
{
    "type": "unsubscribe",
    "subscription": {
        "type": "allActiveAssetCtx",
        "dex": "dex_name" // optional; a single DEX or a list to remove those filters
    }
}
```

### Parameters

| Parameter | Required | Description                                                                                                                                                                                                                                                                                                                   |
| --------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `dex`     | No       | Filter by DEX — a single name or a list of names (up to 32 distinct filters per connection). `"main"` returns native coins (BTC, ETH, etc); `"hyperliquid"` is accepted as an alias for it. Other values (e.g. `"hyna"`) return only coins with that prefix (max 6 characters per name). Omit for all coins across all DEXes. |

### Multiple DEXes

DEX filters are **additive**: a connection holds one `allActiveAssetCtx` subscription whose filter set grows with each subscribe and shrinks with each dex-scoped unsubscribe (the same model as per-coin `trades`/`allFills` subscriptions).

* Subscribing to `"main"` and then `"hyna"` results in one message per tick containing both DEXes' coins — the second subscribe **merges** rather than replaces, and the confirmation echoes the merged set (`"dex": ["hyna", "main"]`).
* Subscribing without `dex` switches the subscription to unfiltered (all DEXes), absorbing any active filters. The confirmation carries a `dex_filters_absorbed` warning listing them.
* Subscribing to a DEX that is already covered — either already in the filter set, or while the unfiltered form is active — is accepted as a no-op with a `redundant_dex` warning.
* Unsubscribing with `dex` removes just those DEXes; the subscription ends when the last filter is removed. Unsubscribing without `dex` always clears the whole subscription. A dex-scoped unsubscribe is rejected with an `error` message while the unfiltered form is active (there is no "all DEXes minus one" mode — unsubscribe fully, then resubscribe with an explicit list).
* The merged filter set is capped at **32 distinct DEXes** per connection; a subscribe that would exceed the cap is rejected with an error.
* Subscribing to an unrecognized DEX — a name that is not `"main"` and not on the deployed perp-DEX roster — succeeds, but the confirmation carries an `unknown_dex` warning listing it (the filter starts matching if such a DEX deploys later). When market metadata is temporarily unavailable the code is `market_activity_unavailable` instead, same as the [`l2Book`](/readme/websocket/orderbook-streaming/l2book.md) coin warnings.

Warnings arrive on the `subscriptionUpdate` confirmation:

```json
{
    "type": "subscriptionUpdate",
    "operation": "subscribe",
    "subscription": { "type": "allActiveAssetCtx", "dex": ["hyna", "main"] },
    "subscribed": ["allActiveAssetCtx"],
    "failed": [],
    "warnings": [
        { "code": "redundant_dex", "message": "allActiveAssetCtx already covers dex(es): [\"hyna\"]", "coins": [], "dexes": ["hyna"] }
    ]
}
```

### Message format

One message per snapshot tick containing all matching asset contexts:

```json
{
    "type": "allActiveAssetCtx",
    "channel": "allActiveAssetCtx",
    "seq": 1,
    "cursor": "0",
    "data": {
        "BTC": {
            "oraclePx": "67250.0",
            "markPx": "67248.5",
            "midPx": "67249.25",
            "impactPxs": ["67249.0", "67249.5"],
            "openInterest": "12345.678",
            "dayNtlVlm": "1643278247.97882",
            "dayBaseVlm": "26703.40439"
        },
        "ETH": {
            "oraclePx": "3230.1",
            "markPx": "3227.4",
            "midPx": "3228.25",
            "impactPxs": ["3228.2", "3228.3"],
            "openInterest": "446072.075",
            "dayNtlVlm": "543210987.65432",
            "dayBaseVlm": "157234.21098"
        },
        "hyna:BTC": {
            "oraclePx": "67250.0",
            "markPx": "67251.2",
            "midPx": "67250.6",
            "impactPxs": ["67250.4", "67250.8"],
            "openInterest": "100.5",
            "dayNtlVlm": "8123456.10",
            "dayBaseVlm": "120.85"
        }
    }
}
```

The `data` field is a map from coin name to asset context. `impactPxs` contains the average execution price to trade impact notional (20k$ for BTC/ETH, 6k$ for others) on bid and ask.

When using the `dex` filter, only matching coins are included. For example, `"dex": "main"` would return only `BTC` and `ETH` from the above, while `"dex": "hyna"` would return only `hyna:BTC`.

### Examples

{% tabs %}
{% tab title="Javascript" %}

```javascript
const WebSocket = require('ws');

const ws = new WebSocket(`wss://api.hydromancer.xyz/ws?token=${process.env.HYDROMANCER_API_KEY}`);

ws.on('message', (data) => {
    const msg = JSON.parse(data);

    if (msg.type === 'connected') {
        ws.send(JSON.stringify({
            type: 'subscribe',
            subscription: {
                type: 'allActiveAssetCtx'
            }
        }));
    } else if (msg.type === 'ping') {
        ws.send(JSON.stringify({ type: 'pong' }));
    } else if (msg.type === 'allActiveAssetCtx') {
        const coins = Object.keys(msg.data);
        console.log(`Received ${coins.length} asset contexts`);
        // Access individual coin data:
        if (msg.data['BTC']) {
            console.log(`BTC mark: ${msg.data['BTC'].markPx}`);
        }
    }
});
```

{% endtab %}

{% tab title="Python" %}

```python
import websocket
import json
import os

def on_message(ws, message):
    msg = json.loads(message)

    if msg.get('type') == 'connected':
        ws.send(json.dumps({
            "type": "subscribe",
            "subscription": {
                "type": "allActiveAssetCtx"
            }
        }))
    elif msg.get('type') == 'ping':
        ws.send(json.dumps({'type': 'pong'}))
    elif msg.get('type') == 'allActiveAssetCtx':
        data = msg['data']
        print(f"Received {len(data)} asset contexts")
        if 'BTC' in data:
            print(f"BTC mark: {data['BTC']['markPx']}")
    elif msg.get('type') == 'error':
        print(f"Error: {msg}")

ws = websocket.WebSocketApp(
    f"wss://api.hydromancer.xyz/ws?token={os.environ.get('HYDROMANCER_API_KEY')}",
    on_message=on_message
)
ws.run_forever()
```

{% endtab %}
{% endtabs %}

#### Error messages:

```
{
    "type": "error",
    "message": "Invalid API key"
}
```

#### Common errors

1. ```
   Rate limit exceeded - allActiveAssetCtx requires add-on permission
   ```
2. ```
   Connection timeout - Respond to ping messages
   ```
3. ```
   Invalid API key
   ```
