Scope serves prices two ways. On-chain, the OraclePrices account holds a fixed 512-slot array of dated prices and the SDK reads it directly. Off-chain, the Kamino REST endpoint serves the same prices pre-aggregated and keyed by mint, with no RPC or SDK required.
Direct on-chain read of every populated slot in a feed.
import { createSolanaRpc } from '@solana/kit';import { Scope, SCOPE_MAINNET_HUBBLE_FEED } from '@kamino-finance/scope-sdk';import Decimal from 'decimal.js';const RPC_ENDPOINT = 'https://api.mainnet-beta.solana.com';const rpc = createSolanaRpc(RPC_ENDPOINT);const scope = new Scope('mainnet-beta', rpc);const oraclePrices = await scope.getSingleOraclePrices({ config: SCOPE_MAINNET_HUBBLE_FEED.configuration,});// Fixed-size array; a slot is unset when its price value is 0.const populated = oraclePrices.prices .map((p, index) => ({ index, p })) .filter(({ p }) => p.price.value.toString() !== '0');console.log(`Feed ${SCOPE_MAINNET_HUBBLE_FEED.oraclePrices}: ${populated.length} populated of ${oraclePrices.prices.length}`);populated.slice(0, 10).forEach(({ index, p }) => { const price = new Decimal(p.price.value.toString()).div(new Decimal(10).pow(Number(p.price.exp))); const updated = new Date(Number(p.unixTimestamp) * 1000).toISOString(); console.log(` [${index}] ${price.toString()} (updated ${updated})`);});
View CodeA price is value / 10^exp; freshness comes from lastUpdatedSlot and unixTimestamp on the same dated price. getSingleOraclePrices accepts the feed by its configuration account, its OraclePrices pubkey, or its PDA seed.
The same prices, pre-aggregated and keyed by mint. No RPC required.
A token’s USD price is resolved by a “scope chain”: up to 4 slot indices, padded with 65535. One index means a direct price; several means a derived price (for example TOKEN/SOL then SOL/USD).
View CodeThe calling program supplies the scope chain. A klend reserve, for example, stores it on its token config; Scope just resolves it against the feed’s price list. Sentinel slots (65535) are skipped.
Filter the price list by mint. No scope chain to walk.
const SOL_MINT = 'So11111111111111111111111111111111111111112';const API = 'https://api.kamino.finance/prices?source=scope';type Price = { usdPrice: string; token: string; mint: string };const rows: Price[] = await (await fetch(API)).json();const sol = rows.find((r) => r.mint === SOL_MINT);if (!sol) console.log('Mint not found in price list:', SOL_MINT);console.log(`${sol.token}: $${sol.usdPrice}`);