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:
CategoryDescription
balancesToken balances and DeFi position amounts
pricesUSD prices and operation cost quotes
yield_marketsSupply rates, caps, and rewards for yield positions
borrow_marketsBorrow rates, caps, collateral data
rewardsClaimable reward proof data
swap_hintsToken wrapper exchange rates
bridge_hintsCross-chain bridge costs and limits
hex_dataRaw hex data (nonce secrets)
completion_statusesOn-chain event confirmation flags
patchesOptimistic balance deltas for in-flight operations
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:
EncodingFormatExampleUsed by
Scientific amount"{integer}e{decimals}""100e6" = 100 USDCbalances, market caps/totals
Decimal price"{number}""3391.3"prices
Decimal rate"0.{digits}""0.032335770872448" = ~3.2%APRs, exchange rates
JSON object/arraySerialized 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.
TypeKey pattern
Tokenbalances/token/{network}/{symbol}/{wallet}
Yield marketbalances/yield_market/{ym_sub_key}/{wallet}
Borrow marketbalances/borrow_market/{bm_sub_key}/{wallet}
Borrow collateralbalances/borrow_market_collateral/{bm_sub_key}/{symbol}/{wallet}
Rewardbalances/reward/{reward_sub_key}
Locked rewardbalances/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.
TypeKey pattern
Token priceprices/token/{symbol}
Asset quoteprices/asset_quote/{quote_id}/{symbol}
Network op quoteprices/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:
ProtocolSub-key pattern
Aaveaave/{network}/{pool_address}/{symbol}
Cometcomet/{network}/{comet_address}/{symbol}
Morpho Vaultmorpho_vault/{network}/{vault_address}/{symbol}
Staking Tokenstaking_token/{network}/{symbol}
Full key: yield_markets/{sub_key} Exampleyield_markets/comet/ethereum/0xc3d688b66703497daa19211eedff47f25384cdc3/USDC:
{
  "supply_apr": "0.032335770872448",
  "supply_cap": null,
  "supply_rewards_apr": "0.001320942912072407",
  "total_supply": "415912669.524557e6"
}
FieldTypeDescription
supply_aprstringAnnual supply rate as a decimal (0.032 ≈ 3.2%)
supply_capstring | nullMaximum supply in scientific notation, null if uncapped
supply_rewards_aprstringAdditional reward APR as a decimal
total_supplystringTotal supplied in scientific notation

borrow_markets

Borrow market data with nested collateral information. Value is a JSON object. Sub-key patterns:
ProtocolSub-key pattern
Aaveaave/{network}/{pool_address}/{symbol}
Cometcomet/{network}/{comet_address}/{symbol}
Morphomorpho/{network}/{collateral_symbol}/{borrow_symbol}
Full key: borrow_markets/{sub_key} Exampleborrow_markets/comet/arbitrum/0x9c4ec768c28520b50860ea7a15bd7213a9ff58bf/USDC:
{
  "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:
FieldTypeDescription
borrow_aprstringAnnual borrow rate as a decimal
borrow_capstring | nullMaximum borrow amount, null if uncapped
borrow_rewards_aprstringReward APR for borrowing
total_borrowstringTotal borrowed in scientific notation
collateralsobjectMap of token symbol → collateral data
Collateral fields:
FieldTypeDescription
borrow_collateral_factorstring | nullLTV ratio for borrowing (0.83 = 83%)
liquidate_collateral_factorstring | nullLTV at which liquidation can begin
liquidation_factorstring | nullLiquidation penalty factor
supply_capstring | nullMaximum collateral supply
total_supplystring | nullTotal collateral deposited
usd_pricestringUSD 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:
TypeSub-key pattern
Comet rewardcomet_reward/{network}/{comet}/{symbol}/{rewards_contract}/{wallet}
Morpho rewardmorpho_reward/{network}/{symbol}/{distributor}/{wallet}
Full key: rewards/{sub_key} Value is a JSON object with a proof field. Two variants: No proof available:
{ "proof": { "proof_type": "none" } }
Morpho reward proof:
{
  "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} Exampleswap_hints/wrapper/ethereum/stETH/ethereum/wstETH:
{
  "exchange_rate": "1.22443661",
  "min_amount": null,
  "max_amount": null
}
FieldTypeDescription
exchange_ratestringHow many wrapped tokens per underlying token
min_amountstring | nullMinimum swap amount
max_amountstring | nullMaximum 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 Examplebridge_hints/across/hyper_evm/USDC/base/USDC:
{
  "estimated_fill_time_sec": 5,
  "fixed_cost": "0e6",
  "max_amount": "10000000e6",
  "max_amount_instant": "5000000e6",
  "min_amount": "0.000001e6",
  "rate": "1"
}
FieldTypeDescription
min_amountstringMinimum bridge amount (scientific)
max_amountstringMaximum bridge amount
max_amount_instantstringMax that can be filled instantly
estimated_fill_time_secintegerExpected fill time in seconds
fixed_coststringFixed fee amount (scientific)
ratestringExchange 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:
[{
  "target": "token/base/USDC/0x1234...",
  "delta": "-50e6",
  "operation_id": "0xabcd...",
  "metadata": { "operation_type": "slow_refund", "estimated_eta": 1234567890 },
  "expires_at": 1234567890
}]
FieldTypeDescription
targetstringBalance type path (without balances/ prefix)
deltastringSigned scientific amount (+credit, -debit)
operation_idstring | nullAssociated operation hex ID
metadataobject | nullOptional metadata (e.g. operation_type, estimated_eta)
expires_atinteger | nullUnix timestamp when patch expires

Network identifiers

Keys use these string identifiers for networks:
NetworkIdentifier
Ethereumethereum
Basebase
Arbitrumarbitrum
Optimismoptimism
Polygonpolygon
Unichainunichain
HyperEVMhyper_evm
World Chainworld_chain

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.