Skip to content

Vault Discovery

The server finds vaults for you. You can pass a result directly into a deposit. You do not enter the address, chain, or asset again.

listVaults

const { vaults, nextPage } = await sr.listVaults({
  asset: TOKENS.USDC,   // optional - filter by asset
  chains: [42161],      // optional - filter by chain
  protocol: "morpho",   // optional - filter by protocol
  minTvl: 1_000_000,    // optional - USD TVL floor
  minApy: 2,            // optional - percent
  page: 0,              // zero-based; walk until nextPage is null
});

The Vault type

The type is a union that discriminates on category. A vault contains the fields that you select a vault by, and the fields that a deposit routes with:

type VaultCommon = {
  id: string                   // server vault id - what `into` keys on
  address: Address             // the vault contract (deposit target)
  chainId: number
  protocol: string             // 'aave' | 'morpho' | 'fluid' | 'yearn' | ...
  asset: { symbol: string; address: Address; decimals: number }
  apy: number | null           // percent (2.57 = 2.57%)
  tvlUsd: number | null
  name?: string
}
 
type Vault =
  | (VaultCommon & { category: "lend" })
  | (VaultCommon & { category: "liquid-staking" })
  | (VaultCommon & { category: "fixed-yield"; maturity: string })

maturity exists only on fixed-yield vaults. The compiler blocks access to it until you narrow on category.

You can pass a Vault directly as the into of a deposit. The deposit gets destChainId from the vault.

getVault

getVault returns the detail view: a Vault plus data that the list omits. You can also pass the result as into.

const details = await sr.getVault(vaultId, chainId);
// details.apyBreakdown  { base?, reward?, total? }
// details.apy7day / details.apy30day
// details.description

Pass chainId when you know it. The call then uses the direct single-vault endpoint and does not scan a list.

preflight

preflight reports the vault state without a quote. It includes depositsDisabled: the vault's on-chain maxDeposit is 0, so the vault accepts no deposits. Vault listings cannot see this state. Only the on-chain read shows it.

const check = await sr.preflight({
  owner: "0xUSER",
  vaultId: vault.address,
  destChainId: vault.chainId,
  amount: "100",
});
if (check.depositsDisabled) {
  // the vault accepts no deposits - select a different vault
}
// check.maxDeposit - remaining cap headroom (null when the vault kind has no per-owner cap)
// check.route      - the bridge token, and whether a src or dest swap is required

Supported chains and tokens

const chains = await sr.getChains();          // ChainInfo[]
const tokens = await sr.getTokens({ chainId: 8453 }); // TokenInfo[]