# 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
   ```


---

# 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.hydromancer.xyz/readme/websocket/usernonfundingledgerevents.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.
