> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kuru.io/llms.txt
> Use this file to discover all available pages before exploring further.

# User balances stream

> Follow replayable balance updates with periodic full snapshots.

```text theme={null}
userBalances@f[@<coalesceMs>]
```

This user-scoped stream uses `(feedEpoch, globalUserSeq)`. Without `seq`, it
sends a complete finalized balance snapshot, replays retained updates after
that snapshot, and then joins live delivery. It also sends a complete snapshot
every five seconds by default. Incremental updates default to a `300`
millisecond coalescing duration.

## Subscribe

```json theme={null}
{"op":"sub","id":7,"t":"userBalances@f@300","u":2,"feedEpoch":0,"seq":2951}
```

## Decoded event

The shape below is the inner `message` returned by `decodeExchangeWsEnvelope`
or `decodeExchangeWsMessage`. Every binary socket message also carries an outer
`id: bigint`, matching your subscription ID. Use it to route snapshots, replay,
and live updates. See [binary subscription envelopes](/api/exchange/websocket#binary-subscription-envelope).

```ts theme={null}
interface ExchangeWsUserBalancesFrameBase {
  wireVersion: 1;
  feedEpoch: bigint;
  view: "finalized";
  kind: "userBalances";
  userId: bigint;
  globalUserSeq: bigint | null;
  globalSeq: bigint | null;
  previousGlobalUserSeq: bigint | null;
  balances: Array<{
    tokenAddress: string;
    freeBalance: bigint;
    reservedBalance: bigint;
  }>;
}

type ExchangeWsUserBalancesFrame =
  | (ExchangeWsUserBalancesFrameBase & {
      snapshot: true;
      stateHead: { blockNumber: bigint; blockId: string } | null;
    })
  | (ExchangeWsUserBalancesFrameBase & {
      snapshot: false;
      sourceBlock: { blockNumber: bigint; blockId: string };
    });
```

Balance values use each token's native decimal units. A snapshot has
`stateHead`; an incremental frame has `sourceBlock`. Replace local balance
state when `snapshot=true`.

For an explicit replay cut `R`, accept the first publication when
`globalUserSeq > R` and `previousGlobalUserSeq` is `null` or at most `R`.
After that sparse bridge, every subsequent `previousGlobalUserSeq` must equal
the last accepted `globalUserSeq` exactly.


## AsyncAPI

````yaml api/exchange/asyncapi.yaml userBalances
id: userBalances
title: Subscribe to user balances
description: Follow replayable balance updates with periodic full snapshots.
servers:
  - id: mainnet
    protocol: wss
    host: gateway.mainnet.kuru.io
    bindings: []
    variables: []
  - id: testnet
    protocol: wss
    host: gateway.testnet.kuru.io
    bindings: []
    variables: []
address: /ws
parameters: []
bindings: []
operations:
  - &ref_1
    id: subscribeUserBalances
    title: Subscribe user balances
    type: receive
    messages:
      - &ref_2
        id: request
        contentType: application/json
        payload:
          - name: userBalances@f subscription
            type: object
            properties:
              - name: op
                type: string
                enumValues:
                  - sub
                required: true
              - name: id
                type: integer
                description: >-
                  JSON integer restricted to JavaScript's exact safe-integer
                  range.
                required: true
              - name: t
                type: string
                required: true
              - name: u
                type: integer
                description: Numeric Kuru user ID.
                required: true
              - name: feedEpoch
                type: integer
                description: Feed namespace. Required when seq is supplied.
                required: false
              - name: seq
                type: integer
                required: false
        headers: []
        jsonPayloadSchema:
          type: object
          additionalProperties: false
          required:
            - op
            - id
            - t
            - u
          allOf:
            - if:
                required:
                  - seq
                x-parser-schema-id: <anonymous-schema-56>
              then:
                required:
                  - feedEpoch
                x-parser-schema-id: <anonymous-schema-57>
              x-parser-schema-id: <anonymous-schema-55>
          properties:
            op:
              type: string
              enum:
                - sub
              x-parser-schema-id: <anonymous-schema-53>
            id: &ref_0
              type: integer
              minimum: 0
              maximum: 9007199254740991
              description: >-
                JSON integer restricted to JavaScript's exact safe-integer
                range.
              x-parser-schema-id: ControlInteger
            t:
              type: string
              pattern: ^userBalances@f(@[1-9][0-9]*)?$
              x-parser-schema-id: <anonymous-schema-54>
            u:
              allOf:
                - *ref_0
              description: Numeric Kuru user ID.
              x-parser-schema-id: UserId
            feedEpoch:
              allOf:
                - *ref_0
              description: Feed namespace. Required when seq is supplied.
              x-parser-schema-id: FeedEpoch
            seq:
              allOf:
                - *ref_0
              minimum: 1
              x-parser-schema-id: ReplaySequence
          x-parser-schema-id: UserBalancesSubscription
        title: userBalances@f subscription
        example: |-
          {
            "op": "sub",
            "id": 7,
            "t": "userBalances@f@300",
            "u": 2,
            "feedEpoch": 0,
            "seq": 2951
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: request
    bindings: []
    extensions:
      - id: x-parser-unique-object-id
        value: userBalances
sendOperations:
  - *ref_1
receiveOperations: []
sendMessages:
  - *ref_2
receiveMessages: []
extensions:
  - id: x-parser-unique-object-id
    value: userBalances
securitySchemes: []

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.