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

# Folio (Portfolio)

> Understanding account portfolios, balances, and the folio key/value structure

# Folio

A **folio** is a real-time snapshot of a sub-account's portfolio — wallet balances, DeFi positions, market data, and operational state — represented as flat key/value string pairs.

## When to use it

* Display a user's balances and DeFi positions in your UI
* Check positions and available collateral before creating a plan
* Monitor yield rates, borrow rates, and bridge costs
* Verify that a transaction has settled (balance changed)
* Stream live portfolio updates via SSE

## Folio structure overview

Every piece of folio data is a `key → value` string pair. Keys are slash-delimited paths where the first segment is the **category**.

There are 10 categories:

| Category              | Description                                         |
| --------------------- | --------------------------------------------------- |
| `balances`            | Token balances and DeFi position amounts            |
| `prices`              | USD prices and operation cost quotes                |
| `yield_markets`       | Supply rates, caps, and rewards for yield positions |
| `borrow_markets`      | Borrow rates, caps, collateral data                 |
| `rewards`             | Claimable reward proof data                         |
| `swap_hints`          | Token wrapper exchange rates                        |
| `bridge_hints`        | Cross-chain bridge costs and limits                 |
| `hex_data`            | Raw hex data (nonce secrets)                        |
| `completion_statuses` | On-chain event confirmation flags                   |
| `patches`             | Optimistic balance deltas for in-flight operations  |

The [`GET /folio`](/api-reference/get-folio) endpoint returns these grouped by category as a JSON object. The [`GET /folio/stream`](/api-reference/stream-folio) SSE endpoint returns them as flat `[[key, value], ...]` arrays.

## Value encoding

Values are always strings (or JSON-encoded strings). The encoding depends on the category:

| Encoding          | Format                   | Example                        | Used by                          |
| ----------------- | ------------------------ | ------------------------------ | -------------------------------- |
| Scientific amount | `"{integer}e{decimals}"` | `"100e6"` = 100 USDC           | balances, market caps/totals     |
| Decimal price     | `"{number}"`             | `"3391.3"`                     | prices                           |
| Decimal rate      | `"0.{digits}"`           | `"0.032335770872448"` = \~3.2% | APRs, exchange rates             |
| JSON object/array | Serialized JSON          | `{"supply_apr": "0.03", ...}`  | markets, hints, rewards, patches |
| Boolean string    | `"true"` / `"false"`     | `"true"`                       | completion\_statuses             |
| Hex string        | `"0x{hex}"`              | `"0xab12..."`                  | hex\_data                        |

### Scientific notation amounts

Amounts use the format `"{coefficient}e{exponent}"` where the exponent matches the token's decimal count. For example:

* `"100e6"` = 100 USDC (6 decimals) → 100,000,000 raw units
* `"1e18"` = 1 ETH (18 decimals) → 1,000,000,000,000,000,000 raw units
* `"0.5e18"` = 0.5 ETH

To get the human-readable amount, the value is already in the right form — `"100e6"` means 100 tokens. To get the raw on-chain integer, evaluate the expression: `100e6 = 100_000_000`.

## Key/value reference

### balances

Token balances and DeFi position amounts. Value is always a scientific notation amount string.

| Type              | Key pattern                                                        |
| ----------------- | ------------------------------------------------------------------ |
| Token             | `balances/token/{network}/{symbol}/{wallet}`                       |
| Yield market      | `balances/yield_market/{ym_sub_key}/{wallet}`                      |
| Borrow market     | `balances/borrow_market/{bm_sub_key}/{wallet}`                     |
| Borrow collateral | `balances/borrow_market_collateral/{bm_sub_key}/{symbol}/{wallet}` |
| Reward            | `balances/reward/{reward_sub_key}`                                 |
| Locked reward     | `balances/locked_reward/{reward_sub_key}`                          |

**Example:**

```
"balances/token/base/USDC/0xaded3444a2bdfb9422d406b786f6d8b9b1eb78ef" → "100e6"
```

This is 100 USDC on Base in wallet `0xaded...78ef`.

### prices

USD prices for tokens and cost quotes for plan operations. Value is a decimal string.

| Type             | Key pattern                                                     |
| ---------------- | --------------------------------------------------------------- |
| Token price      | `prices/token/{symbol}`                                         |
| Asset quote      | `prices/asset_quote/{quote_id}/{symbol}`                        |
| Network op quote | `prices/network_operation_quote/{quote_id}/{network}/{op_type}` |

**Examples:**

```
"prices/token/WETH"   → "3391.3"
"prices/token/cbBTC"  → "100000"
"prices/token/USDC"   → "1"
```

Asset quotes are prices for a specific plan quote context:

```
"prices/asset_quote/0x0a4f...f184/eth"  → "1600"
"prices/asset_quote/0x0a4f...f184/usdc" → "1"
```

Network operation quotes estimate gas costs in USD:

```
"prices/network_operation_quote/0x0a4f...f184/ethereum/baseline" → "4"
"prices/network_operation_quote/0x0a4f...f184/base/baseline"     → "0.1"
"prices/network_operation_quote/0x0a4f...f184/arbitrum/baseline"  → "0.04"
```

### yield\_markets

Supply market data for yield positions. The sub-key identifies the protocol and market. Value is a JSON object.

Sub-key patterns:

| Protocol      | Sub-key pattern                                   |
| ------------- | ------------------------------------------------- |
| Aave          | `aave/{network}/{pool_address}/{symbol}`          |
| Comet         | `comet/{network}/{comet_address}/{symbol}`        |
| Morpho Vault  | `morpho_vault/{network}/{vault_address}/{symbol}` |
| Staking Token | `staking_token/{network}/{symbol}`                |

Full key: `yield_markets/{sub_key}`

**Example** — `yield_markets/comet/ethereum/0xc3d688b66703497daa19211eedff47f25384cdc3/USDC`:

```json theme={null}
{
  "supply_apr": "0.032335770872448",
  "supply_cap": null,
  "supply_rewards_apr": "0.001320942912072407",
  "total_supply": "415912669.524557e6"
}
```

| Field                | Type           | Description                                             |
| -------------------- | -------------- | ------------------------------------------------------- |
| `supply_apr`         | string         | Annual supply rate as a decimal (0.032 ≈ 3.2%)          |
| `supply_cap`         | string \| null | Maximum supply in scientific notation, null if uncapped |
| `supply_rewards_apr` | string         | Additional reward APR as a decimal                      |
| `total_supply`       | string         | Total supplied in scientific notation                   |

### borrow\_markets

Borrow market data with nested collateral information. Value is a JSON object.

Sub-key patterns:

| Protocol | Sub-key pattern                                        |
| -------- | ------------------------------------------------------ |
| Aave     | `aave/{network}/{pool_address}/{symbol}`               |
| Comet    | `comet/{network}/{comet_address}/{symbol}`             |
| Morpho   | `morpho/{network}/{collateral_symbol}/{borrow_symbol}` |

Full key: `borrow_markets/{sub_key}`

**Example** — `borrow_markets/comet/arbitrum/0x9c4ec768c28520b50860ea7a15bd7213a9ff58bf/USDC`:

```json theme={null}
{
  "borrow_apr": "0.037779988043232",
  "borrow_cap": null,
  "borrow_rewards_apr": "0.003814290905460415",
  "total_borrow": "26133596.344005e6",
  "collaterals": {
    "WETH": {
      "borrow_collateral_factor": "0.83",
      "liquidate_collateral_factor": "0.88",
      "liquidation_factor": "0.93",
      "supply_cap": "40000e18",
      "total_supply": "3134.681608547642505126e18",
      "usd_price": "3313.4485"
    }
  }
}
```

Top-level fields:

| Field                | Type           | Description                             |
| -------------------- | -------------- | --------------------------------------- |
| `borrow_apr`         | string         | Annual borrow rate as a decimal         |
| `borrow_cap`         | string \| null | Maximum borrow amount, null if uncapped |
| `borrow_rewards_apr` | string         | Reward APR for borrowing                |
| `total_borrow`       | string         | Total borrowed in scientific notation   |
| `collaterals`        | object         | Map of token symbol → collateral data   |

Collateral fields:

| Field                         | Type           | Description                          |
| ----------------------------- | -------------- | ------------------------------------ |
| `borrow_collateral_factor`    | string \| null | LTV ratio for borrowing (0.83 = 83%) |
| `liquidate_collateral_factor` | string \| null | LTV at which liquidation can begin   |
| `liquidation_factor`          | string \| null | Liquidation penalty factor           |
| `supply_cap`                  | string \| null | Maximum collateral supply            |
| `total_supply`                | string \| null | Total collateral deposited           |
| `usd_price`                   | string         | USD price of the collateral token    |

### rewards

Reward proof metadata for claimable positions. The claimable amount is stored separately at `balances/reward/{sub_key}`.

Sub-key patterns:

| Type          | Sub-key pattern                                                       |
| ------------- | --------------------------------------------------------------------- |
| Comet reward  | `comet_reward/{network}/{comet}/{symbol}/{rewards_contract}/{wallet}` |
| Morpho reward | `morpho_reward/{network}/{symbol}/{distributor}/{wallet}`             |

Full key: `rewards/{sub_key}`

Value is a JSON object with a `proof` field. Two variants:

No proof available:

```json theme={null}
{ "proof": { "proof_type": "none" } }
```

Morpho reward proof:

```json theme={null}
{
  "proof": {
    "proof_type": "morpho_reward",
    "proof": ["0x1234...", "0xabcd..."],
    "proof_amount": "1000e18"
  }
}
```

### swap\_hints

Exchange rate data for token wrapper pairs (e.g. ETH↔WETH, stETH↔wstETH).

Key: `swap_hints/wrapper/{underlying_network}/{underlying_symbol}/{wrapped_network}/{wrapped_symbol}`

**Example** — `swap_hints/wrapper/ethereum/stETH/ethereum/wstETH`:

```json theme={null}
{
  "exchange_rate": "1.22443661",
  "min_amount": null,
  "max_amount": null
}
```

| Field           | Type           | Description                                  |
| --------------- | -------------- | -------------------------------------------- |
| `exchange_rate` | string         | How many wrapped tokens per underlying token |
| `min_amount`    | string \| null | Minimum swap amount                          |
| `max_amount`    | string \| null | Maximum swap amount                          |

### bridge\_hints

Cost and limit data for cross-chain bridge routes.

Key: `bridge_hints/{type}/{network_in}/{symbol_in}/{network_out}/{symbol_out}`

Bridge types: `across`, `cctp_v2`

**Example** — `bridge_hints/across/hyper_evm/USDC/base/USDC`:

```json theme={null}
{
  "estimated_fill_time_sec": 5,
  "fixed_cost": "0e6",
  "max_amount": "10000000e6",
  "max_amount_instant": "5000000e6",
  "min_amount": "0.000001e6",
  "rate": "1"
}
```

| Field                     | Type    | Description                        |
| ------------------------- | ------- | ---------------------------------- |
| `min_amount`              | string  | Minimum bridge amount (scientific) |
| `max_amount`              | string  | Maximum bridge amount              |
| `max_amount_instant`      | string  | Max that can be filled instantly   |
| `estimated_fill_time_sec` | integer | Expected fill time in seconds      |
| `fixed_cost`              | string  | Fixed fee amount (scientific)      |
| `rate`                    | string  | Exchange rate (1 = no slippage)    |

### hex\_data

Raw hex data values.

Key: `hex_data/nonce_secret/{network}/{wallet}`

Value: `0x`-prefixed hex string (e.g. `"0xab12cd34..."`)

### completion\_statuses

Tracks whether on-chain events (quark execution, bridge fills) have been confirmed.

Key: `completion_statuses/{type}/{wallet}/{id}`

Trigger types: `quark_nonce`, `across_fill`, `cctp_v2_fill`

Value: `"true"` or `"false"`

**Example:**

```
"completion_statuses/quark_nonce/0x1234.../0x05" → "true"
```

### patches

Optimistic balance deltas applied while operations are in-flight. Keyed by the same trigger paths as completion\_statuses.

Key: `patches/{type}/{wallet}/{id}`

Trigger types: `quark_nonce`, `across_fill`, `cctp_v2_fill`

Value: JSON array of patch objects:

```json theme={null}
[{
  "target": "token/base/USDC/0x1234...",
  "delta": "-50e6",
  "operation_id": "0xabcd...",
  "metadata": { "operation_type": "slow_refund", "estimated_eta": 1234567890 },
  "expires_at": 1234567890
}]
```

| Field          | Type            | Description                                                |
| -------------- | --------------- | ---------------------------------------------------------- |
| `target`       | string          | Balance type path (without `balances/` prefix)             |
| `delta`        | string          | Signed scientific amount (+credit, -debit)                 |
| `operation_id` | string \| null  | Associated operation hex ID                                |
| `metadata`     | object \| null  | Optional metadata (e.g. `operation_type`, `estimated_eta`) |
| `expires_at`   | integer \| null | Unix timestamp when patch expires                          |

## Network identifiers

Keys use these string identifiers for networks:

| Network     | Identifier    |
| ----------- | ------------- |
| Ethereum    | `ethereum`    |
| Base        | `base`        |
| Arbitrum    | `arbitrum`    |
| Optimism    | `optimism`    |
| Polygon     | `polygon`     |
| Unichain    | `unichain`    |
| HyperEVM    | `hyper_evm`   |
| World Chain | `world_chain` |

## Streaming

The [`GET /folio/stream`](/api-reference/stream-folio) endpoint returns a Server-Sent Events (SSE) stream with two event types:

* **`event: snapshot`** — Full folio as `[[key, value], ...]` sent on connect
* **`event: update`** — Delta batch of changed key/value pairs

A keepalive comment (`: keepalive`) is sent every 30 seconds to keep the connection alive.

See the [Stream Folio API reference](/api-reference/stream-folio) for details.

## Zero-value handling

* Balances matching `/^0e\d+$/` (e.g. `"0e6"`, `"0e18"`) are removed from the store but still broadcast on the stream so clients can delete them locally.
* Patches with value `"[]"` (empty array) are similarly removed from the store but broadcast on the stream.

## How plans use the folio

When you create a plan, Legend automatically computes a fresh folio to determine what operations are possible. The folio is stored with the plan and validated again at execution time to prevent stale transactions.
