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

# Economic History

> Funding, account activity, and borrow/lend interest streams from the canonical ledger.

## Subscribe

```json theme={null}
{
  "method": "subscribe",
  "subscription": {
    "type": "userFundings",
    "user": "0x1111111111111111111111111111111111111111"
  }
}
```

Use the same subscription object with `method: "unsubscribe"` to stop delivery.
Each stream requires a `0x`-prefixed wallet address; addresses are case insensitive.

| Subscription | Payload array | Canonical ledger types |
| - | - | - |
| `userFundings` | `data.fundings` | `funding` |
| `userNonFundingLedgerUpdates` | `data.nonFundingLedgerUpdates` | `deposit`, `withdrawal`, `rewards`, `split`, `merge`, `redemption` |
| `userBorrowLendInterest` | `data.interest` | `interest` (borrower charges and lender income) |

## Delivery and recovery

The subscription acknowledgment precedes an initial snapshot, including an empty snapshot.
Snapshots contain the latest **100 matching rows**, oldest first. Live messages contain only
new or changed rows, in batches of at most 100. All messages carry `data.user`,
`data.isSnapshot`, and Notional's `data.blockNumber` committed-state watermark.
The snapshot read and publication finish synchronously before live delivery can begin.

Rows use the same projection as [HTTP ledger history](/api-reference/info-endpoints/ledger),
including assigned-market funding, LP accrual journals, and outcome operation state.
Amounts remain decimal strings, timestamps remain Unix milliseconds, and unavailable
accounting metadata remains absent or `null`.

**Upsert by the canonical row's `id`**, an opaque stable string. A terminal withdrawal keeps
the pending withdrawal's `id` even though its `hash` and `time` can change. Outcome operations
also retain their identity through pending, active, reconciliation, and terminal statuses.
Separate rows from one transaction have distinct IDs. Do not deduplicate by timestamp or
transaction hash alone, and do not let an older pending row replace a terminal row.

On reconnect, resubscribe and read HTTP history to recover gaps larger than the snapshot
and lifecycle changes to older rows. A snapshot is a recent window, not a replacement for
complete cached history. The frontend performs this recovery and retains live rows while
HTTP reads finish. Successful HTTP reads refresh nonterminal stream state received before
the request; stream updates received during the request still take precedence. Terminal
receipts remain retained across reconnects, including before the first successful HTTP read.
Cache and subscription identities include the wallet and network.
HTTP remains available for complete retained history and exports.

There is no durable WebSocket replay cursor or exactly-once delivery guarantee. Consumers
must tolerate duplicates and repeated snapshots. Dropped messages at the server's backpressure
limit close the connection so recovery can run. Projection failures also close affected streams.
HTTP history uses bounded timestamp pages (2,000 rows by default); complete recovery and
exports traverse every page with a fixed `endTime`. Each stream seeds its accounting projection
from canonical history, independently of HTTP page limits, then applies newly committed
transactions and journal rows in committed order. Old lifecycle changes and backdated funding
remain deliverable without replaying retained history for every update. A new wallet initializes
its LP replay when its first wallet event arrives. Projection state is disposable: unsubscribe,
restart, or a missed commit requires a fresh snapshot; commit gaps close affected streams.

## Funding envelope

```json theme={null}
{
  "channel": "userFundings",
  "data": {
    "user": "0x1111111111111111111111111111111111111111",
    "isSnapshot": false,
    "blockNumber": 123,
    "fundings": [
      {
        "time": 1792108800000,
        "coin": "BTC",
        "usdc": "-0.01234567",
        "szi": "0.1",
        "fundingRate": "0.00001",
        "ledger": {
          "id": "opaque-projection-row-id",
          "time": 1792108800000,
          "hash": "0xabc",
          "delta": {
            "type": "funding",
            "coin": "BTC",
            "usdc": "-0.01234567",
            "szi": "0.1",
            "rate": "0.00001"
          }
        }
      }
    ]
  }
}
```

Positive `usdc` means funding received; negative means paid. `fundingRate` copies `ledger.delta.rate`
when present and is omitted when unavailable. `ledger` preserves the complete HTTP row.

## Non-funding envelope

`{ "channel": "userNonFundingLedgerUpdates", "data": { "user": "0x...", "isSnapshot": true, "blockNumber": 123, "nonFundingLedgerUpdates": [] } }`

Every array element is a canonical [ledger row](/api-reference/info-endpoints/ledger#response-fields),
including `id`, `hash`, `time`, `delta`, and any `status`, `transfer`, or `outcome` metadata.
Transfers retain native asset units; outcome activity retains exact signed `outcome.assetDeltas`.
Interest is delivered exclusively by `userBorrowLendInterest`.

## Borrow/lend envelope

`{ "channel": "userBorrowLendInterest", "data": { "user": "0x...", "isSnapshot": false, "blockNumber": 123, "interest": [] } }`

Each element contains `time`, `token`, `borrow`, `supply`, and `ledger`. `borrow` is the positive
magnitude of a borrower charge; `supply` is lender interest income. The opposite side is `"0"`.
Both are in `token` units. The signed amount, eligible balance or debt, rate basis, APR, and
accrual interval remain unchanged in `ledger`. pUSD borrower charges stay in pUSD. USDC supplier
distributions classified as rewards remain on the non-funding stream. The canonical projection
does not currently itemize pUSD supplier yield.

## Hyperliquid compatibility

The subscription names, `{ channel, data }` envelopes, `user` and `isSnapshot` fields, and funding
and non-funding array names follow [Hyperliquid's subscription contract](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions).
The `userBorrowLendInterest` name, `interest` array, and `time`/`token`/`borrow`/`supply` fields
were verified against the [official deployed client](https://app.hyperliquid.xyz) on October 16, 2026;
this stream is absent from the published subscription list.

The [testnet client](https://app.hyperliquid-testnet.xyz/assets/config-CSq9fkjd.js) and live testnet
snapshots were also checked on October 17, 2026. All three streams use the same payload array
names above. The observed funding snapshot contained 100 rows ordered oldest first;
non-funding snapshots also arrived oldest first.
The deployed frontend retains 100 funding/interest rows on desktop, 30 on mobile, and 30
non-funding rows. It sorts newest first, resubscribes after reconnect, and merges live funding
ahead of complete HTTP funding history. Notional keeps its existing recent-history display
limit and HTTP fallback, while preserving settled receipts when a read replica lags.

The [testnet trading client](https://app.hyperliquid-testnet.xyz/trade) was rechecked on
October 19, 2026. Its deployed history modules still use these stream selectors, bounded
live history, and separate complete HTTP reads. Notional additionally reconciles mutable
operation statuses and retains terminal receipts as described above.

Notional intentionally adds `blockNumber`, canonical row IDs, and the lossless `ledger` field
on funding and interest entries. Non-funding entries use Notional ledger deltas, including
`withdrawal` rather than Hyperliquid's `withdraw`, pending/failed statuses, and multi-asset
outcome metadata. These describe the user's Notional ledger, including omnibus allocations;
they are not raw events from an individual Hyperliquid account.

Funding and interest entries remain separate canonical legs even when they share a market/token
and timestamp. Notional therefore deduplicates by row `id`, rather than the deployed client's
funding key of coin plus timestamp. Interest `token` uses Notional's canonical ledger asset label,
including pUSD; paid and earned amounts keep their native units and decimal-string precision.

The [official HTTP history contract](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-a-users-funding-history-or-non-funding-ledger-updates)
uses `userFunding` (singular) for funding and `userNonFundingLedgerUpdates` for other activity,
with inclusive millisecond `startTime`/`endTime` bounds. Time-range requests are
[paginated at 500 entries or distinct blocks](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#pagination).
Notional's HTTP recovery and exports use its `ledger` read with `types`, inclusive
`startTime`/`endTime`, `limit`, and the stable row `afterId` boundary. Complete reads keep
one fixed `endTime` while traversing pages and fail if any page is unavailable or incomplete.

The [WebSocket reconnect guidance](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket)
allows recovery from a fresh subscription snapshot or an HTTP history read. Notional uses both
because a bounded snapshot can omit older lifecycle changes. Its existing socket heartbeat
sends `{ "method": "ping" }` and accepts `{ "channel": "pong" }`, matching the
[documented heartbeat protocol](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/timeouts-and-heartbeats).


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