Skip to main content

Reading Scope Prices

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.

Read All Prices

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.

Get a Single Token Price

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).
import { createSolanaRpc } from '@solana/kit';
import { Scope, SCOPE_MAINNET_HUBBLE_FEED } from '@kamino-finance/scope-sdk';

const RPC_ENDPOINT = 'https://api.mainnet-beta.solana.com';
const CHAIN = [0, 65535, 65535, 65535]; // SOL/USD, slot 0, single-hop

const rpc = createSolanaRpc(RPC_ENDPOINT);
const scope = new Scope('mainnet-beta', rpc);

const oraclePrices = await scope.getSingleOraclePrices({
  config: SCOPE_MAINNET_HUBBLE_FEED.configuration,
});
if (!Scope.isScopeChainValid(CHAIN)) console.log('Chain is not valid:', CHAIN);

const { price, timestamp } = await scope.getPriceFromChain(CHAIN, oraclePrices);
const ageSec = Math.floor(Date.now() / 1000) - timestamp.toNumber();

console.log(`Price: ${price.toString()}`);
console.log(`Updated: ${new Date(timestamp.toNumber() * 1000).toISOString()} (${ageSec}s ago)`);
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.

Get Token Price History

Past prices for a single token, keyed by mint or symbol. API only, with no on-chain equivalent: the OraclePrices account holds only the current value per slot, so history is served off-chain.
const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
const API = `https://api.kamino.finance/prices/history?token=${USDC_MINT}&frequency=day&start=2026-06-01T00:00:00Z&end=2026-06-10T00:00:00Z`;

// Each point is a [usdPrice, unixSeconds] pair, ordered oldest to newest.
type PricePoint = [price: string, timestamp: number];
const points: PricePoint[] = await (await fetch(API)).json();

console.log(`History points: ${points.length}`);
points.slice(0, 5).forEach(([price, ts]) =>
  console.log(`  ${new Date(ts * 1000).toISOString()}: $${price}`),
);
frequency is minute, hour, or day; omit start/end and the endpoint returns a default recent window (about the last day) at the chosen frequency. See the Get token price history reference for the full parameter list.

Types

Returned by getPriceFromChain. A resolved price plus its freshness.
type ScopeDatedPrice = {
  price: Decimal;
  timestamp: BN;
};

Additional Resources

API Examples

SDK Repository