Skip to main content

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: The GET /folio endpoint returns these grouped by category as a JSON object. The GET /folio/stream 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:

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. Example:
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. Examples:
Asset quotes are prices for a specific plan quote context:
Network operation quotes estimate gas costs in USD:

yield_markets

Supply market data for yield positions. The sub-key identifies the protocol and market. Value is a JSON object. Sub-key patterns: Full key: yield_markets/{sub_key} Exampleyield_markets/comet/ethereum/0xc3d688b66703497daa19211eedff47f25384cdc3/USDC:

borrow_markets

Borrow market data with nested collateral information. Value is a JSON object. Sub-key patterns: Full key: borrow_markets/{sub_key} Exampleborrow_markets/comet/arbitrum/0x9c4ec768c28520b50860ea7a15bd7213a9ff58bf/USDC:
Top-level fields: Collateral fields:

rewards

Reward proof metadata for claimable positions. The claimable amount is stored separately at balances/reward/{sub_key}. Sub-key patterns: Full key: rewards/{sub_key} Value is a JSON object with a proof field. Two variants: No proof available:
Morpho reward proof:

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} Exampleswap_hints/wrapper/ethereum/stETH/ethereum/wstETH:

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 Examplebridge_hints/across/hyper_evm/USDC/base/USDC:

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:

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:

Network identifiers

Keys use these string identifiers for networks:

Streaming

The GET /folio/stream 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 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.