Skip to main content

How to query Iris Core data with the API?

You can query Iris Core data with the GraphQL API. Queries run against the GraphQL Playground. A few conventions carry through every example:
  • Examples read from the Ethereum mainnet staging fork (VNet, chainId: 9991); an integration moves to another network by changing the chainId.
  • By default the API returns only the first 50 results; pass limit (up to 1000) and page with cursors for more. The loanPositions view pages by offset instead.
  • Addresses are lowercase hex, and filters are exact-match.
  • BigInt values are returned as strings; rates and LLTVs are WAD (1e18), amounts are in the token’s own decimals.
  • Plural query names are generated from table names: blmParamss, marketDatas, and whitelistEntrys are not typos.

Discovery and Listing

Loans List

A loan is identified by its pod, the isolated clone address holding that borrower’s position. (chainId, pod) is the primary key everywhere in this API.
Loan rows are immutable: they record the quote as accepted when the loan is opened. Everything that moves lives on position.

Loan and position in one filter

where cannot traverse a relation, so a condition spanning both sides (a solver’s loans that still carry a bond requirement, say) needed two queries and a client-side join. loanPositions is a read-only view over loan joined to position on (chainId, pod). Every column of both tables sits flat on one row, so a single where can filter across both.
Four things differ from the tables the view is built from:
  • Plural only. There is no single-row loanPosition(chainId:, pod:) lookup; filter on pod instead.
  • No relations. collateralToken and debtToken are raw addresses here, not token objects, so { symbol decimals } does not resolve. Read metadata from tokens in the same request.
  • Offset paging, not cursors. after and before are not arguments on this query, and pageInfo carries hasNextPage and hasPreviousPage without cursors. Page with limit and offset.
  • orderBy is required to page safely. A view has no primary key to break ties on and no default order, so a paginated read must order on an effectively unique column (pod, with chainId filtered), or pages can skip and repeat rows.
Everything else matches the underlying tables: the same suffixed operators with AND and OR, a default page of 50 rows, and a totalCount over the whole filtered set.

Position Metrics

Collateral, Debt & Bond

position is one-to-one with loan on (chainId, pod) and holds everything mutable.
bond and bondRequirement are in the debt token’s decimals, collateral in the collateral token’s; a closed loan keeps its row with debt: "0".

Fixed vs Floating Legs

Legs are as of lastUpdate, not as of now.

Bond Health

A bond is unhealthy when bond < bondRequirement, or when ceil((floatingLeg - fixedLeg) × 1e18 / bond) exceeds bondLltv. Both legs are as of lastUpdate, so a ratio computed from them understates a position that has not been touched in a while. For that comparison computed against live venue indices, read positionHealths. See Bond Mechanics.

Liquidatability estimates

positionHealths carries one row per open loan. bondHealthFactor is refreshed by a poll that reads each market’s venue indices onchain and accrues the legs to the poll block, and venueLiquidated follows the venues’ liquidation events. The entity exists so a keeper can filter and sort liquidatability server-side instead of pulling every position and recomputing it client-side.
Five things to know before filtering on it:
  • bondHealthFactor is an estimate, liquidatableAt is exact. The factor is accurate as of updatedAt and drifts until the next poll, so filter with a margin above 1 and re-verify onchain before sending a transaction. liquidatableAt comes from the loan’s own terms and does not move.
  • null means no drawdown, not “unknown”: the floating leg is not above the fixed leg. Because null never satisfies a comparison, any bondHealthFactor_* filter drops those rows, which is what a keeper scan wants.
  • It does not cover the whole bond check. bondHealthFactor only compares drawdown to bondLltv. A bond is also unhealthy when bond < bondRequirement, which is a filter on loanPositions.
  • venueLiquidated is over-inclusive. It turns true when Morpho Blue emits Liquidate or Aave V3 emits LiquidationCall for an open loan’s pod, and back to false at the next IRIS action that accrues or rebases the position. It can stay true for a position with nothing left to recognize, so filter on venueLiquidated: true to find positions awaiting a rebase and check onchain before sending one.
  • Rows exist only while the loan is open. A row is created in the block the loan opens, with bondHealthFactor null until the first poll, and is deleted by the first poll after the loan closes. There are no relations on this entity, so read the loan and position fields in a second query keyed by pod.
bondHealthFactor is the solver’s bond against its drawdown. It is unrelated to the borrower’s venue health factor, which IRIS does not index.

Loan Status

Status is not a column: it is derived at read time from debt, maturity, and overduePeriod.
With now in unix seconds: Of these, closed is a filter on debt, and the liquidatable set is positionHealths(where: { liquidatableAt_lte: now }), whose rows are open by construction. For the rest, fetch the live set with positions(where: { debt_gt: "0" }) and classify client-side, comparing now against the indexed block timestamp from _meta { status }.

Position Tracking

Borrower All Loans Position

Everything a borrower needs on one screen: terms, live balances, and both USD legs.

Borrower Account Overview

Loans, claimable balances, and delegated managers in one request.

Solver Book

A solver’s whole exposure: loans underwritten, bond posted against bond required, and unclaimed earnings. To narrow the book by a position field as well as a loan field, filter the loanPositions view instead.

Bond

BLMs List

A bond lock module (BLM) sets how much bond a solver must post.
A BLM with whitelist rows is a WhitelistBlm; one with none is a plain Blm.

Bond Curve Parameters

Curves are keyed per debt token, so a single BLM prices USDC and USDT loans independently.
position.bondRequirement is computed once at loan open as debt × (slope × duration / 86400 + intercept) / 1e18; see Bond Mechanics.

Solver Whitelist

Rows persist with isWhitelisted: false after a removal, so always filter on the flag.

Enabled Bond LLTVs

The set of bond LLTVs governance permits a quote to use.

Venue & Settlement

Venue Adapters

Every position sits in exactly one venue, addressed by venueId and served by an adapter contract.
loan.venueBitmap is the set of venues the loan may move within (bit n set = venue n allowed); position.venueId is where it is right now.

Enabled Market Data

data is keccak256 of a venue-market blob; hash the blob you hold to check whether it is enabled.

Refinance & Rebase State

Refinancing moves a position between venues, re-snapshotting the venue indices and the market blob.
position.data is the raw blob for the current venue (0x when the venue takes no parameters), the pre-image whose hash appears in marketDatas.

Protocol Configuration

Owner, Fee & Fee Recipient

One singleton row per chain.
config.fee is the live protocol fee; loan.fee is the value snapshotted when that loan was opened.

Authorization

Borrowers can authorize a manager to act on their positions.
Rows persist with isAuthorized: false after revocation, so filter on the flag.

Claimable Balances

Credited earnings (solver interest, protocol fees, collateral surplus) that have not yet been claimed.
One row per (chainId, token, account); claims decrement rather than delete, so a zero amount means fully claimed.

Token Metadata

Token metadata is resolved off-chain for every token the protocol references. USD prices are sourced from DefiLlama.

Token List

Tokens that don’t answer a metadata call are stored with UNKNOWN placeholders rather than omitted.

Prices

priceUsd is refreshed every 5 minutes, is nullable, and is a Float; parse it as a number, not a BigInt.

Token Relations

Any token address field expands in place, which removes the second round trip.
The relation replaces the raw string, so request { address } if you need the hex.

Historical Data

The API serves current state only: every row reflects the latest indexed block, with no event log, snapshot table, or timeseries. For now, read the contract event logs directly, or index them yourself; historical timeseries data will be added to the API in a future release.

Paging, Ordering & Filtering

Every plural query accepts the same arguments: where, orderBy, orderDirection, limit, and cursor paging via after / before with pageInfo. The one exception is the loanPositions view, which takes offset in place of the cursor arguments; see Loan and position in one filter.
Each column exposes suffixed operators, combined with AND by default: AND and OR take lists of filters and nest:
Three notes: limit above the 1000 cap fails with a masked INTERNAL_SERVER_ERROR (“Unexpected error.”); where cannot traverse relations, so cross-entity conditions are a second query plus a client-side join, except for loan and position, which the loanPositions view already joins; prefer cursors over offset for full scans, since offset can skip or repeat rows if a write lands mid-scan.