Markets, Oracles, and Positions
How it works
Velocity has two types of markets: perp markets (perpetual futures with funding rates) and spot markets (token deposits/borrows that serve as collateral). Each market has an onchain account storing configuration like oracle source, fees, funding rates, AMM parameters, and current open interest.
Market Indexes
Markets are identified by a numeric index starting from 0. For example:
- Perp market 0 is typically SOL-PERP
- Spot market 0 is typically the quote asset (dUSDT on devnet, USDT on mainnet-beta)
- Perp market 1 might be BTC-PERP, and so on
Where to find market indexes:
- State account: Query
velocityClient.getStateAccount()fornumberOfMarketsandnumberOfSpotMarkets, the counts of perp and spot markets. This gives you the index range (0tocount - 1) to enumerate; it does not contain the market configurations themselves - SDK methods: Use
velocityClient.getPerpMarketAccounts()orvelocityClient.getSpotMarketAccounts()to get all markets and inspect their indexes - Market account directly: Each market account has a
marketIndexfield you can read - Symbol lookup: Most bots maintain their own mapping from symbol (e.g., “SOL-PERP”) to market index, or query all markets and build the mapping at startup
Each market integrates with an oracle that provides real-time price data, Pyth (push), Pyth Lazer, Prelaunch (for pre-listing markets), or (for the quote asset) QuoteAsset. Switchboard is deprecated (its OracleSource variants are retained only as Deprecated* stubs), and the Pyth pull variants (PythPull, Pyth1KPull, Pyth1MPull, PythStableCoinPull) are rejected onchain with InvalidOracle. Pyth push and Pyth Lazer sources remain fully supported; deployed markets currently use Pyth Lazer. The SDK lets you read oracle prices, check if they’re valid/stale, and use them for quoting or risk calculations. Prices are stored in fixed-point precision (1e6 for PRICE_PRECISION).
Perp markets track funding rates, open interest, and AMM liquidity pools. Spot markets track total deposits, borrows, and utilization rates. When you trade, you’re interacting with these market accounts, opening positions on perp markets or borrowing/depositing in spot markets. Spot markets on Velocity are collateral/borrow-lend only: spot orders cannot be placed on the DLOB (see Orders).
SDK Usage
These are the most common read-path helpers you’ll use to power bots, dashboards, and risk logic.
Market Accounts
Read a single spot market account by index (e.g., market config, oracle source, and utilization state).
const marketIndex = 0;
const spotMarket = velocityClient.getSpotMarketAccount(marketIndex);
console.log(spotMarket?.marketIndex);Method VelocityClient.getSpotMarketAccountReference ↗
Method VelocityClient.getSpotMarketAccountReference ↗| Parameter | Type | Required |
|---|---|---|
marketIndex | numberSpot market index. | Yes |
| Returns |
|---|
SpotMarketAccount | undefined |
Read a single perp market account by index (e.g., AMM params, funding state, and open interest).
const marketIndex = 0;
const perpMarket = velocityClient.getPerpMarketAccount(marketIndex);
console.log(perpMarket?.marketIndex);Method VelocityClient.getPerpMarketAccountReference ↗
Method VelocityClient.getPerpMarketAccountReference ↗| Parameter | Type | Required |
|---|---|---|
marketIndex | numberPerp market index. | Yes |
| Returns |
|---|
PerpMarketAccount | undefined |
Get all spot market accounts at once, useful for startup symbol/index mapping and dashboards.
const spotMarkets = velocityClient.getSpotMarketAccounts();
console.log(spotMarkets.length);Method VelocityClient.getSpotMarketAccountsReference ↗
Method VelocityClient.getSpotMarketAccountsReference ↗| Returns |
|---|
SpotMarketAccount[] |
Get all perp market accounts at once, useful for scanning market metadata and risk parameters.
const perpMarkets = velocityClient.getPerpMarketAccounts();
console.log(perpMarkets.length);Method VelocityClient.getPerpMarketAccountsReference ↗
Method VelocityClient.getPerpMarketAccountsReference ↗| Returns |
|---|
PerpMarketAccount[] |
Reading a Market’s Tier
A perp market’s contractTier and a spot market’s assetTier are enums. The SDK converts them to an ordinal safety rank, where lower is safer, so you can compare and sort them. The numbering follows the on-chain enum declaration order, which is what the program compares against.
| Helper | Input | Returns |
|---|---|---|
getPerpMarketTierNumber(perpMarket) | A PerpMarketAccount | 0 = A, 1 = B, 2 = C, 3 = Speculative, 4 = Highly Speculative, 5 = Isolated |
getSpotMarketTierNumber(spotMarket) | A SpotMarketAccount | 0 = Collateral, 1 = Protected, 2 = Cross, 3 = Isolated, 4 = Unlisted |
perpTierIsAsSafeAs(perpTier, otherPerpTier, otherSpotTier) | Three tier numbers | true if the perp tier is at least as safe as both references |
import {
getPerpMarketTierNumber,
getSpotMarketTierNumber,
perpTierIsAsSafeAs,
} from "@velocity-exchange/sdk";
const perpMarket = velocityClient.getPerpMarketAccount(0);
const perpTier = getPerpMarketTierNumber(perpMarket); // 0 (A) through 5 (Isolated)
// Filter to markets at tier C or safer
const safeMarkets = velocityClient
.getPerpMarketAccounts()
.filter((m) => getPerpMarketTierNumber(m) <= 2);
// Compare a market against the tiers already open on an account
const spotTier = getSpotMarketTierNumber(velocityClient.getSpotMarketAccount(1));
const ok = perpTierIsAsSafeAs(perpTier, 2, spotTier);Function getPerpMarketTierNumberReference ↗
Function getPerpMarketTierNumberReference ↗Maps a perp market's `contractTier` to an ordinal safety rank, lower is safer. Matches the declaration order of the Rust `ContractTier` enum (which derives `Ord` from declaration order, used by `ContractTier::is_as_safe_as_contract`'s `self <= other`).
| Parameter | Type | Required |
|---|---|---|
perpMarket | PerpMarketAccountThe perp market account | Yes |
| Returns |
|---|
number |
perpTierIsAsSafeAs mirrors the program’s own comparison. A perp tier passes when it is numerically at or below otherPerpTier, and it is as safe as the spot reference: any tier beats Unlisted spot (4), and against Cross or Isolated spot (2 or 3) the perp tier must be C or safer (0 to 2).
Tier is not cosmetic, the program derives real limits from it: insurance-fund caps, the oracle confidence band before a price is treated as invalid, the TWAP sanitization band, the oracle/mark divergence gate on PnL settlement, and the auction duration granted per 1% of price difference (100 steps per 1% for tier B or safer, 60 otherwise). If you predict sanitized auction parameters or build a market-safety filter, read the tier with these helpers rather than reimplementing the mapping. See Contract Tiers for every derived limit.
Oracle Price
Read the current oracle data for a perp market (price, confidence, and validity flags).
const marketIndex = 0;
const oracle = velocityClient.getOracleDataForPerpMarket(marketIndex);
console.log(oracle.price.toString());Method VelocityClient.getOracleDataForPerpMarketReference ↗
Method VelocityClient.getOracleDataForPerpMarketReference ↗| Parameter | Type | Required |
|---|---|---|
marketIndex | numberPerp market index. | Yes |
| Returns |
|---|
OraclePriceData |
Read the current oracle data for a spot market using its market index.
const marketIndex = 0;
const oracle = velocityClient.getOracleDataForSpotMarket(marketIndex);
console.log(oracle.price.toString());Method VelocityClient.getOracleDataForSpotMarketReference ↗
Method VelocityClient.getOracleDataForSpotMarketReference ↗| Parameter | Type | Required |
|---|---|---|
marketIndex | numberSpot market index. | Yes |
| Returns |
|---|
OraclePriceData |
Read market-maker-oriented oracle data for perp markets, typically used for DLOB/JIT pricing flows.
const marketIndex = 0;
const oracle = velocityClient.getMMOracleDataForPerpMarket(marketIndex);
console.log(oracle.price.toString());Method VelocityClient.getMMOracleDataForPerpMarketReference ↗
Method VelocityClient.getMMOracleDataForPerpMarketReference ↗| Parameter | Type | Required |
|---|---|---|
marketIndex | numberPerp market index. | Yes |
| Returns |
|---|
MMOraclePriceData |
Positions and Balances
Get your active subaccount’s spot position for a given market index (deposit or borrow state).
const spotPosition = velocityClient.getSpotPosition(0);
console.log(spotPosition);Method VelocityClient.getSpotPositionReference ↗
Method VelocityClient.getSpotPositionReference ↗| Parameter | Type | Required |
|---|---|---|
marketIndex | numberSpot market index. | Yes |
subAccountId | numberSub-account id; defaults to `this.activeSubAccountId`. | No |
| Returns |
|---|
SpotPosition | undefined |
Get your active subaccount’s perp position for a given perp market index, via the subaccount’s User.
const perpPosition = velocityClient.getUser().getPerpPosition(0);
console.log(perpPosition);Method User.getPerpPositionReference ↗
Method User.getPerpPositionReference ↗| Parameter | Type | Required |
|---|---|---|
marketIndex | number | Yes |
| Returns |
|---|
PerpPosition | undefined |
Protocol State
The global state account holds protocol-level configuration including the number of active markets, the tiered admin key set (cold/warm/hot), and fee structures. It is the top-level entry point for querying protocol metadata.
const state = velocityClient.getStateAccount();
console.log(state);Method VelocityClient.getStateAccountReference ↗
Method VelocityClient.getStateAccountReference ↗| Returns |
|---|
StateAccount |