vaultsDocumentation

SDK

Implemented

Reading and driving a vault from TypeScript, and why every preview is a simulation.

@vaults/sdk — reading and driving a vault from TypeScript, on top of viem.

#Previews are simulations, not re-implementations

Every preview calls simulateContract against the deployed bytecode rather than recomputing the maths in TypeScript.

Re-deriving share counts client-side is how an interface ends up confidently displaying a number the chain then disagrees with — and the disagreement always surfaces at the worst possible moment, after the user has signed. Simulating means the preview is the contract's answer, and allowance and pause state are exercised exactly as they will be.

#Reading

ts
import { VaultClient } from '@vaults/sdk';

const client = new VaultClient({ publicClient, chainId: 46630 });

const addresses = await client.listVaults(factoryAddress);
const summary   = await client.getVault(addresses[0]!);
const positions = await client.getPositions(addresses[0]!);

getVault returns the vault's live state: NAV (or the reason it is unavailable), base-asset balance, total shares, pause flags, tracked assets, high-water mark and the risk constitution.

getPositions returns each tracked asset with its balance, the vault's accepted source snapshot, the source's live balance, and a per-position valuation:

ts
interface VaultPositionView {
  token: Address;
  symbol: string;
  decimals: number;
  balance: bigint;
  sourceSnapshot: bigint;   // what the vault accepted
  sourceLive: bigint;       // what the source holds now
  pendingSince: number | null;
  valueInBase: bigint | null;        // null when unpriceable — never zero
  priceUnavailableReason: number | null;
}

Note. valueInBase is null, not 0, when an asset cannot be priced. An unpriceable position is exactly the condition that makes totalAssets() revert, so a caller substituting zero would produce a portfolio that reconciles against a NAV the chain refuses to produce.

Valuation goes through the vault's own price router, using the same arithmetic as the contract (amount × price / 10^decimals), so a displayed value and the NAV it contributes to can never come from different oracles.

#Previewing

ts
const { shares } = await client.previewDeposit(vault, account, amount);
const basket     = await client.previewRedeemInKind(vault, account, shares);
const decision   = await client.previewSync(vault, token);

previewSync returns what a sync would do — including the skip reason if it would decline — without sending a transaction.

#Writing

deposit, redeemInKind, requestBaseRedemption, claimRedemption and sync each build and send a transaction through a wallet client. buildApproval produces an exact-amount approval; the SDK never requests an unlimited allowance.

#Errors

explainViemError decodes a revert into the contract's own custom error with its arguments, so an interface can say why rather than showing a hex selector. See Error reference.

#Stability

Warning. This SDK has no stability guarantee. It is versioned with the protocol it targets, and the protocol has not been audited or deployed to mainnet. Interfaces here may change without a deprecation period.