Reading protocol data
Two view contracts give you everything the Sward interface itself runs on. No indexer required.
All reserves in one call
UiPoolDataProvider.getReservesData(provider) returns every reserve's full state: symbols,
decimals, oracle prices, rates, indexes, caps, rate-model parameters, and configuration flags.
import { createPublicClient, http } from 'viem';
const client = createPublicClient({
transport: http('https://rpc.testnet.chain.robinhood.com'),
});
const [reserves, baseCurrency] = await client.readContract({
address: '0xb98713a9430A773564ED5EC1FAc87105EeCAC6bb',
abi: uiPoolDataProviderAbi,
functionName: 'getReservesData',
args: ['0x7697215A4CDdeb10785c4b33bE773E0F30a4b2c7'],
});
Rates come back as rays (27-decimal fixed point). Divide by 1e27 for the simple annual
rate, then compound per second for the APY shown in the UI:
const apr = Number(reserve.variableBorrowRate) / 1e27;
const apy = (1 + apr / 31_536_000) ** 31_536_000 - 1;
One user's position
Pool.getUserAccountData(user) returns the aggregate position: total collateral and debt in the
base currency (USD, 8 decimals), available borrows, the weighted liquidation threshold and LTV,
and the health factor (18 decimals, type(uint256).max when there is no debt).
Per-reserve balances come from UiPoolDataProvider.getUserReservesData(provider, user); multiply
the scaled balances by the reserve's current index to get live amounts.
Wallet balances in bulk
WalletBalanceProvider.batchBalanceOf([user], tokens) reads any number of ERC-20 balances in a
single call, which is how the app fills the wallet column in Markets.