# Whale Position Updates

The **POSITION\_UPDATE** feed broadcasts every buy/sell transaction enriched with position data: current holdings, bag percentage, supply percentage and SOL tracking.

> This feed covers **Whale wallets** only. For KOL wallets use `wss://kolstream.cabalspy.xyz`, for Smart Money wallets use `wss://smartstream.cabalspy.xyz`.

***

### Connection

javascript

```javascript
const ws = new WebSocket("wss://whalestream.cabalspy.xyz?apiKey=YOUR_API_KEY");
```

***

### Subscriptions

You must subscribe before receiving any events.

#### Subscribe to a specific token

javascript

```javascript
ws.send(JSON.stringify({ type: "subscribe", token: "MINT_ADDRESS" }));
```

#### Subscribe to all tokens

javascript

```javascript
ws.send(JSON.stringify({ type: "subscribe", token: "*" }));
```

#### Unsubscribe

javascript

```javascript
ws.send(JSON.stringify({ type: "unsubscribe", token: "MINT_ADDRESS" }));
```

#### List active subscriptions

javascript

```javascript
ws.send(JSON.stringify({ type: "subscriptions" }));
```

***

### Connection Flow

javascript

```javascript
const ws = new WebSocket("wss://whalestream.cabalspy.xyz?apiKey=YOUR_API_KEY");

ws.onopen = () => {
  ws.send(JSON.stringify({ type: "subscribe", token: "*" }));
};

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);

  switch (message.type) {
    case "connected":     console.log("Connected");              break;
    case "subscribed":    console.log("Subscribed:", message.token); break;
    case "unsubscribed":  console.log("Unsubscribed:", message.token); break;
    case "position_update": console.log("Trade:", message);      break;
    case "error":         console.error("Error:", message.message); break;
  }
};
```

***

### System Messages

| type            | When                       | Fields                              |
| --------------- | -------------------------- | ----------------------------------- |
| `connected`     | On successful connect      | `message`, `docs`                   |
| `subscribed`    | After subscribe            | `token`, `subscriptions`, `message` |
| `unsubscribed`  | After unsubscribe          | `token`, `subscriptions`, `message` |
| `subscriptions` | After requesting list      | `subscriptions`, `count`            |
| `error`         | On invalid message or auth | `message`                           |

***

### Example Message — position\_update

json

```json
{
  "type": "position_update",
  "signature": "5fX9kJ...zABC123",
  "slot": 289145678,
  "timestamp": 1740404242,
  "blockchain": "solana",
  "action": "buy",
  "transaction_type": "buy",

  "wallet": "9WzDXmQ...8kQA",
  "wallet_name": "Whale",
  "wallet_image": "https://cabalspy.xyz/images/WhaleCoin.png",
  "telegram": null,
  "twitter": null,
  "wallet_data": {
    "name": "Whale",
    "wallet_address": "9WzDXmQ...8kQA",
    "telegram": null,
    "twitter": null,
    "image_url": "https://cabalspy.xyz/images/WhaleCoin.png"
  },

  "sol_value": 15.00,
  "sol_value_raw": 15000000000,
  "sol_value_usd": 2250.00,
  "sol_price_usd": 150.00,
  "sol_value_peak": 15.00,
  "sol_value_current": 15.00,

  "fee": 5000,
  "fee_sol": 0.000005,
  "fee_payer": "9WzDXmQ...8kQA",

  "mint": "pumpABC...xyz123",
  "symbol": "MOON",
  "token_name": "Moon Token",
  "token_logo": "https://...",
  "token_decimals": 6,
  "token_supply": 1000000000,
  "token_amount": 50000000,

  "held": 50000000,
  "peak": 50000000,
  "supply_pct": 5.0000,
  "bag_pct": 100.00,
  "prev_supply_pct": 0.0000,
  "prev_bag_pct": 0.00,
  "delta_supply_pct": 5.0000,
  "delta_bag_pct": 100.00,
  "delta_held": 50000000,
  "used_fallback": false
}
```

***

### Field Reference

#### Transaction

| Field              | Type   | Description                               |
| ------------------ | ------ | ----------------------------------------- |
| `type`             | string | Always `"position_update"`                |
| `signature`        | string | Solana transaction signature              |
| `slot`             | number | Solana slot number                        |
| `timestamp`        | number | Unix timestamp                            |
| `blockchain`       | string | Always `"solana"`                         |
| `action`           | string | `"buy"` or `"sell"`                       |
| `transaction_type` | string | Same as `action` — kept for compatibility |

#### Wallet

| Field          | Type    | Description                                    |
| -------------- | ------- | ---------------------------------------------- |
| `wallet`       | string  | Public key of the trading wallet               |
| `wallet_name`  | string? | Label for this wallet (defaults to `"Whale"`)  |
| `wallet_image` | string? | Profile picture URL                            |
| `telegram`     | string? | Telegram link if available                     |
| `twitter`      | string? | Twitter/X profile URL if available             |
| `wallet_data`  | object  | Full wallet object containing all fields above |

#### SOL

| Field               | Type   | Description                                           |
| ------------------- | ------ | ----------------------------------------------------- |
| `sol_value`         | number | SOL amount of this transaction                        |
| `sol_value_raw`     | number | SOL amount in Lamports                                |
| `sol_value_usd`     | number | USD value of this transaction                         |
| `sol_price_usd`     | number | SOL price in USD at time of broadcast                 |
| `sol_value_peak`    | number | Total SOL ever spent buying this token by this wallet |
| `sol_value_current` | number | Remaining unrealized SOL value in this position       |

#### Fees

| Field       | Type   | Description                 |
| ----------- | ------ | --------------------------- |
| `fee`       | number | Transaction fee in Lamports |
| `fee_sol`   | number | Transaction fee in SOL      |
| `fee_payer` | string | Wallet that paid the fee    |

#### Token

| Field            | Type    | Description                                          |
| ---------------- | ------- | ---------------------------------------------------- |
| `mint`           | string  | Token mint address                                   |
| `symbol`         | string  | Token ticker e.g. `"BONK"`                           |
| `token_name`     | string? | Full token name                                      |
| `token_logo`     | string? | Token logo URL                                       |
| `token_decimals` | number  | Token decimal places                                 |
| `token_supply`   | number  | Total on-chain token supply                          |
| `token_amount`   | number  | Amount of tokens traded in this specific transaction |

#### Position

| Field              | Type    | Description                                                            |
| ------------------ | ------- | ---------------------------------------------------------------------- |
| `held`             | number  | Current token balance of this wallet for this mint                     |
| `peak`             | number  | All-time highest token balance this wallet held                        |
| `bag_pct`          | number  | How much of the peak position is still held (0–100%)                   |
| `supply_pct`       | number  | Percentage of total supply currently held                              |
| `prev_supply_pct`  | number  | Supply % before this transaction                                       |
| `prev_bag_pct`     | number  | Bag % before this transaction                                          |
| `delta_supply_pct` | number  | Change in supply % from this transaction                               |
| `delta_bag_pct`    | number  | Change in bag % from this transaction                                  |
| `delta_held`       | number  | Change in token amount from this transaction                           |
| `used_fallback`    | boolean | `true` if supply was estimated (1B fallback) instead of on-chain value |

***

### Errors

json

```json
{ "type": "error", "message": "Invalid or missing API key" }
{ "type": "error", "message": "Unknown type: xyz. Valid: subscribe, unsubscribe, subscriptions" }
{ "type": "error", "message": "Invalid JSON message" }
```

***

### Notes

* You must subscribe before receiving any events.
* Use `"token": "*"` to receive all events across all tracked tokens.
* `token_supply` falls back to `1,000,000,000` if on-chain value is unavailable. Check `used_fallback: true`.
* `bag_pct` = `held / peak * 100`. A value of `0%` means the position was fully closed.
* `token_amount` = tokens traded in this transaction. `held` = cumulative position.
* Whale wallets typically have limited social data — `telegram` and `twitter` are often `null`.
