> 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/usernonfundingledgerevents.md).

# userNonFundingLedgerEvents

### Subscribe

```
{ 
    "type": "subscribe",
    "subscription": {
        "type": "userNonFundingLedgerEvents",
        "addresses": ["0x574bafce69d9411f662a433896e74e4f153096fa"],
        "dex": "dex_name", // this is optional to filter by dex leave this field out for all events
        "addStakingEvents": bool // optional false by default
    }
} 
```

### Unsubscribe

```
{ 
    "type": "unsubscribe",
    "subscription": {
        "type": "userNonFundingLedgerEvents",
        "addresses": ["0x574bafce69d9411f662a433896e74e4f153096fa"],
        "dex": "dex_name", // this is optional to filter by dex leave this field out for all events
        "addStakingEvents": bool // optional false by default
    }
}
```

### userNonFundingLedgerEvents data format

{% hint style="info" %}
**Reconnection Note:** When reconnecting with a session, replay and live events may overlap. Deduplicate using `(time, txIndex, role)` - skip events where this tuple is at or before your last processed event. See [Session Management](/readme/websocket/session-management-and-reconnection.md#deduplication) for details.
{% endhint %}

Each ledger event represents a balance change from a specific user's perspective. Key fields:

* **user**: The primary address this event affects (always matches one of your subscribed addresses)
* **role**: The user's role in the event:
  * `"user"` - Single-party events (deposits, withdrawals, account class transfers, liquidations)
  * `"sender"` - User is sending funds to another party
  * `"receiver"` - User is receiving funds from another party
* **counterparty**: The other address involved in transfers (only present for bilateral transactions)
* **counterpartyDex**: The DEX/chain of the counterparty (omitted when "hyperliquid")

**Important:** For transfers, you only receive the perspective where `user` matches your subscribed address. For example, if Alice sends funds to Bob and you're subscribed to Alice, you receive the sender perspective with Alice as `user` and Bob as `counterparty`. You do NOT receive Bob's receiver perspective unless you're also subscribed to Bob's address.

Each event contains a timestamp, hash, and delta fields describing the ledger change. Events are batched per block.

<pre class="language-json"><code class="lang-json">{
  "type": "userNonFundingLedgerEvents",
  "seq": 1,
  "cursor": "500:1704067200000:3",
  "events": [
    {
     "time": "1704067200000",
     "hash": "0xabc123...",
     "eventType": "SpotTransfer",
     "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
     "counterparty": "0x123456...",
     "role": "sender",
     "amount": "1000.0",
     "token": "USDC",
     "usdcValue": "1000.0",
     "fee": "1.5",
     "feeToken": "USDC",
     "nativeTokenFee": "0.1",
     "nonce": 12345
<strong>    }
</strong>  ]
}
</code></pre>

### 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') {
        // Subscribe to ledger events
        ws.send(JSON.stringify({
            type: 'subscribe',
            subscription: {
                type: 'userNonFundingLedgerEvents',
                addresses: ["0x574bafce69d9411f662a433896e74e4f153096fa"]
            }
        }));
    } else if (msg.type === 'ping') {
        ws.send(JSON.stringify({ type: 'pong' }));
    } else if (msg.type === 'userNonFundingLedgerEvents') {
        console.log(`Received ${msg}`);
    }
});
```

{% endtab %}

{% tab title="Python" %}

```python
import websocket
import json
import os

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

    if msg['type'] == 'connected':
        ws.send(json.dumps({
            "type": "subscribe",
            "subscription": {
                "type": "userNonFundingLedgerEvents",
                "addresses": ["0x574bafce69d9411f662a433896e74e4f153096fa"]
            }
        }))
    elif msg['type'] == 'ping':
        print("Received ping, sending pong")
        ws.send(json.dumps({'type': 'pong'}))
    elif msg['type'] == 'userNonFundingLedgerEvents':
        print(f"Received {msg}")
    elif msg['type'] == 'subscriptionUpdate':
        print(f"Subscription update: {msg}")
    elif msg['type'] == 'error':
        print(f"Error: {msg}")
    else:
        print(f"Unknown message type: {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 %}

<details>

<summary>All possible ledger event types</summary>

**spotTransfer**

```json
{
    "time": "1704067200000",
    "hash": "0xabc123...",
    "eventType": "SpotTransfer",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "counterparty": "0x123456...",
    "role": "sender",
    "amount": "1000.0",
    "token": "USDC",
    "usdcValue": "1000.0",
    "fee": "1.5",
    "feeToken": "USDC",
    "nativeTokenFee": "0.1",
    "nonce": 12345
}
```

**accountClassTransfer**

```json
{
    "time": "1704067200000",
    "hash": "0xdddeeef...",
    "eventType": "AccountClassTransfer",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "userDex": "hyperliquid",
    "role": "user",
    "amount": "1500.0",
    "toPerp": true
}
```

**withdraw**

```json
{
    "time": "1704067200000",
    "hash": "0xbbbccc...",
    "eventType": "Withdraw",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "userDex": "hyperliquid",
    "role": "user",
    "amount": "2000.0",
    "fee": "5.0",
    "nonce": 12347
}
```

**deposit**

```json
{
    "time": "1704067200000",
    "hash": "0x999aaa...",
    "eventType": "Deposit",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "userDex": "hyperliquid",
    "role": "user",
    "amount": "5000.0",
    "isDeposit": true
}
```

**vaultCreate**

```json
{
    "time": "1704067200000",
    "hash": "0xfff111...",
    "eventType": "VaultCreate",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "counterparty": "0xvault123...",
    "role": "sender",
    "vault": "0xvault123...",
    "amount": "10000.0",
    "fee": "10.0"
 }
```

**vaultDeposit**

```json
  {
    "time": "1704067200000",
    "hash": "0x222333...",
    "eventType": "VaultDeposit",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "counterparty": "0xvault123...",
    "role": "sender",
    "vault": "0xvault123...",
    "amount": "5000.0"
  }
```

**vaultWithdraw**

```json
{
    "time": "1704067200000",
    "hash": "0x444555...",
    "eventType": "VaultWithdraw",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "counterparty": "0xvault123...",
    "role": "receiver",
    "vault": "0xvault123...",
    "requestedUsd": "3000.0",
    "commission": "50.0",
    "closingCost": "100.0",
    "basis": "2900.0",
    "netWithdrawnUsd": "2850.0"
  }
```

**vaultDistribution**

```json
  {
    "time": "1704067200000",
    "hash": "0x666777...",
    "eventType": "VaultDistribution",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "counterparty": "0xvault123...",
    "role": "receiver",
    "vault": "0xvault123...",
    "amount": "500.0"
  }
```

**vaultLeaderCommission**

```json
  {
    "time": "1704067200000",
    "hash": "0x888999...",
    "eventType": "VaultLeaderCommission",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "role": "user",
    "amount": "100.0"
  }
```

**liquidation**

```json
  {
    "time": "1704067200000",
    "hash": "0xaaabbb...",
    "eventType": "Liquidation",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "role": "user",
    "liquidatedNtl": "50000.0",
    "accountValue": "45000.0",
    "leverageType": "cross",
    "liquidatedPositions": [
      ["BTC", "0.5"],
      ["ETH", "10.0"]
    ]
  }
```

**internalTransfer**

```json
{
    "time": "1704067200000",
    "hash": "0x111222...",
    "eventType": "InternalTransfer",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "counterparty": "0x333444...",
    "role": "sender",
    "amount": "250.0",
    "fee": "0.5"
 }
```

**subAccountTransfer**

```json
{
    "time": "1704067200000",
    "hash": "0x555666...",
    "eventType": "SubAccountTransfer",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "counterparty": "0x777888...",
    "role": "sender",
    "amount": "100.0"
 }
```

**rewardsClaim**

```json
{
    "time": "1704067200000",
    "hash": "0x111222...",
    "eventType": "RewardsClaim",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "role": "user",
    "amount": "50.0"
}
```

**accountActivationGas**

```json
{
    "time": "1704067200000",
    "hash": "0xeeefff...",
    "eventType": "AccountActivationGas",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "role": "user",
    "amount": "0.001",
    "token": "ETH"
  }
```

**deployGasAuction**

```json
  {
    "time": "1704067200000",
    "hash": "0x555666...",
    "eventType": "DeployGasAuction",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "userDex": "hyperliquid",
    "role": "user",
    "amount": "0.5",
    "token": "ETH"
  }
```

**cStakingTransfer**

```json
  {
    "time": "1704067200000",
    "hash": "0x333444...",
    "eventType": "CStakingTransfer",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "userDex": "hyperliquid",
    "role": "user",
    "amount": "1000.0",
    "token": "USDC",
    "isDeposit": true
  }
```

**spotGenesis**

```json
  {
    "time": "1704067200000",
    "hash": "0xcccdddd...",
    "eventType": "SpotGenesis",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "userDex": "hyperliquid",
    "role": "user",
    "amount": "1000000.0",
    "token": "USDC"
  }
```

**send**

```json
  {
    "time": "1704067200000",
    "hash": "0xdef456...",
    "eventType": "Send",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "userDex": "hyperliquid",
    "counterparty": "0x789abc...",
    "counterpartyDex": "vertex",
    "role": "sender",
    "amount": "500.0",
    "token": "USDC",
    "usdcValue": "500.0",
    "fee": "2.0",
    "feeToken": "USDC",
    "nativeTokenFee": "0.05",
    "nonce": 12346
  }
```

**perpDexClassTransfer**

```json
{
    "time": "1704067200000",
    "hash": "0xaaa111...",
    "eventType": "PerpDexClassTransfer",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "role": "user",
    "amount": "1000.0",
    "token": "USDC",
    "dex": "hyperliquid",
    "toPerp": true
}
```

**activateDexAbstraction**

```json
{
    "time": "1704067200000",
    "hash": "0xbbb222...",
    "eventType": "ActivateDexAbstraction",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "role": "user",
    "dex": "hyperliquid",
    "token": "USDC",
    "amount": "10.0"
}
```

**borrowLend**

```json
{
    "time": "1704067200000",
    "hash": "0xccc333...",
    "eventType": "BorrowLend",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "role": "user",
    "token": "USDC",
    "operation": "deposit",
    "amount": "5000.0",
    "interestAmount": "12.5"
}
```

**borrowLendBackstopLiquidation**

```json
{
    "time": "1704067200000",
    "hash": "0xddd444...",
    "eventType": "BorrowLendBackstopLiquidation",
    "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
    "role": "user",
    "token": "USDC",
    "balanceChange": "-500.0"
}
```

**If addStakingEvents is true also includes**

**Delegation**

```json
  {
    "time": "1704067200000",
    "hash": "0xbbbccc...",
    "eventType": "Delegation",
    "user": "0xa101544878fbf89a7393d44acceafa70820aa809",
    "validator": "0x5e8e92e7bebe1b69b975b4aeee57b09a04d1783b",
    "amount": "202.09235863",
    "currency": "USDC",
    "isUndelegate": true
  }
```

**cDeposit**

```json
  {
    "time": "1704067200000",
    "hash": "0x777888...",
    "eventType": "CDeposit",
    "user": "0x037d8cef56de0f70f7870d4d9dd41974efa9f94b",
    "amount": "0.079789",
    "currency": "USDC"
  }
```

**cWithdrawal**

```json
  {
    "time": "1704067200000",
    "hash": "0x999aaa...",
    "eventType": "CWithdrawal",
    "user": "0x426c3dad1de7e4b6fde4ee1d2daefb0589612c22",
    "amount": "50.0",
    "currency": "USDC",
    "isFinalized": false
  }
```

</details>

#### Error messages:

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

#### Common errors

1. ```
   Connection timeout - Respond to ping messages
   ```
2. ```
   Too many subscriptions - Maximum addresses exceeded
   ```
3. ```
   Invalid address format - Use valid Ethereum addresses
   ```
4. ```
   Invalid API key
   ```
