Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Info API

sdk.info exposes read-only methods for POST /info. It does not require a signer and returns each endpoint's response body directly.

import { TxFlow } from 'txflow-typescript-sdk'
 
const sdk = new TxFlow('testnet')
const meta = await sdk.info.perpMeta()

Each method adds the correct wire type internally. Pass only the method parameters — do not include a type field yourself.

Instrument identifiers

Resolve instruments from metadata before querying them:

const meta = await sdk.info.perpMeta()
const market = meta.universe.find(({ name }) => name === 'BTC-USDC')
 
if (!market) {
  throw new Error('Market not found')
}
 
const book = await sdk.info.l2Book({
  coin: String(market.index),
})

The same instrument identifier has two representations in the SDK:

  • Info parameters such as coin and risk-calculator asset are strings.
  • Exchange order asset fields are numbers.

Prices, sizes, balances, and rates remain decimal strings to preserve precision.

Market data

Common market methods include:

MethodUse
perpMeta()Perpetual instruments and asset indices
l2Book({ coin })L2 order book snapshot
marketTicker(params)Current ticker state
trades(params)Recent trades
candleSnapshot(params)Historical candles
activeAssetData(params)Active asset context for a user

The protocol schemas and field descriptions remain authoritative in the Info API reference.

Account state

Account reads take the owner address, not the agent address:

const user = '0xOwnerAddress'
 
const [account, orders, fills] = await Promise.all([
  sdk.info.clearinghouseState({ user }),
  sdk.info.frontendOpenOrders({ user }),
  sdk.info.userFills({ user }),
])

Useful account methods include:

MethodUse
clearinghouseState({ user, accountType?, exchangeId? })Balances and positions of one sub-account
frontendOpenOrders({ user })Enriched active orders
openorders({ user })Compact active orders
triggerOrders({ user })Trigger orders
positionTpslOrders(params)TP/SL pairs bound to a position
userFills(params)Fill history
userFundings(params)Funding history
historicalOrders(params)Historical order state
twapHistory(params)TWAP history

clearinghouseState defaults to the perp sub-account. Pass accountType: 'outcome' for the prediction sub-account.

userFills, historicalOrders, and userNonFundingLedgerUpdates take an account filter. History methods spell the perp account 'perps', while ledger updates use the singular 'perp' and the field name accountTypes. Add 'outcome' to either to include prediction activity.

Fees

feeTierInfo and feeTierRates answer different questions:

const ladder = await sdk.info.feeTierInfo()
 
const effectiveRates = await sdk.info.feeTierRates({
  accountType: 'perp',
  exchangeId: 0,
  user: '0xOwnerAddress',
})
  • feeTierInfo returns the static tier ladder configured for an exchange.
  • feeTierRates returns effective rates for an account type and optional user.
  • userFees({ user, asset: '1' }) returns the user's fee state for one instrument.

The SDK maps feeTierInfo({ exchangeId }) to the node's exchange_id field automatically.

Builder Codes

Nine read methods cover Builder Code approvals, on-chain reward state, and aggregated analytics:

MethodUse
approvedBuilders({ user })All builders the user approved, with percentage-string rates
maxBuilderFee({ user, builder })One approved rate in tenths of a basis point, 0 when unapproved
builderState({ user })The builder's on-chain accrued, claimable, and claimed rewards
builderMeOverview({ user })Builder dashboard overview from aggregate metrics
builderMeDailySeries({ user, ... })Daily fee or user-count series
builderMeShare({ user, ... })Fee share by trading user or instrument
builderMeEarned({ user, ... })Paginated earnings aggregated by order
builderMeClaimed({ user, ... })Paginated reward claim history
builderMeClaimable({ user })Claimable balance and lifetime earned/claimed totals
const approvals = await sdk.info.approvedBuilders({
  user: '0xOwnerAddress',
})
 
if (!Array.isArray(approvals)) {
  throw new Error(approvals.message)
}

approvedBuilders and maxBuilderFee take the trading user's address in user. builderState and every builderMe* method take the builder's address in user. These methods return either their data or an { message } error object, so narrow the result before reading fields. The full workflow is in Builder Codes.

Outcome

Outcome reads come from two layers, and the distinction matters when results disagree.

Gateway aggregations join the indexed event catalog with live book-derived pricing. They are what discovery UIs want, but they can briefly lag consensus.

MethodUse
outcomeMeta(params)Events with nested markets, pricing, volume, and settlement state
outcomeAssetCtxs({ instrumentIds })24-hour price and volume statistics, batched
outcomeProbability({ instrumentId, range })Historical YES probability samples
outcomeSeriesTimeline(params)Past, current, and upcoming windows of a recurring series
cryptoPrice(params)Open and settlement price of one crypto window
cryptoPriceHistory(params)Ascending price samples that seed a chart

Fullnode reads are consensus truth.

MethodUse
outcomePositions({ user })Open positions in the outcome sub-account
outcomeFrontendOpenOrders({ user })Active outcome orders

outcomeMeta returns two different shapes. An eventSlug point lookup returns the event object directly; every other query returns a paged envelope. Narrow with the exported guard:

import { isOutcomeMetaPage } from 'txflow-typescript-sdk'
 
const result = await sdk.info.outcomeMeta({ exchangeId: 1, limit: 20 })
const events = isOutcomeMetaPage(result) ? result.events : [result]

outcomeMeta responses use snake_case (instrument_id, best_bid, next_cursor), unlike the rest of the SDK, because the gateway serves the indexer catalog verbatim.

outcomePositions returns only the assetPositions slice, with no margin summary and no withdrawable. For account totals and the withdrawable balance call clearinghouseState({ user, accountType: 'outcome', exchangeId: 1 }). The YES and NO legs of one market are separate records distinguished by the sign of position.szi.

const user = '0xOwnerAddress'
 
const [positions, account] = await Promise.all([
  sdk.info.outcomePositions({ user }),
  sdk.info.clearinghouseState({ user, accountType: 'outcome', exchangeId: 1 }),
])

Sorting by sortBy: 'endingSoon' carries its own direction — send it without sortOrder. Page size caps at 50.

Risk calculators

Estimate order effects before signing:

const maxPositions = await sdk.info.getMaxPositions({
  user: '0xOwnerAddress',
  asset: '1',
  orderType: 'MARKET',
})
 
const liquidationPrices = await sdk.info.getLiquidationPrices({
  user: '0xOwnerAddress',
  asset: '1',
  orderType: 'MARKET',
  buyQuantity: '0.001',
  sellQuantity: '0.001',
})

For orderType: 'LIMIT', both buyPrice and sellPrice are required.

TP/SL lookup direction

Two similarly named methods traverse the relationship in opposite directions:

const position = await sdk.info.tpslOrderPosition({
  oid: 123456,
})

This method currently accepts a JavaScript number; only pass order ids within the safe-integer range.

Error behavior

Info methods throw on HTTP and transport failures:

import {
  NetworkError,
  TxFlowApiError,
} from 'txflow-typescript-sdk'
 
try {
  await sdk.info.l2Book({ coin: '1' })
} catch (error) {
  if (error instanceof TxFlowApiError) {
    console.error(error.code, error.message, error.details)
  } else if (error instanceof NetworkError) {
    console.error('The node did not respond')
  }
}

There is no generic raw Info method. The public surface consists of named, typed methods so unsupported request shapes fail during development.

Next steps