Skip to Content
DevelopersMarket MakersMarket Maker Quickstart

Market Maker Quickstart

Get a simple market maker running in under 10 minutes. This guide shows how to place two-sided quotes that automatically update with oracle prices.

Prerequisites

  • Node.js + TypeScript project
  • Velocity SDK installed: npm i @velocity-exchange/sdk
  • Funded Solana account with collateral (dUSDT on devnet; USDC on mainnet)
  • Basic familiarity with async/await

⚠️ RPC choice matters: The default https://api.mainnet-beta.solana.com is rate-limited and unsuitable for production bots. Use a dedicated RPC provider (Helius, Triton, etc.) or you’ll hit 429 errors within minutes. For WebSocket subscriptions, you need a provider that supports accountSubscribe.

Step 1: Initialize VelocityClient

Set up your connection and subscribe to market data.

import { Connection } from "@solana/web3.js"; import { Wallet, VelocityClient, loadKeypair } from "@velocity-exchange/sdk"; const connection = new Connection("https://api.mainnet-beta.solana.com"); const wallet = new Wallet(loadKeypair("~/.config/solana/id.json")); const velocityClient = new VelocityClient({ connection, wallet, env: "mainnet-beta", }); await velocityClient.subscribe(); // Initialize your user account (if first time) // const [txSig] = await velocityClient.initializeUserAccount(0);
Class VelocityClientReference ↗

# VelocityClient Main entry point for interacting with Velocity Exchange from TypeScript. A single instance wraps one `authority` wallet (optionally trading on behalf of multiple sub-accounts via `authoritySubAccountMap`, or as a delegate via `includeDelegates`) and owns: - the Anchor `program` handle and RPC `connection`/`provider`, - the account subscription (`accountSubscriber`) that streams State, PerpMarket, SpotMarket, and oracle accounts (websocket, polling, or grpc — selected via `VelocityClientConfig.accountSubscription`), - the set of loaded `User` / `UserStats` objects for this authority's sub-accounts, - the `txSender` / `txHandler` used to build, sign, and send every instruction the class exposes.

Most instruction-building methods come in pairs: `doThing(...)` builds the instruction(s), wraps them in a transaction, signs, sends, and confirms; `getDoThingIx(...)` (or `getDoThingIxs(...)`) only builds and returns the raw `TransactionInstruction`(s) for callers composing their own transaction (e.g. bundling several instructions, or using a custom `txParams`/lookup-table setup).

Almost every account-touching method requires `subscribe()` to have resolved and the target sub-account's `User` to be loaded first — see `subscribe`, `addUser`, `switchActiveUser`.

PropertyTypeRequired
connection
Connection
Yes
wallet
IWallet
Yes
program
VelocityProgram
Yes
provider
AnchorProvider
Yes
env
VelocityEnv
Yes
opts
ConfirmOptions
Yes
useHotWalletAdmin
boolean
No
users
Map<string, User>
Yes
userStats
UserStats
No
userStatsAccountPublicKey
PublicKey
No
activeSubAccountId
number | undefined
Yes
userAccountSubscriptionConfig
UserSubscriptionConfig
Yes
userStatsAccountSubscriptionConfig
UserStatsSubscriptionConfig
Yes
accountSubscriber
VelocityClientAccountSubscriber
Yes
eventEmitter
StrictEventEmitter<EventEmitter, VelocityClientAccountEvents>
Yes
metricsEventEmitter
StrictEventEmitter<EventEmitter, VelocityClientMetricsEvents>
Yes
_isSubscribed
boolean
Yes
txSender
TxSender
Yes
perpMarketLastSlotCache
Map<number, number>
Yes
spotMarketLastSlotCache
Map<number, number>
Yes
mustIncludePerpMarketIndexes
Set<number>
Yes
mustIncludeSpotMarketIndexes
Set<number>
Yes
authority
PublicKey
Yes
marketLookupTables
PublicKey[]
Yes
lookupTableAccounts
AddressLookupTableAccount[]
No
includeDelegates
boolean
No
authoritySubAccountMap
Map<string, number[]>
No
skipLoadUsers
boolean
No
txVersion
TransactionVersion
Yes
txParams
TxParams
Yes
enableMetricsEvents
boolean
No
txHandler
TxHandler
Yes
isSubscribed
boolean
Whether this client has completed `subscribe()` and its underlying `accountSubscriber` is still actively streaming account updates. Most account-reading and instruction-building methods assume this is `true`; call `subscribe()` first if it is `false`. Overrides the internal subscribed flag directly, without touching `accountSubscriber`. Intended for advanced/test callers managing subscription state manually; regular callers should use `subscribe()` / `unsubscribe()` instead.
Yes
getPrePlaceOrderIxs
any
Yes
getUserMapKey
(subAccountId: number, authority: PublicKey) => string
Builds the internal `Map` key used to index `this.users` for a given sub-account/authority pair.
Yes
createUser
(subAccountId: number, accountSubscriptionConfig: UserSubscriptionConfig, authority?: PublicKey | undefined) => User
Constructs (but does not subscribe) a `User` for the given sub-account/authority.
Yes
subscribe
() => Promise<boolean>
Subscribes the client to on-chain state: loads and subscribes to the sub-account(s) implied by the constructor/`updateWallet` config (`addAndSubscribeToUsers`), subscribes the `accountSubscriber` (State, PerpMarket, SpotMarket, oracle accounts), and, if `userStats` was configured, subscribes it too. Must be called (and resolve `true`) before using most other methods on this class.
Yes
subscribeUsers
() => Promise<boolean>[]
Subscribes every currently-loaded `User` in `this.users`. Does not add new users or subscribe `accountSubscriber`/`userStats` — see `subscribe()` for full client subscription.
Yes
fetchAccounts
() => Promise<void>
Forces every loaded `User`, the `accountSubscriber`, and (if present) `userStats` to fetch fresh account data from RPC immediately, bypassing the normal websocket/polling cadence. Useful in tests (e.g. local validator) where a just-landed transaction's effects need to be visible without waiting for the next update.
Yes
unsubscribe
() => Promise<void>
Unsubscribes all loaded users, the `accountSubscriber`, and (if present) `userStats`, and sets `isSubscribed` to `false`. Does not clear `this.users` — the `User` objects remain but stop receiving updates until re-subscribed.
Yes
unsubscribeUsers
() => Promise<void>[]
Unsubscribes every currently-loaded `User` in `this.users` without clearing the map or touching `accountSubscriber`/`userStats`.
Yes
statePublicKey
PublicKey
No
getStatePublicKey
() => Promise<PublicKey>
Returns the `State` account PDA for this program, computing and caching it on first call.
Yes
signerPublicKey
PublicKey
No
getSignerPublicKey
() => PublicKey
Returns the program's PDA signer (used as the authority for vault CPIs), computing and caching it on first call. Synchronous — the signer PDA has no seeds that require an on-chain lookup.
Yes
getStateAccount
() => StateAccount
Returns the last account-subscriber-cached `State` account. Does not hit RPC.
Yes
forceGetStateAccount
() => Promise<StateAccount>
Like `getStateAccount` but forces a fresh RPC fetch first. Useful for anchor tests where an update needs to be observed immediately rather than waiting for the next subscription push.
Yes
getPerpMarketAccount
(marketIndex: number) => PerpMarketAccount | undefined
Returns the last account-subscriber-cached `PerpMarketAccount` for a market index. Does not hit RPC. The market must be one of the indexes/lookup-tables this client subscribed to.
Yes
getPerpMarketAccountOrThrow
(marketIndex: number) => PerpMarketAccount
Like `getPerpMarketAccount` but throws if the market is not loaded, for call sites that require a guaranteed account.
Yes
forceGetPerpMarketAccount
(marketIndex: number) => Promise<PerpMarketAccount | undefined>
Like `getPerpMarketAccount` but forces a fresh RPC fetch, retrying up to 10 times (one fetch per attempt) until the market account appears. Useful in anchor tests right after `initializePerpMarket` where the market may not yet be visible to the subscriber.
Yes
getPerpMarketAccounts
() => PerpMarketAccount[]
Returns all currently-loaded `PerpMarketAccount`s (does not hit RPC).
Yes
getSpotMarketAccount
(marketIndex: number) => SpotMarketAccount | undefined
Returns the last account-subscriber-cached `SpotMarketAccount` for a market index. Does not hit RPC.
Yes
getSpotMarketAccountOrThrow
(marketIndex: number) => SpotMarketAccount
Like `getSpotMarketAccount` but throws if the market is not loaded, for call sites that require a guaranteed account.
Yes
forceGetSpotMarketAccount
(marketIndex: number) => Promise<SpotMarketAccount | undefined>
Like `getSpotMarketAccount` but forces a fresh RPC fetch first. Useful for anchor tests where an update needs to be observed immediately.
Yes
getSpotMarketAccounts
() => SpotMarketAccount[]
Returns all currently-loaded `SpotMarketAccount`s (does not hit RPC).
Yes
getQuoteSpotMarketAccount
() => SpotMarketAccount
Convenience accessor for the quote spot market (`QUOTE_SPOT_MARKET_INDEX`, always index 0), i.e. the USDC market used to denominate collateral/PnL across the protocol.
Yes
getOraclePriceDataAndSlot
(oraclePublicKey: PublicKey, oracleSource: OracleSource) => DataAndSlot<OraclePriceData> | undefined
Returns the last subscriber-cached oracle price data for a given oracle account/source. Does not hit RPC.
Yes
fetchAllLookupTableAccounts
() => Promise<AddressLookupTableAccount[]>
Fetches and caches the `AddressLookupTableAccount`s for `this.marketLookupTables`, so transaction builders can include them to shrink versioned-transaction size. Subsequent calls return the cached result.
Yes
getTxVersionForNewWallet
any
Yes
updateWallet
(newWallet: IWallet, subAccountIds?: number[] | undefined, activeSubAccountId?: number | undefined, includeDelegates?: boolean | undefined, authoritySubaccountMap?: Map<string, number[]> | undefined) => Promise<...>
Swaps the wallet/authority this client transacts and subscribes as, rebuilding the Anchor `provider`/`program`, `txSender`, `txHandler`, `userStats`, and (if already subscribed) every loaded `User` for the new authority. Use this instead of constructing a new `VelocityClient` when a UI wallet-adapter connection changes. At most one of `includeDelegates`, `subAccountIds`, or `authoritySubaccountMap` may be passed (mirrors the constructor's mutual-exclusion rule); `subAccountIds` is shorthand for `authoritySubaccountMap = &#123; [newWallet.publicKey]: subAccountIds &#125;`.
Yes
emulateAccount
(emulateAuthority: PublicKey) => Promise<boolean>
Update the subscribed accounts to a given authority, while leaving the connected wallet intact. This allows a user to emulate another user's account on the UI and sign permissionless transactions with their own wallet. `authority` is repointed to `emulateAuthority` and `includeDelegates` is forced to `true`, but the connected `wallet` (and thus its signing key) is unchanged — instructions that require the emulated authority's own signature (e.g. deposits from its wallet) will still fail; only actions the connected wallet is independently authorized for (e.g. as a delegate, or read-only views) will succeed.
Yes
switchActiveUser
(subAccountId: number, authority?: PublicKey | undefined) => Promise<void>
Sets the client's `activeSubAccountId`/`authority` (the sub-account used by default when a method's `subAccountId` param is omitted). If `authority` changes, re-derives and re-subscribes `userStats` for the new authority (assumed unnecessary when only the sub-account id changes for the same authority). Does not load or subscribe the target `User` itself — call `addUser` first if it isn't already loaded.
Yes
addUser
(subAccountId: number, authority?: PublicKey | undefined, userAccount?: UserAccount | undefined) => Promise<boolean>
Loads and subscribes a `User` for a sub-account, adding it to `this.users`. If a subscribed `User` for this sub-account/authority is already loaded, returns `true` immediately without re-subscribing.
Yes
addAndSubscribeToUsers
(authority?: PublicKey | undefined) => Promise<boolean>
Adds and subscribes to users based on params set by the constructor or by updateWallet. If `authoritySubAccountMap` is non-empty, loads exactly the (authority, subAccountId) pairs it lists. Otherwise fetches every on-chain `UserAccount` owned by `authority` (defaulting to `this.wallet.publicKey`), plus (when `includeDelegates` is `true`) every account this authority is a delegate for, and loads all of them. If `activeSubAccountId` is not already set, the first loaded account becomes active. A no-op returning `true` if `skipLoadUsers` is set (e.g. no real wallet configured).
Yes
getInitializeUserAccountIxs
(subAccountId?: number | undefined, name?: string | undefined, referrerInfo?: ReferrerInfo | undefined, poolId?: number | undefined) => Promise<[TransactionInstruction[], PublicKey]>
Builds the instructions to initialize a user (sub-account) for `this.authority`, without sending a transaction. For `subAccountId === 0`, also prepends `initializeUserStats` if the authority's `UserStats` account doesn't already exist on-chain (every authority needs exactly one, created alongside its first sub-account).
Yes
initializeUserAccount
(subAccountId?: number | undefined, name?: string | undefined, referrerInfo?: ReferrerInfo | undefined, txParams?: TxParams | undefined) => Promise<[...]>
Initializes a new user (sub-account) for `this.authority` on-chain, then loads and subscribes it into `this.users` via `addUser`. See `getInitializeUserAccountIxs` for parameter semantics and the implicit `UserStats` creation for `subAccountId === 0`.
Yes
getInitializeUserStatsIx
(overrides?: { externalWallet?: PublicKey; } | undefined) => Promise<TransactionInstruction>
Builds the `initializeUserStats` instruction for `this.authority`. Every authority needs exactly one `UserStats` account (created automatically by `getInitializeUserAccountIxs`/ `initializeUserAccount` alongside sub-account 0 if missing); call this directly only when building a custom initialization flow.
Yes
initializeSignedMsgUserOrders
(authority: PublicKey, numOrders: number, txParams?: TxParams | undefined) => Promise<[string, PublicKey]>
Initializes the `SignedMsgUserOrders` account for `authority`, which caches recently-submitted off-chain signed (SignedMsg / "swift") order messages so keepers can look them up and verify duplicates on-chain. Required once per authority before that authority's signed-message orders can be placed.
Yes
getInitializeSignedMsgUserOrdersAccountIx
(authority: PublicKey, numOrders: number, overrides?: { externalWallet?: PublicKey; } | undefined) => Promise<[PublicKey, TransactionInstruction]>
Builds the `initializeSignedMsgUserOrders` instruction. See `initializeSignedMsgUserOrders` for semantics.
Yes
resizeSignedMsgUserOrders
(authority: PublicKey, numOrders: number, userSubaccountId?: number | undefined, txParams?: TxParams | undefined) => Promise<string>
Grows an existing `SignedMsgUserOrders` account to hold more order-message slots. The program only allows growing, never shrinking.
Yes
getResizeSignedMsgUserOrdersInstruction
(authority: PublicKey, numOrders: number, userSubaccountId?: number | undefined) => Promise<TransactionInstruction>
Builds the `resizeSignedMsgUserOrders` instruction. See `resizeSignedMsgUserOrders` for semantics.
Yes
initializeSignedMsgWsDelegatesAccount
(authority: PublicKey, delegates?: PublicKey[] | undefined, txParams?: TxParams | undefined) => Promise<string>
Initializes `authority`'s `SignedMsgWsDelegates` account, which lists wallets authorized to co-sign/relay that authority's signed-message ("swift") orders over a websocket connection without holding general trading authority.
Yes
getInitializeSignedMsgWsDelegatesAccountIx
(authority: PublicKey, delegates?: PublicKey[] | undefined) => Promise<TransactionInstruction>
Builds the `initializeSignedMsgWsDelegates` instruction. See `initializeSignedMsgWsDelegatesAccount` for semantics.
Yes
initializeRevenueShare
(authority: PublicKey, txParams?: TxParams | undefined) => Promise<string>
Initializes the per-authority `RevenueShare` account, which accumulates that authority's lifetime referrer and builder fee-share rewards. One per authority (not per sub-account); an authority must have this before it can earn referrer or builder revenue share.
Yes
getInitializeRevenueShareIx
(authority: PublicKey, overrides?: { payer?: PublicKey; } | undefined) => Promise<TransactionInstruction>
Builds the `initializeRevenueShare` instruction. See `initializeRevenueShare` for semantics.
Yes
initializeRevenueShareEscrow
(authority: PublicKey, numOrders: number, txParams?: TxParams | undefined) => Promise<string>
Initializes `authority`'s `RevenueShareEscrow` account — the per-user account that tracks pending builder-fee orders and the list of builders this user has approved (`approvedBuilders`), required to place orders carrying a builder fee. On creation, `escrow.referrer` is copied from the authority's existing `UserStats.referrer`, if any.
Yes
getInitializeRevenueShareEscrowIx
(authority: PublicKey, numOrders: number, overrides?: { payer?: PublicKey; } | undefined) => Promise<TransactionInstruction>
Builds the `initializeRevenueShareEscrow` instruction. See `initializeRevenueShareEscrow` for semantics.
Yes
resizeRevenueShareEscrowOrders
(authority: PublicKey, numOrders: number, txParams?: TxParams | undefined) => Promise<string>
Grows `authority`'s `RevenueShareEscrow` order slots. On-chain rejects `numOrders` smaller than the current slot count (shrinking is not supported).
Yes
getResizeRevenueShareEscrowOrdersIx
(authority: PublicKey, numOrders: number) => Promise<TransactionInstruction>
Builds the `resizeRevenueShareEscrowOrders` instruction. See `resizeRevenueShareEscrowOrders` for semantics.
Yes
changeApprovedBuilder
(builder: PublicKey, maxFeeTenthBps: number, add: boolean, txParams?: TxParams | undefined) => Promise<string>
Adds, updates, or revokes an approved builder in the caller's own `RevenueShareEscrow` (`this.wallet.publicKey` unless `overrides.authority` is set on the underlying ix). This is the *user's* opt-in that lets `builder` attach a builder fee (capped at `maxFeeTenthBps`) to orders this user places — it does not itself submit any order. `maxFeeTenthBps` is in tenths of a basis point (1 unit = 0.001%, i.e. `10_000` tenth-bps = 1%).
Yes
getChangeApprovedBuilderIx
(builder: PublicKey, maxFeeTenthBps: number, add: boolean, overrides?: { authority?: PublicKey; payer?: PublicKey; } | undefined) => Promise<TransactionInstruction>
Builds the `changeApprovedBuilder` instruction. See `changeApprovedBuilder` for semantics; unlike the wrapper, `overrides.authority` lets you target an escrow other than the connected wallet's.
Yes
addSignedMsgWsDelegate
(authority: PublicKey, delegate: PublicKey, txParams?: TxParams | undefined) => Promise<string>
Authorizes `delegate` on `authority`'s existing `SignedMsgWsDelegates` account (must already be initialized via `initializeSignedMsgWsDelegatesAccount`). Signed by `this.wallet.publicKey`, which must be `authority`.
Yes
getAddSignedMsgWsDelegateIx
(authority: PublicKey, delegate: PublicKey) => Promise<TransactionInstruction>
Builds the `changeSignedMsgWsDelegateStatus` instruction with `add = true`. See `addSignedMsgWsDelegate` for semantics.
Yes
removeSignedMsgWsDelegate
(authority: PublicKey, delegate: PublicKey, txParams?: TxParams | undefined) => Promise<string>
Revokes `delegate`'s authorization on `authority`'s `SignedMsgWsDelegates` account. Signed by `this.wallet.publicKey`, which must be `authority`.
Yes
getRemoveSignedMsgWsDelegateIx
(authority: PublicKey, delegate: PublicKey) => Promise<TransactionInstruction>
Builds the `changeSignedMsgWsDelegateStatus` instruction with `add = false`. See `removeSignedMsgWsDelegate` for semantics.
Yes
getInitializeUserInstructions
any
Yes
getNextSubAccountId
() => Promise<number>
Returns the sub-account id that would be assigned to the next sub-account created for `this.wallet.publicKey` (i.e. `UserStats.numberOfSubAccountsCreated`, which increments on every `initializeUser` and never reuses ids after `deleteUser`). Prefers the already-loaded `userStats` subscription; falls back to an RPC fetch if it isn't loaded or has no cached account yet.
Yes
initializeReferrerName
(name: string) => Promise<string>
Registers `this.wallet`'s sub-account 0 as a referrer under a human-readable `name`, creating a `ReferrerNameAccount` PDA keyed by that name. Other users can then look up this authority's `referrer`/`referrerStats` public keys by name (see `getReferrerNameAccountsForAuthority`) when passing `referrerInfo` to `initializeUserAccount`. Fails if the name is already taken (PDA already initialized).
Yes
updateUserName
(name: string, subAccountId?: number | undefined) => Promise<string>
Updates the display name stored on a sub-account. Signed by `this.wallet.publicKey`, which must be the sub-account's authority.
Yes
updateUserCustomMarginRatio
(updates: { marginRatio: number; subAccountId: number; }[], txParams?: TxParams | undefined) => Promise<string>
Sets a per-sub-account custom (higher) minimum margin ratio for one or more sub-accounts in a single transaction, self-imposing a lower max leverage than the market default. Signed by `this.wallet.publicKey` for each sub-account's authority.
Yes
getUpdateUserCustomMarginRatioIx
(marginRatio: number, subAccountId?: number | undefined) => Promise<TransactionInstruction>
Builds the `updateUserCustomMarginRatio` instruction for a single sub-account. As a side effect, ensures the target sub-account is loaded via `addUser` before building the instruction. See `updateUserCustomMarginRatio` for unit/semantics.
Yes
getUpdateUserPerpPositionCustomMarginRatioIx
(perpMarketIndex: number, marginRatio: number, subAccountId?: number | undefined, overrides?: { userAccountPublicKey?: PublicKey; authority?: PublicKey; signingAuthority?: PublicKey; } | undefined) => Promise<...>
Builds the instruction to set a custom minimum margin ratio for a single open perp position (rather than the whole sub-account), letting a position use different effective max leverage than the sub-account default. Used internally by `getPrePlaceOrderIxs` to implement per-order `positionMaxLev`.
Yes
updateUserPerpPositionCustomMarginRatio
(perpMarketIndex: number, marginRatio: number, subAccountId?: number | undefined, txParams?: TxParams | undefined) => Promise<string>
Sends the instruction built by `getUpdateUserPerpPositionCustomMarginRatioIx`. See that method for semantics/units.
Yes
getUpdateUserMarginTradingEnabledIx
(marginTradingEnabled: boolean, subAccountId?: number | undefined, userAccountPublicKey?: PublicKey | undefined) => Promise<TransactionInstruction>
Builds the instruction to toggle a sub-account's "margin trading enabled" flag, which permits borrowing against spot collateral (multiple simultaneous spot borrows / cross-margined spot). It is incompatible with holding a position in an `Isolated`-tier perp market — enabling it while such a position is open, or opening one while it's enabled, is rejected on-chain. As a side effect, ensures the target sub-account is loaded via `addUser`.
Yes
updateUserMarginTradingEnabled
(updates: { marginTradingEnabled: boolean; subAccountId: number; }[]) => Promise<string>
Sends instructions built by `getUpdateUserMarginTradingEnabledIx` for one or more sub-accounts in a single transaction. See that method for semantics.
Yes
getUpdateUserDelegateIx
(delegate: PublicKey, overrides: { subAccountId?: number; userAccountPublicKey?: PublicKey; authority?: PublicKey; }) => Promise<TransactionInstruction>
Builds the instruction to set (or clear, with `PublicKey.default`) the delegate authority on a sub-account. The delegate can sign most trading instructions (place/cancel orders, etc.) on the sub-account's behalf, but `withdraw` always requires the true owning `authority`'s own signature (delegates can never withdraw). A delegate-initiated internal transfer of the sub-account's collateral to another of the owner's sub-accounts is possible only via `transferDepositByDelegate`, and only once the owner has separately opted in via `updateUserAllowDelegateTransfer`.
Yes
updateUserDelegate
(delegate: PublicKey, subAccountId?: number | undefined) => Promise<string>
Sends the `updateUserDelegate` instruction for `this.wallet.publicKey`'s sub-account. See `getUpdateUserDelegateIx` for full semantics.
Yes
getUpdateUserAllowDelegateTransferIx
(allowDelegateTransfer: boolean) => Promise<TransactionInstruction>
Builds the instruction to set the `allowDelegateTransfer` opt-in flag on `this.wallet.publicKey`'s `UserStats` account. This flag gates `transferDepositByDelegate` across *all* of this authority's sub-accounts — if it is `false` (the default), any delegate-initiated internal transfer attempt is rejected on-chain regardless of that sub-account's delegate. It does not affect direct deposits/withdrawals, which are unaffected by delegate status.
Yes
updateUserAllowDelegateTransfer
(allowDelegateTransfer: boolean) => Promise<string>
Sends the instruction built by `getUpdateUserAllowDelegateTransferIx`. See that method for semantics.
Yes
updateUserAdvancedLp
(updates: { advancedLp: boolean; subAccountId: number; }[]) => Promise<string>
Sends instructions built by `getUpdateAdvancedDlpIx` for one or more sub-accounts. **Currently non-functional**: the on-chain `update_user_advanced_lp` instruction handler is commented out of the program's Anchor `#[program]` module (see `programs/velocity/src/lib.rs`) and is absent from the generated IDL, so `program.instruction.updateUserAdvancedLp` does not exist and this call will throw at runtime until the instruction is re-enabled on-chain.
Yes
getUpdateAdvancedDlpIx
(advancedLp: boolean, subAccountId: number) => Promise<any>
Builds the (currently unavailable — see `updateUserAdvancedLp`) `updateUserAdvancedLp` instruction, which would flag a sub-account as an "advanced LP" participant.
Yes
updateUserReduceOnly
(updates: { reduceOnly: boolean; subAccountId: number; }[]) => Promise<string>
Sends instructions built by `getUpdateUserReduceOnlyIx` for one or more sub-accounts in a single transaction. See that method for semantics.
Yes
getUpdateUserReduceOnlyIx
(reduceOnly: boolean, subAccountId: number) => Promise<TransactionInstruction>
Builds the instruction to toggle a sub-account's reduce-only status. When reduce-only, orders on the sub-account may only decrease existing positions, never open or increase one.
Yes
updateUserPoolId
(updates: { poolId: number; subAccountId: number; }[]) => Promise<string>
Sends instructions built by `getUpdateUserPoolIdIx` for one or more sub-accounts in a single transaction. See that method for semantics.
Yes
getUpdateUserPoolIdIx
(poolId: number, subAccountId: number) => Promise<TransactionInstruction>
Builds the instruction to move a sub-account into a different isolated pool. On-chain, re-validates the sub-account still meets its initial margin requirement after the switch using only markets/oracles passed via `remaining_accounts` — the caller (this method doesn't add any) must supply those if the sub-account has open deposits/positions, or the ix will fail.
Yes
fetchAllUserAccounts
(includeIdle?: boolean | undefined) => Promise<ProgramAccount<UserAccount>[]>
Fetches every `User` account that exists on-chain for this program via `getProgramAccounts` (with a `memcmp` filter, not restricted to this client's authority). Expensive — intended for indexers/ admin tooling, not per-trade calls.
Yes
getUserAccountsForDelegate
(delegate: PublicKey) => Promise<UserAccount[]>
Fetches (via RPC `memcmp` filter, not the account subscriber) every on-chain `User` account whose `delegate` field equals `delegate`, i.e. every sub-account this wallet can trade on behalf of as a delegate.
Yes
getUserAccountsAndAddressesForAuthority
(authority: PublicKey) => Promise<ProgramAccount<UserAccount>[]>
Fetches (via RPC, not the account subscriber) every on-chain `User` account owned by `authority`, with each account's PDA address included.
Yes
getUserAccountsForAuthority
(authority: PublicKey) => Promise<UserAccount[]>
Fetches (via RPC, not the account subscriber) every on-chain `User` account owned by `authority`. Used internally by `addAndSubscribeToUsers` to discover an authority's sub-accounts.
Yes
getReferredUserStatsAccountsByReferrer
(referrer: PublicKey) => Promise<UserStatsAccount[]>
Fetches (via RPC `memcmp` filter) every `UserStats` account whose `referrer` field equals `referrer`, i.e. every authority that was referred by this referrer.
Yes
getReferrerNameAccountsForAuthority
(authority: PublicKey) => Promise<ReferrerNameAccount[]>
Fetches (via RPC `memcmp` filter) every `ReferrerNameAccount` registered by `authority` via `initializeReferrerName`.
Yes
deleteUser
(subAccountId?: number | undefined, txParams?: TxParams | undefined) => Promise<string>
Deletes a sub-account owned by `this.wallet.publicKey` and unsubscribes/removes it from `this.users`. On-chain requires the sub-account to be fully closed out: no open perp/spot positions, no open orders, not bankrupt, not being liquidated, and (unless idle) sub-account 0 of a referrer cannot be deleted at all. If the protocol charges a `maxInitializeUserFee` and the account's `UserStats` is younger than ~13 days, the sub-account must also be marked `idle`.
Yes
getUserDeletionIx
(userAccountPublicKey: PublicKey) => Promise<TransactionInstruction>
Builds the `deleteUser` instruction. See `deleteUser` for on-chain preconditions.
Yes
forceDeleteUser
(userAccountPublicKey: PublicKey, userAccount: UserAccount, txParams?: TxParams | undefined) => Promise<string>
Keeper-only instruction: force-cancels all open orders and deletes/closes an inactive, near-zero equity user account, refunding remaining rent to `userAccount.authority`. Requires the signer (`this.wallet.publicKey`) to hold the `UserFlag` hot-role. On-chain, requires the account's total equity to be under `QUOTE_PRECISION / 20` (0.05 USDC, QUOTE_PRECISION = 1e6) and (outside `anchor-test` builds) at least ~3 months of inactivity since `lastActiveSlot`. Not for self-service account deletion — see `deleteUser` for that.
Yes
getForceDeleteUserIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount) => Promise<TransactionInstruction>
Builds the keeper-only `forceDeleteUser` instruction, assembling `remaining_accounts` for the account's non-empty spot positions, its revenue-share escrow (if any order carries a builder fee), and every mint/token-program needed for its open spot balances. See `forceDeleteUser` for on-chain preconditions.
Yes
deleteSignedMsgUserOrders
(txParams?: TxParams | undefined) => Promise<string>
Closes `this.wallet.publicKey`'s `SignedMsgUserOrders` account, refunding its rent to the authority. Requires the account to exist (see `isSignedMsgUserOrdersAccountInitialized`).
Yes
getSignedMsgUserOrdersDeletionIx
(authority: PublicKey) => Promise<any>
Builds the `deleteSignedMsgUserOrders` instruction, signed by `this.wallet.publicKey`. See `deleteSignedMsgUserOrders` for semantics.
Yes
isSignedMsgUserOrdersAccountInitialized
(authority: PublicKey) => Promise<boolean>
Checks if a SignedMsg User Orders account exists for the given authority. The account pubkey is derived using the program ID and authority as seeds. Makes an RPC call to check if the account exists on-chain.
Yes
reclaimRent
(subAccountId?: number | undefined, txParams?: TxParams | undefined) => Promise<string>
Reclaims any lamports on a sub-account's `User` PDA in excess of the rent-exempt minimum for its current size (e.g. left over after the account was resized smaller), transferring them to `this.wallet.publicKey`.
Yes
getReclaimRentIx
(userAccountPublicKey: PublicKey) => Promise<TransactionInstruction>
Builds the `reclaimRent` instruction. See `reclaimRent` for semantics/preconditions.
Yes
getUser
(subAccountId?: number | undefined, authority?: PublicKey | undefined) => User
Looks up an already-loaded `User` from `this.users` (does not fetch or subscribe).
Yes
hasUser
(subAccountId?: number | undefined, authority?: PublicKey | undefined) => boolean
Checks whether a `User` for the given sub-account/authority is currently loaded in `this.users`, without throwing. Safe to call with unresolvable `subAccountId`/`authority` (returns `false`).
Yes
getUsers
() => User[]
Returns every currently-loaded `User`, with sub-accounts owned directly by `this.wallet.publicKey` first, followed by delegated sub-accounts (owned by other authorities this wallet delegates for).
Yes
getUserStats
() => UserStats | undefined
Returns the `UserStats` instance for `this.authority`, if one was constructed (via `config.userStats`, `updateWallet`, `emulateAccount`, or `switchActiveUser`).
Yes
getUserStatsOrThrow
() => UserStats
Like `getUserStats` but throws if there is no UserStats subscription, for call sites that require a guaranteed account.
Yes
fetchReferrerNameAccount
(name: string) => Promise<ReferrerNameAccount | undefined>
Fetches (via RPC, not the account subscriber) the `ReferrerNameAccount` registered for a given name via `initializeReferrerName`.
Yes
getUserStatsAccountPublicKey
() => PublicKey
Returns the `UserStats` account PDA for `this.authority`, computing and caching it on first call (or after `this.authority` changes, since callers like `updateWallet`/`switchActiveUser` reset the cache).
Yes
getUserAccountPublicKey
(subAccountId?: number | undefined, authority?: PublicKey | undefined) => Promise<PublicKey>
Returns the user account PDA for an already-loaded sub-account (does not derive/compute a PDA for a sub-account that hasn't been loaded).
Yes
getUserAccount
(subAccountId?: number | undefined, authority?: PublicKey | undefined) => UserAccount | undefined
Returns the last subscriber-cached `UserAccount` data for a loaded sub-account. Does not hit RPC.
Yes
getUserAccountOrThrow
(subAccountId?: number | undefined, authority?: PublicKey | undefined) => UserAccount
Like `getUserAccount` but throws a named error instead of returning `undefined` when the account has not been loaded yet. Use at call sites that structurally require a loaded account.
Yes
forceGetUserAccount
(subAccountId?: number | undefined, authority?: PublicKey | undefined) => Promise<UserAccount | undefined>
Like `getUserAccount` but forces a fresh RPC fetch first. Useful for anchor tests where an update needs to be observed immediately.
Yes
getUserAccountAndSlot
(subAccountId?: number | undefined, authority?: PublicKey | undefined) => DataAndSlot<UserAccount> | undefined
Like `getUserAccount` but also returns the slot the data was last observed at.
Yes
getSpotPosition
(marketIndex: number, subAccountId?: number | undefined) => SpotPosition | undefined
Returns a sub-account's spot balance entry for a market, if it holds one.
Yes
getQuoteAssetTokenAmount
() => BN
Convenience accessor for the active sub-account's quote (USDC) token amount.
Yes
getIsolatedPerpPositionTokenAmount
(perpMarketIndex: number, subAccountId?: number | undefined) => BN
Returns the isolated deposit token amount backing a sub-account's isolated perp position in a given market (the collateral segregated into that position via `transferIsolatedPerpPositionDeposit`, distinct from the sub-account's general/cross balances).
Yes
getTokenAmount
(marketIndex: number) => BN
Returns the active sub-account's balance in a spot market, converted from the internal scaled balance representation to actual token units.
Yes
convertToSpotPrecision
(marketIndex: number, amount: any) => BN
Converts a human-readable (UI) amount to a market's on-chain spot precision (`10^mint.decimals`). A plain `number` is scaled up via `castNumberToSpotPrecision`; a `BN` is assumed to already be a whole-token count and is scaled by the same factor.
Yes
convertToPerpPrecision
(amount: any) => BN
Converts a human-readable (UI) base-asset amount to `BASE_PRECISION` (1e9), the precision used for perp/spot order base amounts.
Yes
convertToPricePrecision
(amount: any) => BN
Converts a human-readable (UI) price to `PRICE_PRECISION` (1e6).
Yes
mustIncludeMarketsInIx
({ perpMarketIndexes, spotMarketIndexes, }: { perpMarketIndexes: number[]; spotMarketIndexes: number[]; }) => void
Each velocity instruction must include perp and spot market accounts in the ix remaining accounts. Use this function to force a subset of markets to be included in the remaining accounts for every ix built by this client going forward (accumulates into `mustIncludePerpMarketIndexes` / `mustIncludeSpotMarketIndexes`; there is no corresponding "unset" — construct a new client to reset). Useful when an instruction's own logic can't infer every market/oracle it needs (e.g. a cross-margin health check spanning markets the user has no position in yet).
Yes
cachePerpMarketSlot
any
Yes
cacheSpotMarketSlot
any
Yes
getRemainingAccounts
(params: RemainingAccountParams) => AccountMeta[]
Builds the `remaining_accounts` list (perp/spot market + oracle accounts, plus any accounts derived from the given `userAccounts`) that most instructions need appended so the on-chain handler can load the markets/oracles it touches. Always includes markets registered via `mustIncludeMarketsInIx`, in addition to whatever `params` (e.g. `userAccounts`, `writableSpotMarketIndexes`) implies. Used internally by nearly every instruction-building method on this class; exposed publicly for callers assembling custom instructions.
Yes
addPerpMarketToRemainingAccountMaps
(marketIndex: number, writable: boolean, oracleAccountMap: Map<string, AccountMeta>, spotMarketAccountMap: Map<number, AccountMeta>, perpMarketAccountMap: Map<...>) => void
Adds a perp market's account meta (and its oracle and quote spot market) into the shared maps used to de-duplicate remaining accounts across multiple markets in one instruction. The oracle is marked writable only for `prelaunch`-sourced oracles being written to.
Yes
addSpotMarketToRemainingAccountMaps
(marketIndex: number, writable: boolean, oracleAccountMap: Map<string, AccountMeta>, spotMarketAccountMap: Map<number, AccountMeta>) => void
Adds a spot market's account meta (and its oracle, if any) into the shared maps used to de-duplicate remaining accounts across multiple markets in one instruction.
Yes
addBuilderToRemainingAccounts
(builders: PublicKey[], remainingAccounts: AccountMeta[]) => void
Appends each builder's `User` (sub-account 0) and `RevenueShare` account metas to `remainingAccounts` (writable), deduping by pubkey so an authority that is both a builder and a referrer isn't pushed twice — the on-chain revenue-share account loader rejects duplicates and would abort the whole instruction.
Yes
getRemainingAccountMapsForUsers
(userAccounts: UserAccount[]) => { oracleAccountMap: Map<string, AccountMeta>; spotMarketAccountMap: Map<number, AccountMeta>; perpMarketAccountMap: Map<...>; }
Builds the deduplicated oracle/spot-market/perp-market account-meta maps needed to cover every non-empty position across a set of user accounts (e.g. taker + makers in a fill), including the quote spot market whenever a spot position has open orders. All accounts are added read-only.
Yes
getOrder
(orderId: number | undefined, subAccountId?: number | undefined) => Order | undefined
Look up an open order by its program-assigned order ID from the cached user account. `orderId` is the monotonically incrementing u32 counter that the program assigns at placement time — it is not known until the place instruction executes on-chain. Use `getOrderByUserId` when you need to look up an order by the caller-supplied `userOrderId` instead. Returns `undefined` when the order is not found (already filled, cancelled, or the account cache is stale).
Yes
getOrderByUserId
(userOrderId: number, subAccountId?: number | undefined) => Order | undefined
Look up an open order by the caller-supplied `userOrderId` from the cached user account. `userOrderId` is a 1-255 slot chosen by the caller in `OrderParams` and is stable across the life of the order — useful when you need to reference an order before the program-assigned `Order.orderId` is known (e.g. immediately after placing without waiting for confirmation). Use `getOrder` when you have the program-assigned ID. Returns `undefined` when the order is not found (already filled, cancelled, or the account cache is stale).
Yes
getAssociatedTokenAccount
(marketIndex: number, useNative?: boolean | undefined, tokenProgram?: PublicKey | undefined, authority?: PublicKey | undefined, allowOwnerOffCurve?: boolean | undefined) => Promise<...>
Resolves the token account to use for a spot market's mint. For the wrapped-SOL market with `useNative = true` (the default), returns `authority` itself (native SOL, no wrapping) rather than an SPL associated token account; for every other market (or `useNative = false`), returns the derived associated token account address (not guaranteed to exist on-chain — see `getAssociatedTokenAccountCreationIx`).
Yes
createAssociatedTokenAccountIdempotentInstruction
(account: PublicKey, payer: PublicKey, owner: PublicKey, mint: PublicKey, tokenProgram?: PublicKey | undefined) => TransactionInstruction
Builds an `CreateIdempotent` associated-token-account instruction (creates `account` if it doesn't already exist; no-ops without failing if it does), constructed manually rather than via `@solana/spl-token`'s helper.
Yes
getDepositTxnIx
(amount: BN, marketIndex: number, associatedTokenAccount: PublicKey, subAccountId?: number | undefined, reduceOnly?: boolean | undefined, overrides?: { authority?: PublicKey; } | undefined) => Promise<...>
Builds the full instruction sequence for a deposit, without sending a transaction. If `associatedTokenAccount` equals the signer and the market is wrapped SOL, transparently wraps native SOL first (creates a temporary wrapped-SOL account funded with `amount`, deposits from it, then closes it at the end of the same transaction, refunding rent to the signer) — otherwise deposits directly from `associatedTokenAccount`.
Yes
buildSwiftDepositTx
(signedOrderParams: SignedMsgOrderParams, takerInfo: { taker: PublicKey; takerStats: PublicKey; takerUserAccount: UserAccount; signingAuthority: PublicKey; }, depositAmount: BN, depositSpotMarketIndex: number, tradePerpMarketIndex: number, subAccountId: number, takerAssociatedTokenAccount: PublicKey, initSwiftAccoun...
Builds (but does not send) a single transaction that deposits collateral and then places a pre-signed SignedMsg ("swift") taker perp order in one atomic bundle — useful for funding a new or under-collateralized account immediately before submitting an off-chain-signed order. Optionally also initializes the taker's `SignedMsgUserOrders` account (with 8 order slots) first, if it doesn't already exist.
Yes
createDepositTxn
(amount: BN, marketIndex: number, associatedTokenAccount: PublicKey, subAccountId?: number | undefined, reduceOnly?: boolean | undefined, txParams?: TxParams | undefined, initSwiftAccount?: boolean | undefined, overrides?: { ...; } | undefined) => Promise<...>
Builds (via `getDepositTxnIx`) and wraps a full deposit transaction, without sending it. Optionally also initializes the depositor's `SignedMsgUserOrders` account first, if it doesn't already exist. Forces `computeUnits` to `800_000` regardless of `txParams`/`this.txParams`.
Yes
deposit
(amount: BN, marketIndex: number, associatedTokenAccount: PublicKey, subAccountId?: number | undefined, reduceOnly?: boolean | undefined, txParams?: TxParams | undefined, initSwiftAccount?: boolean | undefined, overrides?: { ...; } | undefined) => Promise<...>
Deposits collateral into a spot market for a sub-account: builds (`createDepositTxn`), signs, and sends the transaction, then caches the confirming slot for this market so subsequent instructions built by this client can use the freshest oracle/market data.
Yes
getDepositInstruction
(amount: BN, marketIndex: number, userTokenAccount: PublicKey, subAccountId?: number | undefined, reduceOnly?: boolean | undefined, userInitialized?: boolean | undefined, overrides?: { ...; } | undefined) => Promise<...>
Builds the raw `deposit` instruction (no SOL-wrapping helpers — see `getDepositTxnIx` for the full sequence). Assembles `remaining_accounts` from the target sub-account's current positions (forcing a fresh fetch when `userInitialized` is `true`) plus the market's mint and, if the mint uses a transfer hook, its extra account metas.
Yes
checkIfAccountExists
any
Yes
getWrappedSolAccountCreationIxs
(amount: BN, includeRent?: boolean | undefined, overrides?: { authority?: PublicKey; } | undefined) => Promise<{ ixs: TransactionInstruction[]; signers: Signer[]; pubkey: PublicKey; }>
Builds the instructions to create and fund a temporary wrapped-SOL token account (via `createAccountWithSeed` + `initializeAccount`, no keypair required — derived deterministically from `authority` and a random seed). The caller is responsible for closing it after use (see the `createCloseAccountInstruction` pattern in `getDepositTxnIx`).
Yes
getTokenProgramForSpotMarket
(spotMarketAccount: SpotMarketAccount) => PublicKey
Returns the correct SPL token program (classic or Token-2022) for a spot market's mint, based on its `tokenProgramFlag`.
Yes
isToken2022
(spotMarketAccount: SpotMarketAccount) => boolean
Checks whether a spot market's mint belongs to the Token-2022 program.
Yes
isTransferHook
(spotMarketAccount: SpotMarketAccount) => boolean
Checks whether a spot market's mint has a Token-2022 transfer hook, requiring extra account metas to be appended on any instruction that moves its tokens.
Yes
addTokenMintToRemainingAccounts
(spotMarketAccount: SpotMarketAccount, remainingAccounts: AccountMeta[]) => void
Appends a spot market's mint as a read-only remaining account, but only when the mint is Token-2022 (the classic SPL Token program doesn't need the mint passed for transfers). No-op for classic SPL Token mints.
Yes
addExtraAccountMetasToRemainingAccounts
(mint: PublicKey, remainingAccounts: AccountMeta[]) => Promise<void>
Resolves and appends the Token-2022 transfer-hook program's extra required account metas for a mint. Required on any instruction transferring tokens for a mint where `isTransferHook` is `true` (e.g. deposits/withdrawals/transfers involving that market).
Yes
getAssociatedTokenAccountCreationIx
(tokenMintAddress: PublicKey, associatedTokenAddress: PublicKey, tokenProgram: PublicKey) => TransactionInstruction
Builds a (non-idempotent) instruction to create an associated token account owned by `this.wallet.publicKey`, paid for by `this.wallet.publicKey`.
Yes
createInitializeUserAccountAndDepositCollateralIxs
(amount: BN, userTokenAccount: PublicKey, marketIndex?: number | undefined, subAccountId?: number | undefined, name?: string | undefined, fromSubAccountId?: number | undefined, referrerInfo?: ReferrerInfo | undefined, donateAmount?: any, customMaxMarginRatio?: number | undefined, poolId?: number | undefined, overrid...
Builds the full instruction sequence to create a new sub-account and fund it with an initial deposit in one transaction, without sending it. Handles: initializing `UserStats` (for `subAccountId === 0`) and the `SignedMsgUserOrders` account if missing, wrapping native SOL when depositing/donating SOL, creating the depositor's associated token account for Token-2022 mints if it doesn't exist, sourcing the deposit either from a token account or (if `fromSubAccountId` is given) via an internal transfer from another of the authority's sub-accounts, an optional donation to the market's revenue pool, an optional custom margin ratio, and unwrapping any temporary SOL account at the end.
Yes
createInitializeUserAccountAndDepositCollateral
(amount: BN, userTokenAccount: PublicKey, marketIndex?: number | undefined, subAccountId?: number | undefined, name?: string | undefined, fromSubAccountId?: number | undefined, referrerInfo?: ReferrerInfo | undefined, donateAmount?: any, txParams?: TxParams | undefined, customMaxMarginRatio?: number | undefined, poo...
Builds (via `createInitializeUserAccountAndDepositCollateralIxs`) and wraps the full initialize-and-deposit transaction, without sending it. See that method for parameter semantics.
Yes
initializeUserAccountAndDepositCollateral
(amount: BN, userTokenAccount: PublicKey, marketIndex?: number | undefined, subAccountId?: number | undefined, name?: string | undefined, fromSubAccountId?: number | undefined, referrerInfo?: ReferrerInfo | undefined, donateAmount?: any, txParams?: TxParams | undefined, customMaxMarginRatio?: number | undefined, poo...
Creates a new sub-account and deposits initial collateral into it in a single transaction, then loads and subscribes the new sub-account via `addUser`. See `createInitializeUserAccountAndDepositCollateralIxs` for full parameter semantics.
Yes
initializeUserAccountForDevnet
(subAccountId: number | undefined, name: string | undefined, marketIndex: number, tokenFaucet: TokenFaucet, amount: BN, referrerInfo?: ReferrerInfo | undefined, txParams?: TxParams | undefined) => Promise<...>
Devnet/test-only convenience: mints test tokens from a `TokenFaucet` into a fresh associated token account, then creates a new sub-account and deposits the minted amount, all in one transaction. Not usable on mainnet (no faucet exists there).
Yes
getWithdrawalIxs
(amount: BN, marketIndex: number, associatedTokenAddress: PublicKey, reduceOnly?: boolean | undefined, subAccountId?: number | undefined) => Promise<TransactionInstruction[]>
Builds the full instruction sequence for a withdrawal, without sending a transaction. If `associatedTokenAddress` equals the signer and the market is wrapped SOL, creates a temporary wrapped-SOL account to receive the withdrawal and closes it (unwrapping to native SOL) at the end of the same transaction; otherwise, creates the destination associated token account first if it doesn't already exist.
Yes
withdraw
(amount: BN, marketIndex: number, associatedTokenAddress: PublicKey, reduceOnly?: boolean | undefined, subAccountId?: number | undefined, txParams?: TxParams | undefined) => Promise<...>
Withdraws from a user account. If deposit doesn't already exist, creates a borrow (or increases an existing one) — unless `reduceOnly` is set. Always requires the sub-account's true owning authority to sign (`this.wallet.publicKey`); a delegate cannot withdraw at all, even with `allowDelegateTransfer` enabled.
Yes
withdrawAllDustPositions
(subAccountId?: number | undefined, txParams?: TxParams | undefined, opts?: { dustPositionCountCallback?: (count: number) => void; } | undefined) => Promise<string | undefined>
Fully withdraws every spot market position on a sub-account too small to be worth carrying ("dust", as determined by `User.getSpotMarketAccountsWithDustPosition`), in one transaction. Each withdrawal requests 2x the current token amount with `reduceOnly = true` so the on-chain clamp (see `withdraw`) withdraws exactly the full balance without risking a borrow, regardless of balance drift between calculation and execution.
Yes
getWithdrawIx
(amount: BN, marketIndex: number, userTokenAccount: PublicKey, reduceOnly?: boolean | undefined, subAccountId?: number | undefined) => Promise<TransactionInstruction>
Builds the raw `withdraw` instruction (no SOL-wrapping/ATA-creation helpers — see `getWithdrawalIxs` for the full sequence). Signed by `this.wallet.publicKey`, which must be the sub-account's true owning authority (delegates cannot withdraw).
Yes
transferDeposit
(amount: BN, marketIndex: number, fromSubAccountId: number, toSubAccountId: number, txParams?: TxParams | undefined) => Promise<string>
Transfers a spot balance directly between two sub-accounts owned by `this.wallet.publicKey` (withdraws from `fromSubAccountId`, deposits into `toSubAccountId`) without leaving the program — no token account round-trip. Signed by `this.wallet.publicKey`, which must literally be the `authority` on *both* sub-accounts (this is the owner-to-owner path; a delegate must use `transferDepositByDelegate` instead).
Yes
getTransferDepositIx
(amount: BN, marketIndex: number, fromSubAccountId: number, toSubAccountId: number) => Promise<TransactionInstruction>
Builds the `transferDeposit` instruction. See `transferDeposit` for semantics/preconditions. Uses an already-loaded `from` sub-account's cached data if available (to build `remaining_accounts` from its current positions); otherwise fetches it directly via RPC.
Yes
transferDepositByDelegate
(amount: BN, marketIndex: number, fromSubAccountId: number, toSubAccountId: number, txParams?: TxParams | undefined) => Promise<string>
Like `transferDeposit`, but signed by a *delegate* (`this.wallet.publicKey`) rather than the sub-accounts' owning authority. On-chain requires all of: - the owner has opted in via `updateUserAllowDelegateTransfer(true)` on their `UserStats` — the transfer is rejected outright otherwise, regardless of delegate status on the sub-accounts; - `this.wallet.publicKey` is set as the `delegate` on **both** `fromSubAccountId` and `toSubAccountId` (see `updateUserDelegate`) — a delegate for only one side is not sufficient; - both sub-accounts share the same owning `authority` (this only moves funds within one owner's sub-accounts, never across different owners); - neither sub-account is bankrupt, and `fromSubAccountId !== toSubAccountId`.
Yes
getTransferDepositByDelegateIx
(amount: BN, marketIndex: number, fromSubAccountId: number, toSubAccountId: number) => Promise<TransactionInstruction>
Builds the `transferDepositByDelegate` instruction. See `transferDepositByDelegate` for the full set of on-chain preconditions. Uses an already-loaded `from` sub-account's cached data if available; otherwise fetches it directly via RPC. Sub-accounts are derived under `this.authority` (the sub-accounts' owner), not `this.wallet.publicKey` (the delegate signer).
Yes
transferPools
(depositFromMarketIndex: number, depositToMarketIndex: number, borrowFromMarketIndex: number, borrowToMarketIndex: number, depositAmount: any, borrowAmount: any, fromSubAccountId: number, toSubAccountId: number, txParams?: TxParams | undefined) => Promise<...>
Moves a deposit balance and/or a borrow balance for the same underlying mint between two sub-accounts owned by `this.wallet.publicKey` that sit in *different* isolated pools, in one on-chain instruction (`transferPools`). Unlike `transferDeposit` (which only moves a single spot balance and requires same-pool markets), this requires: `depositFromMarketIndex`/ `depositToMarketIndex` to share a mint but different `poolId`s, `borrowFromMarketIndex`/ `borrowToMarketIndex` to likewise share a mint but different pool ids, and the deposit-from/ borrow-from markets to share `fromSubAccountId`'s pool while the deposit-to/borrow-to markets share `toSubAccountId`'s pool. Both sub-accounts must be re-validated against their initial margin requirement after the move.
Yes
getTransferPoolsIx
(depositFromMarketIndex: number, depositToMarketIndex: number, borrowFromMarketIndex: number, borrowToMarketIndex: number, depositAmount: any, borrowAmount: any, fromSubAccountId: number, toSubAccountId: number, isToNewSubAccount?: boolean | undefined) => Promise<...>
Builds the `transferPools` instruction. See `transferPools` for full semantics/preconditions.
Yes
transferPerpPosition
(fromSubAccountId: number, toSubAccountId: number, marketIndex: number, amount: BN, txParams?: TxParams | undefined) => Promise<string>
Moves all or part of an open perp position from one sub-account to another via the `transferPerpPosition` instruction, settling funding on both sides first. The signer (`this.wallet.publicKey`) must independently satisfy `can_sign_for_user` (be the owning `authority` or the sub-account's `delegate`) on *both* `fromSubAccountId` and `toSubAccountId` — unlike `transferDepositByDelegate`, there is no separate `allowDelegateTransfer` opt-in gate, and the two sub-accounts are not required to share the same owning authority.
Yes
getTransferPerpPositionIx
(fromSubAccountId: number, toSubAccountId: number, marketIndex: number, amount: BN) => Promise<TransactionInstruction>
Builds the `transferPerpPosition` instruction. See `transferPerpPosition` for full semantics.
Yes
specialTransferPerpPositionToVamm
(userAccountPublicKey: PublicKey, marketIndex: number, amount?: any, txParams?: TxParams | undefined) => Promise<string>
Special-account-only: transfers all or part of a position on the protocol's designated "vAMM hedger" account directly into the AMM's own inventory, offsetting the vAMM's synthetic position. On-chain requires `userAccountPublicKey`'s `specialUserStatus` to be `VammHedger`, the position's direction to already be opposite the AMM's net inventory (`amm.baseAssetAmountWithAmm`), and the transferred amount to fit within the AMM's available capacity for that direction. Not usable on a regular trading sub-account.
Yes
getSpecialTransferPerpPositionToVammIx
(userAccountPublicKey: PublicKey, marketIndex: number, amount?: any) => Promise<TransactionInstruction>
Builds the `specialTransferPerpPositionToVamm` instruction. See `specialTransferPerpPositionToVamm` for full semantics/preconditions.
Yes
depositIntoIsolatedPerpPosition
(amount: BN, perpMarketIndex: number, userTokenAccount: PublicKey, subAccountId?: number | undefined, txParams?: TxParams | undefined) => Promise<string>
Deposits collateral from a token account directly into an isolated perp position's own segregated balance (as opposed to `deposit`, which credits the sub-account's general/cross balance). The position's quote spot market is derived from `perpMarketIndex`'s `quoteSpotMarketIndex`.
Yes
getDepositIntoIsolatedPerpPositionIx
(amount: BN, perpMarketIndex: number, userTokenAccount: PublicKey, subAccountId?: number | undefined) => Promise<TransactionInstruction>
Builds the `depositIntoIsolatedPerpPosition` instruction. See `depositIntoIsolatedPerpPosition` for semantics.
Yes
transferIsolatedPerpPositionDeposit
(amount: BN, perpMarketIndex: number, subAccountId?: number | undefined, txParams?: TxParams | undefined, trySettle?: boolean | undefined, noBuffer?: boolean | undefined) => Promise<...>
Moves collateral between an isolated perp position's segregated balance and the sub-account's general/cross balance, in the same underlying quote spot market (derived from `perpMarketIndex`). Positive `amount` moves collateral **from general into the isolated position**; negative moves it **from the isolated position back to general**. If the requested outflow from the isolated position would exceed its current deposit (i.e. it needs unrealized PnL to be realized first, or the caller wants to withdraw everything), prepends a `TRY_SETTLE` settle-PnL instruction for `perpMarketIndex` before the transfer.
Yes
getTransferIsolatedPerpPositionDepositIx
(amount: BN, perpMarketIndex: number, subAccountId?: number | undefined, noAmountBuffer?: boolean | undefined, signingAuthority?: PublicKey | undefined) => Promise<TransactionInstruction>
Builds the `transferIsolatedPerpPositionDeposit` instruction (without the `TRY_SETTLE` prepend — see `transferIsolatedPerpPositionDeposit` for the full sequence). See that method for the sign/precision convention of `amount`.
Yes
withdrawFromIsolatedPerpPosition
(amount: BN, perpMarketIndex: number, userTokenAccount: PublicKey, subAccountId?: number | undefined, txParams?: TxParams | undefined) => Promise<string>
Withdraws collateral out of the protocol directly from an isolated perp position's segregated balance to a token account (as opposed to `withdraw`, which draws from the sub-account's general/cross balance). See `getWithdrawFromIsolatedPerpPositionIxsBundle` for the settle-PnL and amount-clamping logic applied first.
Yes
getWithdrawFromIsolatedPerpPositionIxsBundle
(amount: BN, perpMarketIndex: number, subAccountId?: number | undefined, userTokenAccount?: PublicKey | undefined) => Promise<TransactionInstruction[]>
Builds the full instruction sequence for `withdrawFromIsolatedPerpPosition`: computes the position's claimable unrealized PnL, and clamps `amount` to the isolated deposit plus that claimable PnL — the on-chain `amount` is `u64` with no "withdraw all" sentinel (unlike the sibling `transferIsolatedPerpPositionDeposit`, whose `i64` `amount` treats `i64::MIN` as one), so passing `BN` values larger than the withdrawable balance is how a caller requests "withdraw everything". Also prepends a `TRY_SETTLE` settle-PnL instruction for `perpMarketIndex` whenever the request draws into unrealized (unsettled) PnL. Note the clamp is a build-time estimate: if the settle realizes less than the claimable PnL (e.g. the market's PnL pool is short), the withdraw can still fail on-chain with `InsufficientCollateral`.
Yes
getWithdrawFromIsolatedPerpPositionIx
(amount: BN, perpMarketIndex: number, userTokenAccount: PublicKey, subAccountId?: number | undefined) => Promise<TransactionInstruction>
Builds the raw `withdrawFromIsolatedPerpPosition` instruction (no settle-PnL/clamping — see `getWithdrawFromIsolatedPerpPositionIxsBundle` for the full sequence).
Yes
updateSpotMarketCumulativeInterest
(marketIndex: number, txParams?: TxParams | undefined) => Promise<string>
Permissionless crank: forces a spot market to accrue interest (updating `cumulativeDepositInterest`/`cumulativeBorrowInterest` and TWAP stats) up to the current slot. The instruction's accounts impose no authority/hot-role check beyond the transaction fee payer — anyone can call this to keep a market's interest current between organic deposit/withdraw/borrow activity.
Yes
updateSpotMarketCumulativeInterestIx
(marketIndex: number) => Promise<TransactionInstruction>
Builds the `updateSpotMarketCumulativeInterest` instruction. See `updateSpotMarketCumulativeInterest` for semantics.
Yes
openPosition
(direction: PositionDirection, amount: BN, marketIndex: number, limitPrice?: any, subAccountId?: number | undefined) => Promise<string>
Opens/increases a perp position with a market order (or a limit order if `limitPrice` is given), filled immediately against the AMM/makers via `placeAndTakePerpOrder`.
Yes
sendSignedTx
(tx: VersionedTransaction | Transaction, opts?: ConfirmOptions | undefined) => Promise<string>
Submits and confirms a transaction that has already been fully signed elsewhere (e.g. by an external/hardware wallet flow), skipping this client's normal build-and-sign step entirely. Not order/instruction-specific — works for any pre-signed `Transaction`/`VersionedTransaction`.
Yes
prepareMarketOrderTxs
(orderParams: OptionalOrderParams, userAccountPublicKey: PublicKey, userAccount: UserAccount, makerInfo?: MakerInfo | MakerInfo[] | undefined, txParams?: TxParams | undefined, bracketOrdersParams?: OptionalOrderParams[] | undefined, cancelExistingOrders?: boolean | undefined, settlePnl?: boolean | undefined, positio...
Builds (without sending) the set of transactions needed to place a market order and, for legacy (non-versioned) transactions, a companion transaction that fills it against the AMM. Also builds optional companion transactions to cancel the market's existing orders first and/or settle PnL after the fill. Used by `sendMarketOrderAndGetSignedFillTx`.
Yes
sendMarketOrderAndGetSignedFillTx
(orderParams: OptionalOrderParams, userAccountPublicKey: PublicKey, userAccount: UserAccount, makerInfo?: MakerInfo | MakerInfo[] | undefined, txParams?: TxParams | undefined, bracketOrdersParams?: OptionalOrderParams[] | undefined, cancelExistingOrders?: boolean | undefined, settlePnl?: boolean | undefined) => Prom...
Sends a market order transaction and, for legacy (non-versioned) transactions, also returns a co-signed fill transaction the caller can broadcast themselves to fill the order against the AMM (useful when the caller wants to control fill timing/submission rather than relying on a keeper). Internally builds transactions via `prepareMarketOrderTxs`, signs them all, then sends only `marketOrderTx`.
Yes
placePerpOrder
(orderParams: OptionalOrderParams, txParams?: TxParams | undefined, subAccountId?: number | undefined, isolatedPositionDepositAmount?: any) => Promise<...>
Places a single perp order without attempting to fill it in the same instruction — the order rests until a keeper (or a `placeAndTake*`/signed-msg fill) matches it. Use `placeAndTakePerpOrder` instead if the caller wants an immediate attempt to fill against the AMM/makers.
Yes
getBuilderEscrowAccountMeta
any
Returns the RevenueShareEscrow account meta for the placing user when `orderParams` carries a builder code (`builderIdx` + `builderFeeTenthBps`), otherwise `undefined`. The on-chain handlers peek for this account last in `remaining_accounts`, so callers must push it after the market/oracle/maker accounts.
Yes
getTakerEscrowAccountMeta
any
Returns the AccountMeta for the taker's RevenueShareEscrow when a fill of the taker's order must include it: the order carries a builder code, or the taker is referred (their escrow was initialized with a referrer). Returns `undefined` when neither applies so no account meta is added to the transaction. The on-chain handlers peek for this account last in `remaining_accounts`, so callers must push it after the market/oracle/maker accounts. Throws when `takerEscrow` does not belong to `takerAuthority`.
Yes
getPlacePerpOrderIx
(orderParams: OptionalOrderParams, subAccountId?: number | undefined, depositToTradeArgs?: { isMakingNewAccount: boolean; depositMarketIndex: number; } | undefined) => Promise<...>
Builds the `placePerpOrder` instruction. See `placePerpOrder` for semantics. Automatically attaches the placing user's `RevenueShareEscrow` account when `orderParams` carries a builder code (`builderIdx`/`builderFeeTenthBps`).
Yes
updateAMMs
(marketIndexes: number[], txParams?: TxParams | undefined) => Promise<string>
Yes
getUpdateAMMsIx
(marketIndexes: number[]) => Promise<TransactionInstruction>
Yes
settleExpiredMarket
(marketIndex: number, txParams?: TxParams | undefined) => Promise<string>
Admin instruction: finalizes settlement pricing for a perp market that has already been put into `Settlement` status (`market.status === MarketStatus.SETTLEMENT`), snapping the market's settlement price/oracle-twap so every position can subsequently be closed at that fixed price via `settlePNL`. Requires a warm- or cold-tier admin signer (`check_warm`).
Yes
getSettleExpiredMarketIx
(marketIndex: number) => Promise<TransactionInstruction>
Builds the `settleExpiredMarket` instruction. See `settleExpiredMarket` for semantics. Signs with `this.wallet.publicKey` when not subscribed, or the state's `coldAdmin` when subscribed — the on-chain constraint accepts either a warm- or cold-tier admin, so passing `coldAdmin` always satisfies it regardless of which tier the actual signer holds.
Yes
settleExpiredMarketPoolsToRevenuePool
(marketIndex: number, txParams?: TxParams | undefined) => Promise<string>
Admin instruction: sweeps a settled (`MarketStatus.SETTLEMENT`) perp market's remaining fee pool and PnL pool balances into the quote spot market's revenue pool, once all user positions in the market have been settled out. Requires a warm- or cold-tier admin signer.
Yes
getSettleExpiredMarketPoolsToRevenuePoolIx
(perpMarketIndex: number) => Promise<TransactionInstruction>
Builds the `settleExpiredMarketPoolsToRevenuePool` instruction. See `settleExpiredMarketPoolsToRevenuePool` for semantics.
Yes
cancelOrder
(orderId?: number | undefined, txParams?: TxParams | undefined, subAccountId?: number | undefined, overrides?: { withdrawIsolatedDepositAmount?: any; } | undefined) => Promise<...>
Cancel an open order and broadcast the transaction. When `orderId` is `undefined` (omitted or passed explicitly), the instruction is sent with a `null` order ID and the program cancels the most recently placed order on-chain via `get_last_order_id`. This is safe to use in a composed transaction where a place instruction runs first and the assigned order ID is not yet known. Note: when `orderId` is `undefined` and `overrides.withdrawIsolatedDepositAmount` is also provided, `getOrder` will return `undefined` (the ID is unknown client-side), causing the withdraw path to throw — supply an explicit `orderId` in that case.
Yes
getCancelOrderIx
(orderId?: number | undefined, subAccountId?: number | undefined) => Promise<TransactionInstruction>
Build a `cancelOrder` instruction for the given order. When `orderId` is `undefined` (omitted or passed explicitly), the instruction is built with a `null` order ID (`orderId ?? null`). The program interprets a `null` ID as "cancel the user's most recently placed order" (via `get_last_order_id` on-chain). This is useful when composing a multi-instruction transaction where a place instruction precedes the cancel and the program-assigned order ID is not yet known at build time. When `orderId` is supplied, only that specific order is cancelled.
Yes
cancelOrderByUserId
(userOrderId: number, txParams?: TxParams | undefined, subAccountId?: number | undefined) => Promise<string>
Cancel an open order identified by its caller-supplied `userOrderId` and broadcast the transaction.
Yes
getCancelOrderByUserIdIx
(userOrderId: number, subAccountId?: number | undefined) => Promise<TransactionInstruction>
Builds the `cancelOrderByUserId` instruction. See `cancelOrderByUserId` for semantics.
Yes
cancelOrdersByIds
(orderIds?: number[] | undefined, txParams?: TxParams | undefined, subAccountId?: number | undefined, user?: User | undefined, overrides?: { authority?: PublicKey; } | undefined) => Promise<...>
Sends a transaction to cancel the provided order ids.
Yes
getCancelOrdersByIdsIx
(orderIds?: number[] | undefined, subAccountId?: number | undefined, user?: User | undefined, overrides?: { authority?: PublicKey; } | undefined) => Promise<TransactionInstruction>
Returns the transaction instruction to cancel the provided order ids.
Yes
cancelOrders
(marketType?: MarketType | undefined, marketIndex?: number | undefined, direction?: PositionDirection | undefined, txParams?: TxParams | undefined, subAccountId?: number | undefined) => Promise<...>
Cancel all of a user's open orders matching the given (optional) filters, and broadcast the transaction. Any filter left `undefined` is not applied — calling with no filters cancels every open order on the sub-account.
Yes
getCancelOrdersIx
(marketType: MarketType | null | undefined, marketIndex: number | null | undefined, direction: PositionDirection | null | undefined, subAccountId?: number | undefined) => Promise<...>
Builds the `cancelOrders` instruction. See `cancelOrders` for filter semantics (`null`/`undefined` on any of `marketType`/`marketIndex`/`direction` means "don't filter on that field").
Yes
cancelAndPlaceOrders
(cancelOrderParams: { marketType?: MarketType; marketIndex?: number; direction?: PositionDirection; }, placeOrderParams: OrderParams[], txParams?: TxParams | undefined, subAccountId?: number | undefined) => Promise<...>
Atomically cancels orders matching the given filters and places new orders in a single transaction (cancel instruction first, then place). Useful for order replacement flows (e.g. re-quoting) where the old orders must not be fillable in the gap before the new ones land.
Yes
placeOrders
(params: OrderParams[], txParams?: TxParams | undefined, subAccountId?: number | undefined, optionalIxs?: TransactionInstruction[] | undefined, isolatedPositionDepositAmount?: any) => Promise<...>
Places a batch of orders (perp and/or spot) in a single instruction. None are filled in-instruction — each rests until matched by a keeper or a subsequent fill/place-and-take.
Yes
preparePlaceOrdersTx
(params: OrderParams[], txParams?: TxParams | undefined, subAccountId?: number | undefined, optionalIxs?: TransactionInstruction[] | undefined, isolatedPositionDepositAmount?: any) => Promise<...>
Builds (without sending) the `placeOrders` transaction. See `placeOrders` for semantics.
Yes
getPlaceOrdersIx
(params: OptionalOrderParams[], subAccountId?: number | undefined, overrides?: { authority?: PublicKey; } | undefined) => Promise<TransactionInstruction>
Builds the `placeOrders` instruction. See `placeOrders` for semantics. Attaches the placing user's `RevenueShareEscrow` once (not per-order) when any order in the batch carries a builder code — the on-chain handler expects a single escrow account for the whole batch.
Yes
getPlaceOrdersAndSetPositionMaxLevIx
(params: OptionalOrderParams[], positionMaxLev: number, subAccountId?: number | undefined) => Promise<TransactionInstruction[]>
Builds a `placeOrders` instruction followed by an instruction that sets a custom max-leverage margin ratio on the position for `params[0]`'s market. Unlike `placeOrders`, this bypasses the `RevenueShareEscrow` attachment for builder-coded orders (uses the raw `program.instruction` call directly) — don't use it for batches containing a builder-coded order.
Yes
placeScaleOrders
(params: ScaleOrderParams, txParams?: TxParams | undefined, subAccountId?: number | undefined) => Promise<string>
Places multiple limit orders (`params.orderCount`, 2-32) distributed across a price range in a single instruction, none filled in-instruction — each rests until matched.
Yes
preparePlaceScaleOrdersTx
(params: ScaleOrderParams, txParams?: TxParams | undefined, subAccountId?: number | undefined) => Promise<{ placeScaleOrdersTx: VersionedTransaction | Transaction; }>
Builds (without sending) the `placeScaleOrders` transaction. See `placeScaleOrders` for semantics.
Yes
getPlaceScaleOrdersIx
(params: ScaleOrderParams, subAccountId?: number | undefined) => Promise<TransactionInstruction>
Builds the `placeScaleOrders` instruction. See `placeScaleOrders` for semantics.
Yes
fillPerpOrder
(userAccountPublicKey: PublicKey, user: UserAccount, order?: Pick<Order, "marketIndex" | "orderId"> | undefined, makerInfo?: MakerInfo | MakerInfo[] | undefined, txParams?: TxParams | undefined, fillerSubAccountId?: number | undefined, fillerAuthority?: PublicKey | undefined, hasBuilderFee?: boolean | undefined, tak...
Keeper instruction that fills a resting DLOB perp order against one or more makers (or the AMM/vAMM when no maker matches). Permissionless — any signer can act as filler and earns the filler reward. Does not place or cancel orders itself; it only matches an order that is already on the book.
Yes
getFillPerpOrderIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, order?: Pick<Order, "marketIndex" | "orderId"> | undefined, makerInfo?: MakerInfo | MakerInfo[] | undefined, fillerSubAccountId?: number | undefined, isSignedMsg?: boolean | undefined, fillerAuthority?: PublicKey | undefined, hasBuilderFee?: boolean | undef...
Builds the `fillPerpOrder` instruction. See `fillPerpOrder` for semantics. Assembles maker accounts and the taker's `RevenueShareEscrow` (when owed) into `remainingAccounts` in the order the on-chain handler expects: user/maker market+oracle accounts first, then each maker's `(maker, makerStats)` pair, then the taker escrow meta last.
Yes
getRevertFillIx
(fillerPublicKey?: PublicKey | undefined) => Promise<TransactionInstruction>
Builds the `revertFill` instruction. Used by keepers as a same-transaction fallback after a simulated fill fails downstream (e.g. a subsequent instruction errors): it only asserts the filler's `lastActiveSlot` equals the current slot and otherwise is a no-op, letting the keeper's earlier fill CPI effects be discarded by the transaction failing cleanly rather than with a confusing downstream error.
Yes
placeSpotOrder
(_orderParams: OptionalOrderParams, _txParams?: TxParams | undefined, _subAccountId?: number | undefined) => Promise<string>
Disabled. Spot DLOB trading (order placement/matching) is turned off in this deployment — spot balances, deposits, withdrawals, and swaps remain available.
Yes
preparePlaceSpotOrderTx
(_orderParams: OptionalOrderParams, _txParams?: TxParams | undefined, _subAccountId?: number | undefined) => Promise<void>
Disabled. See `placeSpotOrder`.
Yes
getPlaceSpotOrderIx
(_orderParams: OptionalOrderParams, _subAccountId?: number | undefined, _overrides?: { authority?: PublicKey; } | undefined) => Promise<TransactionInstruction>
Disabled. See `placeSpotOrder`.
Yes
fillSpotOrder
(_userAccountPublicKey: PublicKey, _user: UserAccount, _order?: Pick<Order, "marketIndex" | "orderId"> | undefined, _fulfillmentConfig?: unknown, _makerInfo?: MakerInfo | ... 1 more ... | undefined, _txParams?: TxParams | undefined) => Promise<...>
Disabled. See `placeSpotOrder`.
Yes
getFillSpotOrderIx
(_userAccountPublicKey: PublicKey, _userAccount: UserAccount, _order?: Pick<Order, "marketIndex" | "orderId"> | undefined, _fulfillmentConfig?: unknown, _makerInfo?: MakerInfo | ... 1 more ... | undefined, _fillerPublicKey?: PublicKey | undefined) => Promise<...>
Disabled. See `placeSpotOrder`.
Yes
swap
({ swapClient, jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, reduceOnly, txParams, v6, quote, onlyDirectRoutes, }: { swapClient?: UnifiedSwapClient | SwapClient; jupiterClient?: JupiterClient; outMarketIndex: number; inMarketIndex: n...
Swaps one spot-market token for another inside the user's velocity account: brackets the external swap provider's instructions between the program's `beginSwap`/`endSwap` instructions in a single transaction, so the swap is settled directly against the user's deposits/vault balances rather than the wallet's own token accounts. Sends and confirms the transaction.
Yes
getTitanSwapIx
({ titanClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, onlyDirectRoutes, reduceOnly, userAccountPublicKey, }: { titanClient: TitanClient; outMarketIndex: number; inMarketIndex: number; outAssociatedTokenAccount?: PublicKey; inAssociatedToken...
Builds the instruction list for a Titan-routed swap: creates any missing associated token accounts, wraps Titan's routing instructions between `beginSwap`/`endSwap`. See `swap` for parameter semantics; `amount` is in the "in" token's mint decimals.
Yes
getJupiterSwapIxV6
({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, onlyDirectRoutes, quote, reduceOnly, userAccountPublicKey, }: { jupiterClient: JupiterClient; outMarketIndex: number; inMarketIndex: number; outAssociatedTokenAccount?: PublicKey; inAs...
Builds the instruction list for a Jupiter v6-routed swap: fetches a quote if none is passed, creates any missing associated token accounts, and wraps Jupiter's routing instructions between `beginSwap`/`endSwap`. See `swap` for parameter semantics; `amount` is in the "in" token's mint decimals.
Yes
getSwapIx
({ outMarketIndex, inMarketIndex, amountIn, inTokenAccount, outTokenAccount, limitPrice, reduceOnly, userAccountPublicKey, }: { outMarketIndex: number; inMarketIndex: number; amountIn: BN; inTokenAccount: PublicKey; outTokenAccount: PublicKey; limitPrice?: any; reduceOnly?: SwapReduceOnly; userAccountPublicKey?: Pub...
Builds the `beginSwap`/`endSwap` instruction pair that must bracket an external swap provider's routing instructions in the same transaction. `beginSwap` snapshots the token account balances and moves `amountIn` out of the in-market vault; `endSwap` reconciles the post-swap token balances back into the user's velocity deposits, enforces `limitPrice` and `reduceOnly`, and validates both spot markets' oracles are fresh/valid.
Yes
getSwapIxV2
({ swapClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, onlyDirectRoutes, reduceOnly, quote, v6, userAccountPublicKey, }: { swapClient: UnifiedSwapClient; outMarketIndex: number; inMarketIndex: number; outAssociatedTokenAccount?: PublicKey; in...
Builds the instruction list for a swap routed through a `UnifiedSwapClient` (the current preferred swap path). Creates any missing associated token accounts and wraps the client's routing instructions between `beginSwap`/`endSwap`. See `swap` for parameter semantics; `amount` is in the "in" token's mint decimals (or "out" token's decimals when `swapMode` is `ExactOut`).
Yes
stakeForMSOL
({ amount }: { amount: BN; }) => Promise<TxSigAndSlot>
Converts a portion of the user's deposited wSOL (spot market index 1) into mSOL (spot market index 2) by staking it with Marinade Finance, then swapping the resulting mSOL back into the velocity deposit via `beginSwap`/`endSwap`. Sends and confirms the transaction.
Yes
getStakeForMSOLIx
({ amount, userAccountPublicKey, }: { amount: BN; userAccountPublicKey?: PublicKey; }) => Promise<TransactionInstruction[]>
Builds the instruction list for `stakeForMSOL`: wraps a Marinade `deposit` (wSOL to mSOL) between the velocity `beginSwap`/`endSwap` pair so the mSOL lands back in the user's velocity deposit for spot market index 2. Hardcodes wSOL as market index 1 and mSOL as market index 2.
Yes
triggerOrder
(userAccountPublicKey: PublicKey, user: UserAccount, order: Order, txParams?: TxParams | undefined, fillerPublicKey?: PublicKey | undefined) => Promise<...>
Keeper instruction: activates a resting trigger order (stop/take-profit, perp or spot) once its `triggerPrice`/`triggerCondition` has been met, turning it into a fillable market/limit order. Permissionless — any signer can act as filler and earns a small keeper fee. Does not fill the order itself; a separate fill instruction (or place-and-take) is still required.
Yes
getTriggerOrderIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Order, fillerPublicKey?: PublicKey | undefined) => Promise<TransactionInstruction>
Builds the `triggerOrder` instruction. See `triggerOrder` for semantics.
Yes
forceCancelOrders
(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams | undefined, fillerPublicKey?: PublicKey | undefined) => Promise<...>
Keeper instruction: cancels a user's open, non-position-reducing orders when the user fails their initial margin requirement (reverts with `SufficientCollateral` if the user still meets it, or with `UserIsBeingLiquidated`/`UserBankrupt` if either is set). Charges the user a per-cancelled-order fee paid to the filler. Permissionless — any signer can act as filler.
Yes
getForceCancelOrdersIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, fillerPublicKey?: PublicKey | undefined) => Promise<TransactionInstruction>
Builds the `forceCancelOrders` instruction. See `forceCancelOrders` for semantics.
Yes
updateUserIdle
(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams | undefined, fillerPublicKey?: PublicKey | undefined) => Promise<...>
Keeper instruction: marks a user account idle after confirming (via `validate_user_is_idle`) it has been inactive long enough — the inactivity window is shorter (accelerated) when the user's equity is below 1000 USDC (QUOTE_PRECISION, 1e6). Idle users are excluded from some keeper crank workloads. Permissionless — any signer can act as filler.
Yes
getUpdateUserIdleIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, fillerPublicKey?: PublicKey | undefined) => Promise<TransactionInstruction>
Builds the `updateUserIdle` instruction. See `updateUserIdle` for semantics.
Yes
logUserBalances
(userAccountPublicKey: PublicKey, txParams?: TxParams | undefined) => Promise<string>
Debug/monitoring instruction: emits the user's equity, each non-zero spot position's signed token amount (native mint decimals), and each open perp position's unrealized PnL (QUOTE_PRECISION, 1e6) as program logs. Has no on-chain state effect. Exchange must not be paused.
Yes
getLogUserBalancesIx
(userAccountPublicKey: PublicKey) => Promise<TransactionInstruction>
Builds the `logUserBalances` instruction. See `logUserBalances` for semantics. Fetches the user account fresh from the RPC (rather than relying on a cached/passed-in account) to build `remainingAccounts`.
Yes
updateUserStatsReferrerStatus
(userAuthority: PublicKey, txParams?: TxParams | undefined) => Promise<string>
Recomputes and updates the `isReferrer` flag on a `UserStats` account from its current referrer-related fields. Permissionless — anyone can trigger the refresh for any authority.
Yes
getUpdateUserStatsReferrerStatusIx
(userAuthority: PublicKey) => Promise<TransactionInstruction>
Builds the `updateUserStatsReferrerStatus` instruction. See `updateUserStatsReferrerStatus` for semantics.
Yes
updateUserOpenOrdersCount
(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams | undefined, fillerPublicKey?: PublicKey | undefined) => Promise<...>
Keeper instruction: recounts `user.orders` and rewrites `openOrders`/`hasOpenOrder`/ `openAuctions`/`hasOpenAuction` to match the account's actual order state — a repair instruction for when these cached counters have drifted. Permissionless — any signer can act as filler.
Yes
getUpdateUserOpenOrdersCountIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, fillerPublicKey?: PublicKey | undefined) => Promise<TransactionInstruction>
Builds the `updateUserOpenOrdersCount` instruction. See `updateUserOpenOrdersCount` for semantics.
Yes
placeAndTakePerpOrder
(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[] | undefined, successCondition?: PlaceAndTakeOrderSuccessCondition | undefined, auctionDurationPercentage?: number | undefined, txParams?: TxParams | undefined, subAccountId?: number | undefined, takerEscrow?: RevenueShareEscrowAccount | undefined...
Places a perp order and immediately attempts to fill it in the same instruction against the AMM and/or the supplied `makerInfo`. `orderParams.postOnly` must be `PostOnlyParams.NONE` — the on-chain handler rejects post-only orders here (use `placeAndMakePerpOrder` instead for a post-only maker order). If the order is immediate-or-cancel (or `successCondition`/ `auctionDurationPercentage` is set) and still open after the fill attempt, it is cancelled in the same instruction.
Yes
preparePlaceAndTakePerpOrderWithAdditionalOrders
(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[] | undefined, bracketOrdersParams?: OptionalOrderParams[] | undefined, txParams?: TxParams | undefined, subAccountId?: number | undefined, cancelExistingOrders?: boolean | undefined, settlePnl?: boolean | undefined, exitEarlyIfSimFails?: boolean |...
Builds (without sending) a `placeAndTakePerpOrder` transaction bundled with optional bracket orders (e.g. TP/SL) in the same transaction, plus optional companion transactions to cancel the market's existing orders first and/or settle PnL after. Reuses a single recent blockhash across all built transactions to save RPC round trips.
Yes
placeAndTakePerpWithAdditionalOrders
(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[] | undefined, bracketOrdersParams?: OptionalOrderParams[] | undefined, txParams?: TxParams | undefined, subAccountId?: number | undefined, cancelExistingOrders?: boolean | undefined, settlePnl?: boolean | undefined, exitEarlyIfSimFails?: boolean |...
Builds, signs, and sends a `placeAndTakePerpOrder` transaction bundled with bracket orders via `preparePlaceAndTakePerpOrderWithAdditionalOrders`, and returns the signed (but unsent) companion cancel/settle-PnL transactions for the caller to broadcast separately.
Yes
getPlaceAndTakePerpOrderIx
(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[] | undefined, successCondition?: PlaceAndTakeOrderSuccessCondition | undefined, auctionDurationPercentage?: number | undefined, subAccountId?: number | undefined, overrides?: { ...; } | undefined, takerEscrow?: RevenueShareEscrowAccount | undefine...
Builds the `placeAndTakePerpOrder` instruction. See `placeAndTakePerpOrder` for semantics.
Yes
placeAndMakePerpOrder
(orderParams: OptionalOrderParams, takerInfo: TakerInfo, txParams?: TxParams | undefined, subAccountId?: number | undefined, takerEscrow?: RevenueShareEscrowAccount | undefined) => Promise<...>
Places a resting maker order and, in the same instruction, fills a specific counterparty taker order (`takerInfo.order`) against it. `orderParams` must be an immediate-or-cancel, post-only (not `PostOnlyParams.NONE`) limit order — the on-chain handler rejects any other shape with `InvalidOrderIOCPostOnly`.
Yes
getPlaceAndMakePerpOrderIx
(orderParams: OptionalOrderParams, takerInfo: TakerInfo, subAccountId?: number | undefined, takerEscrow?: RevenueShareEscrowAccount | undefined) => Promise<...>
Builds the `placeAndMakePerpOrder` instruction. See `placeAndMakePerpOrder` for semantics.
Yes
signSignedMsgOrderParamsMessage
(orderParamsMessage: SignedMsgOrderParamsMessage | SignedMsgOrderParamsDelegateMessage, delegateSigner?: boolean | undefined) => SignedMsgOrderParams
Borsh-encodes a swift/signed-msg order message and signs the resulting hex-encoded buffer with `signMessage` (this client's wallet keypair by default). The returned payload is what a swift/signed-msg service or a taker-facing `placeSignedMsgTakerOrder` expects.
Yes
buildDepositAndPlaceSignedMsgOrderRequest
(depositTx: VersionedTransaction, orderParamsMessage: SignedMsgOrderParamsMessage | SignedMsgOrderParamsDelegateMessage, delegateSigner?: boolean | undefined) => { ...; }
Bundles a pre-signed deposit transaction with a signed swift/signed-msg order message into the request shape the Swift service expects for a "deposit and place" flow (e.g. depositing new collateral and placing an order off-chain in one round trip before either lands on-chain).
Yes
encodeSignedMsgOrderParamsMessage
(orderParamsMessage: SignedMsgOrderParamsMessage | SignedMsgOrderParamsDelegateMessage, delegateSigner?: boolean | undefined) => Buffer
Borsh-encodes a swift/signed-msg order message using the program's IDL type coder. Used internally by `signSignedMsgOrderParamsMessage`; call directly if you need the raw encoded bytes without also signing them.
Yes
decodeSignedMsgOrderParamsMessage
(encodedMessage: Buffer, delegateSigner?: boolean | undefined) => SignedMsgOrderParamsMessage | SignedMsgOrderParamsDelegateMessage
Decodes a borsh-encoded swift/signed-msg order message. Zero-pads the input by 128 bytes before decoding so messages encoded by an older IDL (missing newer, all-`Option` fields) still decode instead of throwing on a too-short buffer. Note: this padding assumes any newer fields added to the message type are `Option`s — a 128+ byte non-optional field addition could still fail to decode older messages correctly.
Yes
signMessage
(message: Uint8Array<ArrayBufferLike>, keypair?: Keypair | undefined) => Buffer
Signs arbitrary bytes with a raw ed25519 detached signature (not a Solana transaction signature) — the primitive used to sign swift/signed-msg order messages.
Yes
placeSignedMsgTakerOrder
(signedSignedMsgOrderParams: SignedMsgOrderParams, marketIndex: number, takerInfo: { taker: PublicKey; takerStats: PublicKey; takerUserAccount: UserAccount; signingAuthority: PublicKey; }, precedingIxs?: TransactionInstruction[] | undefined, overrideCustomIxIndex?: number | undefined, txParams?: TxParams | undefined...
Submits a previously off-chain-signed swift/signed-msg taker order on-chain: verifies the ed25519 signature via the sysvar-instructions program and records the order in the taker's `SignedMsgUserOrders` account (see `initializeSignedMsgUserOrders`, required beforehand). This only registers the order — it does not place or fill it against the market; a keeper (or `placeAndMakeSignedMsgPerpOrder`) still performs the actual place/fill.
Yes
getPlaceSignedMsgTakerPerpOrderIxs
(signedSignedMsgOrderParams: SignedMsgOrderParams, marketIndex: number, takerInfo: { taker: PublicKey; takerStats: PublicKey; takerUserAccount: UserAccount; signingAuthority: PublicKey; }, precedingIxs?: TransactionInstruction[] | undefined, overrideCustomIxIndex?: number | undefined) => Promise<...>
Builds the two instructions for `placeSignedMsgTakerOrder`: an ed25519-signature-verify instruction (must be placed at the sysvar-instructions index this function assumes — see `precedingIxs`/`overrideCustomIxIndex`) followed by the `placeSignedMsgTakerOrder` program instruction. See `placeSignedMsgTakerOrder` for semantics.
Yes
placeAndMakeSignedMsgPerpOrder
(signedSignedMsgOrderParams: SignedMsgOrderParams, signedMsgOrderUuid: Uint8Array<ArrayBufferLike>, takerInfo: { taker: PublicKey; takerStats: PublicKey; takerUserAccount: UserAccount; signingAuthority: PublicKey; }, orderParams: OptionalOrderParams, txParams?: TxParams | undefined, subAccountId?: number | undefined...
Verifies and registers a taker's off-chain signed swift/signed-msg order (same as `placeSignedMsgTakerOrder`) and, in the same transaction, places a maker order and fills the taker order against it in one shot — the signed-msg analog of `placeAndMakePerpOrder`. `orderParams` (the maker order) is subject to the same IOC/post-only/limit requirement as `placeAndMakePerpOrder`.
Yes
getPlaceAndMakeSignedMsgPerpOrderIxs
(signedSignedMsgOrderParams: SignedMsgOrderParams, signedMsgOrderUuid: Uint8Array<ArrayBufferLike>, takerInfo: { taker: PublicKey; takerStats: PublicKey; takerUserAccount: UserAccount; signingAuthority: PublicKey; }, orderParams: OptionalOrderParams, subAccountId?: number | undefined, precedingIxs?: TransactionInstr...
Builds the instructions for `placeAndMakeSignedMsgPerpOrder`: the taker signature-verify + registration instructions from `getPlaceSignedMsgTakerPerpOrderIxs`, followed by the `placeAndMakeSignedMsgPerpOrder` program instruction. See `placeAndMakeSignedMsgPerpOrder` for semantics.
Yes
preparePlaceAndTakeSpotOrder
(_orderParams: OptionalOrderParams, _fulfillmentConfig?: unknown, _makerInfo?: MakerInfo | undefined, _txParams?: TxParams | undefined, _subAccountId?: number | undefined) => Promise<...>
Disabled. See `placeSpotOrder`.
Yes
placeAndTakeSpotOrder
(_orderParams: OptionalOrderParams, _fulfillmentConfig?: unknown, _makerInfo?: MakerInfo | undefined, _txParams?: TxParams | undefined, _subAccountId?: number | undefined) => Promise<...>
Disabled. See `placeSpotOrder`.
Yes
getPlaceAndTakeSpotOrderIx
(_orderParams: OptionalOrderParams, _fulfillmentConfig?: unknown, _makerInfo?: MakerInfo | undefined, _subAccountId?: number | undefined) => Promise<TransactionInstruction>
Disabled. See `placeSpotOrder`.
Yes
placeAndMakeSpotOrder
(_orderParams: OptionalOrderParams, _takerInfo: TakerInfo, _fulfillmentConfig?: unknown, _txParams?: TxParams | undefined, _subAccountId?: number | undefined) => Promise<...>
Disabled. See `placeSpotOrder`.
Yes
getPlaceAndMakeSpotOrderIx
(_orderParams: OptionalOrderParams, _takerInfo: TakerInfo, _fulfillmentConfig?: unknown, _subAccountId?: number | undefined) => Promise<TransactionInstruction>
Disabled. See `placeSpotOrder`.
Yes
closePosition
(marketIndex: number, limitPrice?: any, subAccountId?: number | undefined) => Promise<string>
Closes (or reduces to zero) the caller's entire perp position in `marketIndex` with a reduce-only market order (or limit order if `limitPrice` is given), filled immediately via `placeAndTakePerpOrder`.
Yes
modifyPerpOrder
(orderId: number, newBaseAmount?: any, newLimitPrice?: any, newOraclePriceOffset?: any) => Promise<string>
Modifies an open order by closing it and replacing it with a new order.
Yes
modifyPerpOrderByUserOrderId
(userOrderId: number, newBaseAmount?: any, newLimitPrice?: any, newOraclePriceOffset?: any) => Promise<string>
Modifies an open order by closing it and replacing it with a new order.
Yes
modifyOrder
(orderParams: { orderId: number; newDirection?: PositionDirection; newBaseAmount?: any; newLimitPrice?: any; newOraclePriceOffset?: any; newTriggerPrice?: any; newTriggerCondition?: OrderTriggerCondition; ... 7 more ...; policy?: number; }, txParams?: TxParams | undefined, subAccountId?: number | undefined) => Promi...
Modifies an open order (spot or perp) by closing it and replacing it with a new order in one instruction. Only fields present (non-`undefined`) in `orderParams` are changed; the rest of the order is left as-is.
Yes
getModifyOrderIx
({ orderId, newDirection, newBaseAmount, newLimitPrice, newOraclePriceOffset, newTriggerPrice, newTriggerCondition, auctionDuration, auctionStartPrice, auctionEndPrice, reduceOnly, postOnly, bitFlags, maxTs, policy, }: { orderId: number; newDirection?: PositionDirection; newBaseAmount?: any; newLimitPrice?: any; new...
Builds the `modifyOrder` instruction. See `modifyOrder` for field semantics/precisions.
Yes
modifyOrderByUserOrderId
(orderParams: { userOrderId: number; newDirection?: PositionDirection; newBaseAmount?: any; newLimitPrice?: any; newOraclePriceOffset?: any; newTriggerPrice?: any; newTriggerCondition?: OrderTriggerCondition; ... 7 more ...; maxTs?: any; }, txParams?: TxParams | undefined, subAccountId?: number | undefined) => Promi...
Modifies an open order (identified by its caller-supplied `userOrderId`) by closing it and replacing it with a new order in one instruction. Note: unlike `modifyOrder`, omitted `reduceOnly`/`bitFlags` are sent as `false`/`null` respectively rather than "leave unchanged" — passing this method's `orderParams` without `reduceOnly` will explicitly clear an existing reduce-only flag on the order.
Yes
getModifyOrderByUserIdIx
({ userOrderId, newDirection, newBaseAmount, newLimitPrice, newOraclePriceOffset, newTriggerPrice, newTriggerCondition, auctionDuration, auctionStartPrice, auctionEndPrice, reduceOnly, postOnly, bitFlags, maxTs, policy, }: { userOrderId: number; newDirection?: PositionDirection; newBaseAmount?: any; newLimitPrice?: ...
Builds the `modifyOrderByUserOrderId` instruction. See `modifyOrderByUserOrderId` for field semantics/precisions, including the `reduceOnly`/`bitFlags` default-clearing note.
Yes
settlePNLs
(users: { settleeUserAccountPublicKey: PublicKey; settleeUserAccount: UserAccount; }[], marketIndexes: number[], opts?: { filterInvalidMarkets?: boolean; } | undefined, txParams?: TxParams | undefined) => Promise<...>
Keeper instruction: settles unrealized perp PnL to/from each user's quote spot balance for every `(user, marketIndex)` pair, one `settlePnl` instruction per pair in a single transaction. Permissionless — any signer can act as the settling authority. Defaults to `computeUnits: 1_400_000` if `txParams` is not supplied, since settling several users/markets in one transaction is compute-heavy.
Yes
getSettlePNLsIxs
(users: { settleeUserAccountPublicKey: PublicKey; settleeUserAccount: UserAccount; }[], marketIndexes: number[], revenueShareEscrowMap?: RevenueShareEscrowMap | undefined) => Promise<...>
Builds one `settlePnl` instruction per `(user, marketIndex)` combination in `users` x `marketIndexes`. See `settlePNL`/`settlePNLIx` for per-instruction semantics.
Yes
settlePNL
(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: number, txParams?: TxParams | undefined, optionalIxs?: TransactionInstruction[] | undefined, revenueShareEscrowMap?: RevenueShareEscrowMap | undefined) => Promise<...>
Keeper instruction: settles a single user's unrealized perp PnL on one market to/from their quote spot balance. Reads the live oracle (falling back to the AMM's freshness check only if the live oracle is degraded); requires the market not be in `Settlement` status (use `settleExpiredMarket`/expired-position settlement for that) and the quote spot market vault balance to reconcile afterward. Permissionless — any signer can act as the settling authority.
Yes
settlePNLIx
(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: number, revenueShareEscrowMap?: RevenueShareEscrowMap | undefined) => Promise<...>
Builds the `settlePnl` instruction. See `settlePNL` for semantics. When `revenueShareEscrowMap` is passed, inspects the settlee's `RevenueShareEscrow` for completed, unpaid builder-fee or referral-reward orders on `marketIndex` and, if found, appends the escrow PDA plus each relevant builder/referrer authority to `remainingAccounts` so the on-chain sweep can pay them during settlement. Falls back to attaching just the escrow PDA (for lazy cleanup) when the settlee has any builder order but isn't present in the map (stale-cache case).
Yes
settleMultiplePNLs
(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndexes: number[], mode: SettlePnlMode, revenueShareEscrowMap?: RevenueShareEscrowMap | undefined, txParams?: TxParams | undefined) => Promise<...>
Keeper instruction: settles one user's unrealized perp PnL across several markets in a single `settleMultiplePnl` instruction/transaction. Fits at most ~4 markets per transaction (see `settleMultiplePNLsMultipleTxs` for more). Permissionless — any signer can act as the settling authority.
Yes
settleMultiplePNLsMultipleTxs
(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndexes: number[], mode: SettlePnlMode, txParams?: TxParams | undefined, optionalIxs?: TransactionInstruction[] | undefined, revenueShareEscrowMap?: RevenueShareEscrowMap | undefined) => Promise<...>
Settles one user's unrealized perp PnL across an arbitrary number of markets by splitting `marketIndexes` into groups of 4 (more than ~4 markets' worth of accounts won't fit in a single transaction) and sending one `settleMultiplePnl` transaction per group, sequentially. Compute units scale with group size (`300_000` per market, capped at `1_400_000`).
Yes
settleMultiplePNLsIx
(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndexes: number[], mode: SettlePnlMode, overrides?: { authority?: PublicKey; } | undefined, revenueShareEscrowMap?: RevenueShareEscrowMap | undefined) => Promise<...>
Builds the `settleMultiplePnl` instruction. See `settleMultiplePNLs` for semantics. Attaches the settlee's `RevenueShareEscrow` and any relevant builder/referrer accounts when `revenueShareEscrowMap` shows completed builder/referral orders on any of `marketIndexes` (same logic as `settlePNLIx`, generalized across markets).
Yes
getSetUserStatusToBeingLiquidatedIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount) => Promise<TransactionInstruction>
Builds the `setUserStatusToBeingLiquidated` instruction. See `setUserStatusToBeingLiquidated` for semantics.
Yes
setUserStatusToBeingLiquidated
(userAccountPublicKey: PublicKey, userAccount: UserAccount) => Promise<string>
Keeper instruction: flags a user account as being liquidated (sets the `beingLiquidated` status bit) without performing any liquidation itself. Used to "claim" a liquidation ahead of the actual `liquidatePerp`/`liquidateSpot` call so a concurrent liquidator can't race it; the on-chain handler re-checks the user is actually below maintenance margin before setting the flag. Permissionless — any signer can act as liquidator.
Yes
liquidatePerp
(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, maxBaseAssetAmount: BN, limitPrice?: any, txParams?: TxParams | undefined, liquidatorSubAccountId?: number | undefined) => Promise<...>
Keeper instruction: liquidates part or all of a user's perp position in `marketIndex` when the user is below maintenance margin (or already flagged `beingLiquidated`), transferring the position to the calling liquidator's sub-account at the oracle price (subject to `limitPrice` and the on-chain liquidation fee). Reverts if `userAccountPublicKey` equals the liquidator's own user account. Permissionless — any signer can act as liquidator, taking on the position and its PnL themselves.
Yes
getLiquidatePerpIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, maxBaseAssetAmount: BN, limitPrice?: any, liquidatorSubAccountId?: number | undefined) => Promise<...>
Builds the `liquidatePerp` instruction. See `liquidatePerp` for semantics.
Yes
liquidatePerpWithFill
(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, makerInfos: MakerInfo[], txParams?: TxParams | undefined, liquidatorSubAccountId?: number | undefined) => Promise<...>
Keeper instruction: liquidates a user's perp position in `marketIndex` by filling it directly against the supplied `makerInfos` (instead of transferring it to the liquidator's own sub-account as `liquidatePerp` does). Reverts if `userAccountPublicKey` equals the liquidator's own user account. Permissionless — any signer can act as liquidator/filler.
Yes
getLiquidatePerpWithFillIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, makerInfos: MakerInfo[], liquidatorSubAccountId?: number | undefined) => Promise<...>
Builds the `liquidatePerpWithFill` instruction. See `liquidatePerpWithFill` for semantics.
Yes
liquidateSpot
(userAccountPublicKey: PublicKey, userAccount: UserAccount, assetMarketIndex: number, liabilityMarketIndex: number, maxLiabilityTransfer: BN, limitPrice?: any, txParams?: TxParams | undefined, liquidatorSubAccountId?: number | undefined) => Promise<...>
Keeper instruction: liquidates a user's spot position by transferring `liabilityMarketIndex` debt from the user to the liquidator's own sub-account in exchange for `assetMarketIndex` collateral, when the user is below maintenance margin (or already flagged `beingLiquidated`). Reverts if `userAccountPublicKey` equals the liquidator's own user account. Permissionless — any signer can act as liquidator.
Yes
getLiquidateSpotIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, assetMarketIndex: number, liabilityMarketIndex: number, maxLiabilityTransfer: BN, limitPrice?: any, liquidatorSubAccountId?: number | undefined) => Promise<...>
Builds the `liquidateSpot` instruction. See `liquidateSpot` for semantics.
Yes
getJupiterLiquidateSpotWithSwapIxV6
({ jupiterClient, liabilityMarketIndex, assetMarketIndex, swapAmount, assetTokenAccount, liabilityTokenAccount, slippageBps, swapMode, onlyDirectRoutes, quote, userAccount, userAccountPublicKey, liquidatorSubAccountId, maxAccounts, }: { jupiterClient: JupiterClient; liabilityMarketIndex: number; assetMarketIndex: nu...
Builds a Jupiter-routed spot-liquidation-with-swap instruction set: swaps the liquidator's `assetMarketIndex` proceeds into `liabilityMarketIndex` tokens via Jupiter inside a `beginSwap`/`endSwap` flash-loan sandwich (see `getLiquidateSpotWithSwapIx`), letting the liquidator repay the user's debt without needing to already hold the liability token. Fetches a quote from `jupiterClient` when `quote` is not supplied, and idempotently creates any missing associated token accounts.
Yes
getLiquidateSpotWithSwapIx
({ liabilityMarketIndex, assetMarketIndex, swapAmount: swapAmount, assetTokenAccount, liabilityTokenAccount, userAccount, userAccountPublicKey, liquidatorSubAccountId, }: { liabilityMarketIndex: number; assetMarketIndex: number; swapAmount: BN; assetTokenAccount: PublicKey; liabilityTokenAccount: PublicKey; userAcco...
Builds the `liquidateSpotWithSwapBegin`/`...End` instruction pair that sandwiches an external swap (e.g. Jupiter) so a liquidator can repay a user's `liabilityMarketIndex` debt using proceeds from selling `assetMarketIndex` collateral within the same transaction, without pre-funding the liability token. The on-chain handler validates the liability spot market's flash-loan balance is unwound by `endSwap`. See `getJupiterLiquidateSpotWithSwapIxV6` for the Jupiter-specific wrapper that assembles the full instruction list around this pair.
Yes
liquidateBorrowForPerpPnl
(userAccountPublicKey: PublicKey, userAccount: UserAccount, perpMarketIndex: number, liabilityMarketIndex: number, maxLiabilityTransfer: BN, limitPrice?: any, txParams?: TxParams | undefined, liquidatorSubAccountId?: number | undefined) => Promise<...>
Keeper instruction: liquidates a user by transferring `liabilityMarketIndex` spot debt from the user to the liquidator in exchange for a matching amount of the user's positive unsettled perp PnL in `perpMarketIndex`. Only usable once the user's position size in `perpMarketIndex` is zero (the PnL must already be fully unrealized/settled-out, not backed by an open position). Reverts if `userAccountPublicKey` equals the liquidator's own user account. Permissionless — any signer can act as liquidator.
Yes
getLiquidateBorrowForPerpPnlIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, perpMarketIndex: number, liabilityMarketIndex: number, maxLiabilityTransfer: BN, limitPrice?: any, liquidatorSubAccountId?: number | undefined) => Promise<...>
Builds the `liquidateBorrowForPerpPnl` instruction. See `liquidateBorrowForPerpPnl` for semantics.
Yes
liquidatePerpPnlForDeposit
(userAccountPublicKey: PublicKey, userAccount: UserAccount, perpMarketIndex: number, assetMarketIndex: number, maxPnlTransfer: BN, limitPrice?: any, txParams?: TxParams | undefined, liquidatorSubAccountId?: number | undefined) => Promise<...>
Keeper instruction: liquidates a user by transferring negative unsettled perp PnL in `perpMarketIndex` from the user to the liquidator in exchange for `assetMarketIndex` spot collateral (the inverse of `liquidateBorrowForPerpPnl`). Only usable once the user's position size in `perpMarketIndex` is zero. Reverts if `userAccountPublicKey` equals the liquidator's own user account. Permissionless — any signer can act as liquidator.
Yes
getLiquidatePerpPnlForDepositIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, perpMarketIndex: number, assetMarketIndex: number, maxPnlTransfer: BN, limitPrice?: any, liquidatorSubAccountId?: number | undefined) => Promise<...>
Builds the `liquidatePerpPnlForDeposit` instruction. See `liquidatePerpPnlForDeposit` for semantics.
Yes
resolvePerpBankruptcy
(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, txParams?: TxParams | undefined, liquidatorSubAccountId?: number | undefined) => Promise<...>
Keeper instruction: resolves a user's perp bankruptcy in `marketIndex` (negative equity that liquidation alone could not cover) by socializing the loss — first attempting to backstop it from the quote spot market's insurance fund, then socializing any remainder across the market's other position holders via the cumulative funding/PnL pool. Reverts if the resulting insurance payout would fully drain the insurance fund vault, or if `userAccountPublicKey` equals the liquidator's own user account. Permissionless — any signer can act as liquidator.
Yes
getResolvePerpBankruptcyIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, liquidatorSubAccountId?: number | undefined) => Promise<TransactionInstruction>
Builds the `resolvePerpBankruptcy` instruction. See `resolvePerpBankruptcy` for semantics. Always settles against the quote spot market (`QUOTE_SPOT_MARKET_INDEX`).
Yes
resolveSpotBankruptcy
(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, txParams?: TxParams | undefined, liquidatorSubAccountId?: number | undefined) => Promise<...>
Keeper instruction: resolves a user's spot bankruptcy (negative balance in `marketIndex` that liquidation alone could not cover) by backstopping the deficit from that spot market's insurance fund. Reverts if `userAccountPublicKey` equals the liquidator's own user account. Permissionless — any signer can act as liquidator.
Yes
getResolveSpotBankruptcyIx
(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, liquidatorSubAccountId?: number | undefined) => Promise<TransactionInstruction>
Builds the `resolveSpotBankruptcy` instruction. See `resolveSpotBankruptcy` for semantics. Adds the spot market's mint (and transfer-hook extra account metas, if applicable) to `remainingAccounts` for the token transfer from the insurance fund vault.
Yes
updateFundingRate
(perpMarketIndex: number, oracle: PublicKey, txParams?: TxParams | undefined) => Promise<string>
Keeper instruction: recomputes and applies `marketIndex`'s hourly-anchored funding rate (`cumulativeFundingRateLong`/`Short`, FUNDING_RATE_PRECISION, 1e9) from the current oracle/AMM mark-price spread, then updates the market's oracle-derived TWAP stats. No-ops (via `FundingWasNotUpdated`, which the underlying call surfaces as a failed transaction) if it is not yet time for the next update — `perp_market.market_stats.funding_period` seconds since the last update, on-the-hour aligned. Reverts if the market's funding is paused or the market is not `Active`/`ReduceOnly`. Permissionless — any signer can act as keeper.
Yes
getUpdateFundingRateIx
(perpMarketIndex: number, oracle: PublicKey) => Promise<TransactionInstruction>
Builds the `updateFundingRate` instruction. See `updateFundingRate` for semantics.
Yes
updatePrelaunchOracle
(perpMarketIndex: number, txParams?: TxParams | undefined) => Promise<string>
Keeper instruction: refreshes a `Prelaunch`-oracle-source perp market's synthetic oracle price from its own recent trading activity (used for markets without a live external price feed, e.g. pre-listing futures). Only valid when the market's `oracleSource` is `Prelaunch`. Permissionless — any signer can act as keeper.
Yes
getUpdatePrelaunchOracleIx
(perpMarketIndex: number) => Promise<TransactionInstruction>
Builds the `updatePrelaunchOracle` instruction. See `updatePrelaunchOracle` for semantics.
Yes
updatePerpBidAskTwap
(perpMarketIndex: number, makers: [PublicKey, PublicKey][], txParams?: TxParams | undefined) => Promise<string>
Keeper instruction: estimates the market's bid/ask price from the given makers' resting DLOB orders (filtered to those within `BID_ASK_TWAP_MAX_ORACLE_DIVERGENCE_PERCENT` of the oracle price) and folds the estimate into `lastBidPriceTwap`/`lastAskPriceTwap`. Restricted: the calling wallet's `UserStats` must have `canUpdateBidAskTwap` set and at least 1000 USDC (`QUOTE_PRECISION`, 1e6) staked in the insurance fund (`ifStakedQuoteAssetAmount`), or the instruction reverts.
Yes
getUpdatePerpBidAskTwapIx
(perpMarketIndex: number, makers: [PublicKey, PublicKey][]) => Promise<TransactionInstruction>
Builds the `updatePerpBidAskTwap` instruction. See `updatePerpBidAskTwap` for semantics.
Yes
settleFundingPayment
(userAccountPublicKey: PublicKey, txParams?: TxParams | undefined) => Promise<string>
Keeper instruction: settles accrued funding payments into the quote balance of every perp position the target user currently holds, using each market's latest `cumulativeFundingRateLong`/`Short` (FUNDING_RATE_PRECISION, 1e9). Fetches the user account fresh from the RPC (does not rely on this client's subscription cache) to determine which markets to include. Permissionless — any signer can act as keeper.
Yes
getSettleFundingPaymentIx
(userAccountPublicKey: PublicKey) => Promise<TransactionInstruction>
Builds the `settleFundingPayment` instruction. See `settleFundingPayment` for semantics. Fetches the user account directly via `program.account.user.fetch` and includes every market the user has a non-empty position in as a writable remaining account.
Yes
triggerEvent
(eventName: keyof VelocityClientAccountEvents, data?: any) => void
Manually emits an event on this client's internal `eventEmitter`, as if it had come from the account subscriber. Intended for tests/tooling that need to simulate account-update events; not used by normal instruction-building code paths.
Yes
getOracleDataForPerpMarket
(marketIndex: number) => OraclePriceData
Reads the last-known primary oracle price for a perp market from the account subscriber's cache (no RPC call). This is the raw exchange oracle price, unadjusted by the market's MM oracle — use `getMMOracleDataForPerpMarket` when you need the price the program actually uses for fills/margin.
Yes
getMMOracleDataForPerpMarket
(marketIndex: number) => MMOraclePriceData
Resolves the effective oracle price the program uses for `marketIndex` — the market's MM (market-maker-fed) oracle when it is fresher, valid, and not too divergent from the primary exchange oracle; otherwise falls back to the primary oracle. Mirrors the on-chain `get_mm_oracle_price_data` gating so client-side price reads (mark price, margin, liquidation previews) match what a fill/settlement will actually see. Falls back to the primary oracle (`getOracleDataForPerpMarket`) when any of the following hold: - the MM oracle price is zero (uninitialized) or its computed `OracleValidity` is `NonPositive`/`TooVolatile` (per `state.oracleGuardRails`); - the primary oracle is judged more recent than the MM oracle — by sequence-id ordering when both oracles have a usable, closely-matched `sequenceId`, otherwise by slot comparison; - the MM and primary oracle prices diverge by more than 1% (`PERCENTAGE_PRECISION`, 1e6 scale). Otherwise returns the MM oracle's price/slot/confidence.
Yes
getOracleDataForSpotMarket
(marketIndex: number) => OraclePriceData
Reads the last-known oracle price for a spot market from the account subscriber's cache (no RPC call). Spot markets do not have an MM oracle — this is always the effective price used for margin/borrow-lending calculations.
Yes
initializeInsuranceFundStake
(marketIndex: number, txParams?: TxParams | undefined) => Promise<string>
Creates this wallet's `InsuranceFundStake` PDA for `marketIndex`, required once before staking into that market's insurance fund for the first time. A caller may only initialize their own stake account. Reverts if insurance-fund init is paused for the market.
Yes
getInitializeInsuranceFundStakeIx
(marketIndex: number) => Promise<TransactionInstruction>
Builds the `initializeInsuranceFundStake` instruction. See `initializeInsuranceFundStake` for semantics.
Yes
getAddInsuranceFundStakeIx
(marketIndex: number, amount: BN, collateralAccountPublicKey: PublicKey) => Promise<TransactionInstruction>
Builds the `addInsuranceFundStake` instruction, transferring `amount` of the market's token from `collateralAccountPublicKey` into its insurance fund vault and minting the caller's `InsuranceFundStake` the corresponding IF shares. Reverts if `amount` is zero, the spot market is not active, insurance-fund add is paused, or a withdraw request is already in progress on the stake account. See `addInsuranceFundStake`/`getAddInsuranceFundStakeIxs` for a wrapper that also handles account creation and funding from a sub-account.
Yes
addInsuranceFundStake
({ marketIndex, amount, collateralAccountPublicKey, initializeStakeAccount, fromSubaccount, txParams, }: { marketIndex: number; amount: BN; collateralAccountPublicKey: PublicKey; initializeStakeAccount?: boolean; fromSubaccount?: boolean; txParams?: TxParams; }) => Promise<...>
Add to an insurance fund stake and optionally initialize the account
Yes
getAddInsuranceFundStakeIxs
({ marketIndex, amount, collateralAccountPublicKey, initializeStakeAccount, fromSubaccount, }: { marketIndex: number; amount: BN; collateralAccountPublicKey: PublicKey; initializeStakeAccount?: boolean; fromSubaccount?: boolean; }) => Promise<TransactionInstruction[]>
Get instructions to add to an insurance fund stake and optionally initialize the account
Yes
requestRemoveInsuranceFundStake
(marketIndex: number, amount: BN, txParams?: TxParams | undefined) => Promise<string>
Starts the unstaking cooldown for this wallet's insurance fund stake in `marketIndex`, locking in the number of IF shares corresponding to `amount` at the current share price. The actual withdrawal must be completed with `removeInsuranceFundStake` after `spotMarket.insuranceFund.unstakingPeriod` seconds have elapsed; only one request may be in-flight per stake account (`cancelRequestRemoveInsuranceFundStake` to reset). A caller may only act on their own stake account.
Yes
cancelRequestRemoveInsuranceFundStake
(marketIndex: number, txParams?: TxParams | undefined) => Promise<string>
Cancels this wallet's in-progress `requestRemoveInsuranceFundStake` for `marketIndex`, clearing the pending withdraw request so the stake resumes earning normally. Reverts if no withdraw request is currently in progress. A caller may only act on their own stake account.
Yes
removeInsuranceFundStake
(marketIndex: number, collateralAccountPublicKey: PublicKey, txParams?: TxParams | undefined) => Promise<string>
Completes a previously-requested insurance fund unstake for `marketIndex`, transferring the requested shares' worth of tokens from the insurance fund vault to `collateralAccountPublicKey` (creating it, and a temporary wrapped-SOL account if the market is SOL, when needed). Reverts if `spotMarket.insuranceFund.unstakingPeriod` has not yet elapsed since the matching `requestRemoveInsuranceFundStake`, or if the spot market's utilization is above the healthy threshold. A caller may only act on their own stake account.
Yes
updateUserQuoteAssetInsuranceStake
(authority: PublicKey, txParams?: TxParams | undefined) => Promise<string>
Keeper instruction: refreshes `authority`'s quote-market (`QUOTE_SPOT_MARKET_INDEX`) insurance fund stake bookkeeping (applies any pending rebase to the stake's share count/value) without adding or removing funds. `insuranceFundStake` and `userStats` must belong to the same authority. Permissionless — any signer can trigger the refresh for any staker.
Yes
getUpdateUserQuoteAssetInsuranceStakeIx
(authority: PublicKey) => Promise<TransactionInstruction>
Builds the `updateUserQuoteAssetInsuranceStake` instruction. See `updateUserQuoteAssetInsuranceStake` for semantics. Always targets `QUOTE_SPOT_MARKET_INDEX`.
Yes
settleRevenueToInsuranceFund
(spotMarketIndex: number, txParams?: TxParams | undefined) => Promise<string>
Keeper instruction: sweeps the market's proportional share of accumulated protocol revenue from its spot vault into its insurance fund vault. Only callable once per `spotMarket.insuranceFund.revenueSettlePeriod` seconds (on-the-hour aligned from `lastRevenueSettleTs`); reverts early with the remaining wait time otherwise. Reverts if the market has `revenueSettlePeriod <= 0` (settling to IF disabled). Permissionless — any signer can trigger the sweep.
Yes
getSettleRevenueToInsuranceFundIx
(spotMarketIndex: number) => Promise<TransactionInstruction>
Builds the `settleRevenueToInsuranceFund` instruction. See `settleRevenueToInsuranceFund` for semantics.
Yes
sweepPerpMarketFees
(perpMarketIndex: number, txParams?: TxParams | undefined) => Promise<string>
Permissionless streaming-sweep keeper instruction: materializes a perp market's accrued pending fee carveouts out of the PnL pool — `pendingProtocolFee` to the market's protocol fee pool (runs first, buffer-exempt), then `pendingIfFee` to the quote spot market's revenue pool and `pendingAmmProvision` into the AMM's fee pool (both leave `feePoolBufferTarget` behind). Every drain reserves `max(netUserPnl, 0)` so user claims stay backed. This runs inline on every `settlePNL` already — this instruction lets a keeper run it on demand without settling anyone's PnL. Gates the oracle price used to value `netUserPnl` the same way `settlePNL` does (price-band + validity/divergence checks when the market has curve updates enabled).
Yes
getSweepPerpMarketFeesIx
(perpMarketIndex: number) => Promise<TransactionInstruction>
Builds the `sweepPerpMarketFees` instruction. See `sweepPerpMarketFees` for semantics.
Yes
resolvePerpPnlDeficit
(spotMarketIndex: number, perpMarketIndex: number, txParams?: TxParams | undefined) => Promise<string>
Keeper instruction: backstops a perp market's negative PnL pool from the quote spot market's insurance fund (first attempting a revenue-to-IF settlement so the vault balance is up-to-date). `spotMarketIndex` must be `QUOTE_SPOT_MARKET_INDEX`. Permissionless — any signer can trigger it.
Yes
getResolvePerpPnlDeficitIx
(spotMarketIndex: number, perpMarketIndex: number) => Promise<TransactionInstruction>
Builds the `resolvePerpPnlDeficit` instruction. See `resolvePerpPnlDeficit` for semantics.
Yes
getDepositIntoSpotMarketRevenuePoolIx
(marketIndex: number, amount: BN, userTokenAccountPublicKey: PublicKey) => Promise<TransactionInstruction>
Builds the `depositIntoSpotMarketRevenuePool` instruction. See `depositIntoSpotMarketRevenuePool` for semantics.
Yes
depositIntoSpotMarketRevenuePool
(marketIndex: number, amount: BN, userTokenAccountPublicKey: PublicKey) => Promise<string>
This ix will donate your funds to velocity revenue pool. It does not deposit into your user account
Yes
getPerpMarketExtendedInfo
(marketIndex: number) => PerpMarketExtendedInfo
Computes display/risk metadata for a perp market from currently-subscribed account state (no RPC call): minimum order size, maintenance margin ratio, PnL pool value, contract tier, and the maximum insurance available to the market.
Yes
getMarketFees
(marketType: MarketType, marketIndex?: number | undefined, user?: User | undefined, orderParams?: Pick<OrderParams, "builderIdx" | "builderFeeTenthBps"> | undefined) => { ...; }
Calculates taker / maker fee (as a percentage, e.g. .001 = 10 basis points) for particular marketType
Yes
getMarketIndexAndType
(name: string) => { marketIndex: number; marketType: MarketType; } | undefined
Returns the market index and type for a given market name E.g. "SOL-PERP" -> &#123; marketIndex: 0, marketType: MarketType.PERP &#125;
Yes
postPythLazerOracleUpdate
(feedIds: number[], pythMessageHex: string) => Promise<string>
Posts a signed Pyth Lazer price update on-chain for one or more feeds, prepended with the Ed25519 signature-verification instruction the handler requires. Permissionless — any signer can post a valid, correctly-signed update.
Yes
getPostPythLazerOracleUpdateIxs
(feedIds: number[], pythMessageHex: string, precedingIxs?: TransactionInstruction[] | undefined, overrideCustomIxIndex?: number | undefined) => Promise<TransactionInstruction[]>
Builds the `postPythLazerOracleUpdate` instruction pair. See `postPythLazerOracleUpdate` for semantics.
Yes
getPauseSpotMarketDepositWithdrawIx
(spotMarketIndex: number) => Promise<TransactionInstruction>
Builds the `pauseSpotMarketDepositWithdraw` instruction. See `pauseSpotMarketDepositWithdraw` for semantics.
Yes
pauseSpotMarketDepositWithdraw
(spotMarketIndex: number, txParams?: TxParams | undefined) => Promise<string>
Emergency circuit-breaker instruction: pauses deposits and withdrawals for a spot market, but only when the on-chain handler detects the spot market's vault invariant has already been violated (actual vault balance diverges from the market's tracked deposit/borrow balances, e.g. from an exploit) — it reverts with an error if the vault amount is still valid, so this cannot be used to arbitrarily pause a healthy market. Permissionless — any signer can trigger it once the invariant is broken.
Yes
updateMmOracleNative
(marketIndex: number, oraclePrice: BN, oracleSequenceId: BN) => Promise<string>
Updates a perp market's market-maker (MM) oracle price using the program's high-frequency custom native entrypoint (bypasses Anchor's account deserialization overhead — see `createNativeInstructionDiscriminatorBuffer`). Restricted to the state's configured `hotMmOracleCrank` signer in production (unchecked under the `anchor-test` feature) and can be disabled entirely via a state feature-bit-flag kill switch. See `getMMOracleDataForPerpMarket` for how this price is subsequently gated against the primary oracle before use.
Yes
getUpdateMmOracleNativeIx
(marketIndex: number, oraclePrice: BN, oracleSequenceId: BN) => Promise<TransactionInstruction>
Builds the `updateMmOracleNative` instruction. See `updateMmOracleNative` for semantics. Hand- assembles the instruction (perp market, signer, clock sysvar, state) rather than going through `this.program.instruction`, since this targets the native (non-Anchor) entrypoint.
Yes
updateAmmSpreadAdjustmentNative
(marketIndex: number, ammSpreadAdjustment: number) => Promise<string>
Updates a perp market's AMM spread adjustment using the program's high-frequency custom native entrypoint. Restricted to the state's configured `hotAmmSpreadAdjust` signer in production (unchecked under the `anchor-test` feature).
Yes
getUpdateAmmSpreadAdjustmentNativeIx
(marketIndex: number, ammSpreadAdjustment: number) => Promise<TransactionInstruction>
Builds the `updateAmmSpreadAdjustmentNative` instruction. See `updateAmmSpreadAdjustmentNative` for semantics. Hand-assembles the instruction (perp market, signer, state) rather than going through `this.program.instruction`, since this targets the native (non-Anchor) entrypoint.
Yes
getLpPoolAccount
(lpPoolId: number) => Promise<LPPoolAccount>
Fetches an LP pool account by ID directly from the RPC (not from this client's subscription cache). An LP pool ("VLP") is a basket of spot-market "constituent" tokens that mints/redeems a pool token against deposits/withdrawals and absorbs perp AMM PnL to hedge the protocol's inventory risk (see `settlePerpToLpPool`).
Yes
getConstituentTargetBaseAccount
(lpPoolId: number) => Promise<ConstituentTargetBaseAccount>
Fetches the target-base weights for an LP pool's constituents directly from the RPC. Target base is each constituent's ideal share of the pool, derived from the AMMs it backs (`updateLpConstituentTargetBase`); swap/add/remove-liquidity fees are priced off deviation from these targets.
Yes
getAmmCache
() => Promise<AmmCache>
Fetches the program's single global AMM cache account directly from the RPC — a snapshot of each hedge-enabled perp market's inventory/price/PnL used by LP pool AUM, target-base, and settlement instructions without having to reload every perp market individually.
Yes
updateLpConstituentTargetBase
(lpPoolId: number, constituents: PublicKey[], txParams?: TxParams | undefined) => Promise<string>
Keeper instruction: recomputes each listed constituent's target-base weight from the current AMM cache (each hedge-enabled perp market's inventory relative to its constituents), used to price LP pool swap/add/remove-liquidity fees. Requires `updateAmmCache` to have run recently for the relevant markets. Permissionless — any signer can act as keeper.
Yes
getUpdateLpConstituentTargetBaseIx
(lpPoolId: number, constituents: PublicKey[]) => Promise<TransactionInstruction>
Builds the `updateLpConstituentTargetBase` instruction. See `updateLpConstituentTargetBase` for semantics.
Yes
updateLpPoolAum
(lpPool: LPPoolAccount, spotMarketIndexOfConstituents: number[], txParams?: TxParams | undefined) => Promise<string>
Keeper instruction: recomputes an LP pool's total AUM and per-constituent value from each constituent's spot market and vault balance, refreshing `lastAumSlot`. Swaps and add/remove liquidity revert with `LpPoolAumDelayed` if this has not run within `LP_POOL_SWAP_AUM_UPDATE_DELAY` slots of the action, so it must typically precede those instructions in the same transaction (see `getAllUpdateLpPoolAumIxs`). Permissionless — any signer can act as keeper.
Yes
getUpdateLpPoolAumIxs
(lpPool: LPPoolAccount, spotMarketIndexOfConstituents: number[]) => Promise<TransactionInstruction>
Builds the `updateLpPoolAum` instruction. See `updateLpPoolAum` for semantics.
Yes
updateAmmCache
(perpMarketIndexes: number[], txParams?: TxParams | undefined) => Promise<string>
Keeper instruction: refreshes the global AMM cache's per-market inventory/price/PnL snapshot for the given hedge-enabled perp markets, feeding LP pool AUM, target-base, and settlement math. Permissionless — any signer can act as keeper.
Yes
getUpdateAmmCacheIx
(perpMarketIndexes: number[]) => Promise<TransactionInstruction>
Builds the `updateAmmCache` instruction. See `updateAmmCache` for semantics.
Yes
updateConstituentOracleInfo
(constituent: ConstituentAccount) => Promise<string>
Keeper instruction: refreshes a single LP pool constituent's cached oracle price/slot from its spot market's oracle. Called ahead of AUM/target-base updates that need a fresh price for that constituent. Permissionless — any signer can act as keeper.
Yes
getUpdateConstituentOracleInfoIx
(constituent: ConstituentAccount) => Promise<TransactionInstruction>
Builds the `updateConstituentOracleInfo` instruction. See `updateConstituentOracleInfo` for semantics.
Yes
lpPoolSwap
(inMarketIndex: number, outMarketIndex: number, inAmount: BN, minOutAmount: BN, lpPool: PublicKey, userAuthority: PublicKey, txParams?: TxParams | undefined) => Promise<...>
Swaps `inMarketIndex` tokens for `outMarketIndex` tokens directly against an LP pool's constituent vaults (not the DLOB/AMM), paying a fee priced off each constituent's deviation from its target-base weight. Reverts if pool swaps are disabled, `inMarketIndex` equals `outMarketIndex`, or `updateLpPoolAum` has not run within `LP_POOL_SWAP_AUM_UPDATE_DELAY` slots (see `getAllLpPoolSwapIxs` for a wrapper that prepends the required AUM refresh).
Yes
getLpPoolSwapIx
(inMarketIndex: number, outMarketIndex: number, inAmount: BN, minOutAmount: BN, lpPool: PublicKey, userAuthority: PublicKey) => Promise<TransactionInstruction>
Builds the `lpPoolSwap` instruction. See `lpPoolSwap` for semantics.
Yes
viewLpPoolSwapFees
(inMarketIndex: number, outMarketIndex: number, inAmount: BN, inTargetWeight: BN, outTargetWeight: BN, lpPool: PublicKey, constituentTargetBase: PublicKey, constituentInTokenAccount: PublicKey, constituentOutTokenAccount: PublicKey, inConstituent: PublicKey, outConstituent: PublicKey, txParams?: TxParams | undefined...
Simulation-only instruction: computes what `lpPoolSwap` would charge for the given swap without moving any funds (intended to be run via `simulateTransaction`/a view call, not actually confirmed on-chain). Useful for quoting a swap's fee before submitting it.
Yes
getViewLpPoolSwapFeesIx
(inMarketIndex: number, outMarketIndex: number, inAmount: BN, inTargetWeight: BN, outTargetWeight: BN, lpPool: PublicKey, constituentTargetBase: PublicKey, constituentInTokenAccount: PublicKey, constituentOutTokenAccount: PublicKey, inConstituent: PublicKey, outConstituent: PublicKey) => Promise<...>
Builds the `viewLpPoolSwapFees` instruction. See `viewLpPoolSwapFees` for semantics.
Yes
getCreateLpPoolTokenAccountIx
(lpPool: LPPoolAccount) => Promise<TransactionInstruction>
Builds an idempotent instruction creating this wallet's associated token account for an LP pool's mint, needed before receiving pool tokens from `lpPoolAddLiquidity`.
Yes
createLpPoolTokenAccount
(lpPool: LPPoolAccount, txParams?: TxParams | undefined) => Promise<string>
Creates this wallet's associated token account for an LP pool's mint. See `getCreateLpPoolTokenAccountIx`.
Yes
lpPoolAddLiquidity
({ inMarketIndex, inAmount, minMintAmount, lpPool, txParams, }: { inMarketIndex: number; inAmount: BN; minMintAmount: BN; lpPool: LPPoolAccount; txParams?: TxParams; }) => Promise<string>
Deposits `inMarketIndex` tokens into an LP pool's matching constituent and mints LP pool tokens in return, priced at the pool's current AUM-derived share price. Reverts if mint/redeem is disabled, the constituent doesn't allow deposits (or is reduce-only and this isn't a reducing deposit), the pool is gated by a whitelist mint this wallet doesn't hold, or `updateLpPoolAum` has not run within `LP_POOL_SWAP_AUM_UPDATE_DELAY` slots (see `getAllLpPoolAddLiquidityIxs` for a wrapper that prepends the required AUM refresh).
Yes
getLpPoolAddLiquidityIx
({ inMarketIndex, inAmount, minMintAmount, lpPool, }: { inMarketIndex: number; inAmount: BN; minMintAmount: BN; lpPool: LPPoolAccount; }) => Promise<TransactionInstruction[]>
Builds the `lpPoolAddLiquidity` instruction (plus any needed wrapped-SOL / associated-token- account setup and teardown instructions). See `lpPoolAddLiquidity` for semantics.
Yes
viewLpPoolAddLiquidityFees
({ inMarketIndex, inAmount, lpPool, txParams, }: { inMarketIndex: number; inAmount: BN; lpPool: LPPoolAccount; txParams?: TxParams; }) => Promise<string>
Simulation-only instruction: computes what `lpPoolAddLiquidity` would mint/charge for the given deposit without moving any funds (intended for `simulateTransaction`, not confirmation).
Yes
getViewLpPoolAddLiquidityFeesIx
({ inMarketIndex, inAmount, lpPool, }: { inMarketIndex: number; inAmount: BN; lpPool: LPPoolAccount; }) => Promise<TransactionInstruction>
Builds the `viewLpPoolAddLiquidityFees` instruction. See `viewLpPoolAddLiquidityFees` for semantics.
Yes
lpPoolRemoveLiquidity
({ outMarketIndex, lpToBurn, minAmountOut, lpPool, txParams, }: { outMarketIndex: number; lpToBurn: BN; minAmountOut: BN; lpPool: LPPoolAccount; txParams?: TxParams; }) => Promise<string>
Burns LP pool tokens and withdraws `outMarketIndex` tokens from the pool's matching constituent in return, priced at the pool's current AUM-derived share price. Reverts if mint/redeem is disabled, the constituent doesn't allow withdrawals, or `updateLpPoolAum` has not run within `LP_POOL_SWAP_AUM_UPDATE_DELAY` slots (see `getAllLpPoolRemoveLiquidityIxs` for a wrapper that prepends the required perp settlement and AUM refresh).
Yes
getLpPoolRemoveLiquidityIx
({ outMarketIndex, lpToBurn, minAmountOut, lpPool, }: { outMarketIndex: number; lpToBurn: BN; minAmountOut: BN; lpPool: LPPoolAccount; }) => Promise<TransactionInstruction[]>
Builds the `lpPoolRemoveLiquidity` instruction (plus an idempotent associated-token-account creation instruction for a wrapped-SOL output, if needed). See `lpPoolRemoveLiquidity` for semantics.
Yes
viewLpPoolRemoveLiquidityFees
({ outMarketIndex, lpToBurn, lpPool, txParams, }: { outMarketIndex: number; lpToBurn: BN; lpPool: LPPoolAccount; txParams?: TxParams; }) => Promise<string>
Simulation-only instruction: computes what `lpPoolRemoveLiquidity` would return for the given burn without moving any funds (intended for `simulateTransaction`, not confirmation).
Yes
getViewLpPoolRemoveLiquidityFeesIx
({ outMarketIndex, lpToBurn, lpPool, }: { outMarketIndex: number; lpToBurn: BN; lpPool: LPPoolAccount; }) => Promise<TransactionInstruction>
Builds the `viewLpPoolRemoveLiquidityFees` instruction. See `viewLpPoolRemoveLiquidityFees` for semantics.
Yes
getAllLpPoolAddLiquidityIxs
({ inMarketIndex, inAmount, minMintAmount, lpPool, }: { inMarketIndex: number; inAmount: BN; minMintAmount: BN; lpPool: LPPoolAccount; }, constituentMap: ConstituentMap, includeUpdateConstituentOracleInfo?: boolean | undefined, view?: boolean | undefined) => Promise<...>
Convenience wrapper that prepends the AUM refresh `lpPoolAddLiquidity` requires (an `updateConstituentOracleInfo` per constituent, then `updateLpPoolAum`) ahead of either the real add-liquidity instruction or, when `view` is set, its fee-simulation counterpart.
Yes
getAllLpPoolRemoveLiquidityIxs
({ outMarketIndex, lpToBurn, minAmountOut, lpPool, }: { outMarketIndex: number; lpToBurn: BN; minAmountOut: BN; lpPool: LPPoolAccount; }, constituentMap: ConstituentMap, includeUpdateConstituentOracleInfo?: boolean | undefined, view?: boolean | undefined) => Promise<...>
Convenience wrapper that prepends what `lpPoolRemoveLiquidity` requires: settling every hedge- enabled perp market's PnL into the pool (`getAllSettlePerpToLpPoolIxs`) and refreshing AUM (`getAllUpdateLpPoolAumIxs`), ahead of either the real remove-liquidity instruction or, when `view` is set, its fee-simulation counterpart.
Yes
getAllUpdateLpPoolAumIxs
(lpPool: LPPoolAccount, constituentMap: ConstituentMap, includeUpdateConstituentOracleInfo?: boolean | undefined) => Promise<TransactionInstruction[]>
Builds the full instruction set to refresh an LP pool's AUM: one `updateConstituentOracleInfo` per constituent (optional) followed by `updateLpPoolAum` across all of them.
Yes
getAllUpdateConstituentTargetBaseIxs
(perpMarketIndexes: number[], lpPool: LPPoolAccount, constituentMap: ConstituentMap, includeUpdateConstituentOracleInfo?: boolean | undefined) => Promise<...>
Builds the full instruction set to refresh an LP pool's constituent target-base weights: `updateAmmCache` for the given markets, an optional `updateConstituentOracleInfo` per constituent, `updateLpConstituentTargetBase`, then a full AUM refresh (`getAllUpdateLpPoolAumIxs`, oracle info not repeated).
Yes
getAllLpPoolSwapIxs
(lpPool: LPPoolAccount, constituentMap: ConstituentMap, inMarketIndex: number, outMarketIndex: number, inAmount: BN, minOutAmount: BN, userAuthority: PublicKey) => Promise<...>
Convenience wrapper that prepends the AUM refresh `lpPoolSwap` requires ahead of the swap instruction itself.
Yes
settlePerpToLpPool
(lpPoolId: number, perpMarketIndexes: number[]) => Promise<string>
Keeper instruction: settles quote PnL owed between one or more hedge-enabled perp markets' fee and PnL pools and the LP pool's quote constituent, bounded by the pool's settle cap. Requires `updateAmmCache` to have run recently for the given markets. Permissionless — any signer can act as keeper.
Yes
getSettlePerpToLpPoolIx
(lpPoolId: number, perpMarketIndexes: number[]) => Promise<TransactionInstruction>
Builds the `settlePerpToLpPool` instruction. See `settlePerpToLpPool` for semantics.
Yes
getAllSettlePerpToLpPoolIxs
(lpPoolId: number, marketIndexes: number[]) => Promise<TransactionInstruction[]>
Builds the full instruction set to settle perp PnL into an LP pool: `updateAmmCache` for the given markets followed by `settlePerpToLpPool`.
Yes
handleSignedTransaction
any
Below here are the transaction sending functions
Yes
handlePreSignedTransaction
any
Yes
isVersionedTransaction
any
Yes
sendTransaction
(tx: VersionedTransaction | Transaction, additionalSigners?: Signer[] | undefined, opts?: ConfirmOptions | undefined, preSigned?: boolean | undefined) => Promise<...>
Signs (unless `preSigned`) and sends a transaction via this client's `txSender`, dispatching to `sendVersionedTransaction` or `send` based on whether `tx` is a `VersionedTransaction`. The shared low-level send path underlying nearly every instruction-building method on this class.
Yes
buildTransaction
(instructions: TransactionInstruction | TransactionInstruction[], txParams?: TxParams | undefined, txVersion?: TransactionVersion | undefined, lookupTables?: AddressLookupTableAccount[] | undefined, forceVersionedTransaction?: boolean | undefined, recentBlockhash?: Readonly<...> | undefined, optionalIxs?: Transactio...
Assembles one or more instructions into a single unsigned transaction via `this.txHandler`, applying compute-unit/priority-fee instructions from `txParams`, resolving address lookup tables for versioned transactions, and fetching a recent blockhash if not supplied. Used by nearly every instruction-building method on this class before sending.
Yes
buildBulkTransactions
(instructions: (TransactionInstruction | TransactionInstruction[])[], txParams?: TxParams | undefined, txVersion?: TransactionVersion | undefined, lookupTables?: AddressLookupTableAccount[] | undefined, forceVersionedTransaction?: boolean | undefined) => Promise<...>
Builds many independent transactions in one call — each entry in `instructions` becomes its own transaction via the same path as `buildTransaction`. An entry may build to `undefined` if the underlying `txHandler` implementation skips it (e.g. empty instruction list).
Yes
buildTransactionsMap
(instructionsMap: Record<string, TransactionInstruction | TransactionInstruction[]>, txParams?: TxParams | undefined, txVersion?: TransactionVersion | undefined, lookupTables?: AddressLookupTableAccount[] | undefined, forceVersionedTransaction?: boolean | undefined) => Promise<...>
Like `buildBulkTransactions`, but keyed by caller-chosen labels instead of array position — each value in `instructionsMap` becomes its own transaction, returned under the same key.
Yes
buildAndSignTransactionsMap
(instructionsMap: Record<string, TransactionInstruction | TransactionInstruction[]>, txParams?: TxParams | undefined, txVersion?: TransactionVersion | undefined, lookupTables?: AddressLookupTableAccount[] | undefined, forceVersionedTransaction?: boolean | undefined) => Promise<...>
Like `buildTransactionsMap`, but additionally signs every built transaction with this client's wallet before returning — useful for batching several independent, pre-signed transactions (e.g. to submit separately or hand off to `sendSignedTx`).
Yes
isOrderIncreasingPosition
(orderParams: OptionalOrderParams, subAccountId?: number | undefined) => boolean
Determines whether placing `orderParams` would increase the magnitude of the sub-account's existing perp position in that market (same-direction add, or opening a new position) as opposed to reducing/flattening/flipping it. Used by `placePerpOrder`/`placeOrders`/ `preparePlaceOrdersTx` to decide whether an `isolatedPositionDepositAmount` transfer should be prepended — that transfer only makes sense when the order grows the position.
Yes

Step 2: Get oracle price

Read the current oracle price to calculate your bid/ask spread.

import { PRICE_PRECISION, convertToNumber } from "@velocity-exchange/sdk"; const marketIndex = 0; // SOL-PERP const oracle = velocityClient.getOracleDataForPerpMarket(marketIndex); const oraclePrice = convertToNumber(oracle.price, PRICE_PRECISION); console.log(`Oracle price: $${oraclePrice}`);
Method VelocityClient.getOracleDataForPerpMarketReference ↗
ParameterTypeRequired
marketIndex
number
Perp market index.
Yes
Returns
OraclePriceData

Step 3: Place two-sided quotes

Place a bid (buy) below oracle and an ask (sell) above oracle. Using PostOnlyParams.MUST_POST_ONLY ensures your orders never cross and you always earn maker rebates.

import { PRICE_PRECISION, convertToNumber, MarketType, OrderType, PositionDirection, PostOnlyParams } from "@velocity-exchange/sdk"; const marketIndex = 0; // SOL-PERP const spread = 0.5; // $0.50 spread on each side const size = 0.1; // 0.1 SOL per order // Fetch oracle price for spread calculation const oracle = velocityClient.getOracleDataForPerpMarket(marketIndex); const oraclePrice = convertToNumber(oracle.price, PRICE_PRECISION); const bidPrice = oraclePrice - spread; const askPrice = oraclePrice + spread; await velocityClient.placeOrders([ { orderType: OrderType.LIMIT, marketType: MarketType.PERP, marketIndex, direction: PositionDirection.LONG, baseAssetAmount: velocityClient.convertToPerpPrecision(size), price: velocityClient.convertToPricePrecision(bidPrice), postOnly: PostOnlyParams.MUST_POST_ONLY, }, { orderType: OrderType.LIMIT, marketType: MarketType.PERP, marketIndex, direction: PositionDirection.SHORT, baseAssetAmount: velocityClient.convertToPerpPrecision(size), price: velocityClient.convertToPricePrecision(askPrice), postOnly: PostOnlyParams.MUST_POST_ONLY, }, ]); console.log(`Placed bid @ $${bidPrice}, ask @ $${askPrice}`);
Method VelocityClient.placeOrdersReference ↗
ParameterTypeRequired
params
OrderParams[]
Orders to place; `baseAssetAmount` is BASE_PRECISION (1e9) for perp (token-mint precision for spot), `price`/`triggerPrice`/`oraclePriceOffset` are PRICE_PRECISION (1e6).
Yes
txParams
TxParams
Optional compute-unit/priority-fee overrides.
No
subAccountId
number
Sub-account to place the orders for; defaults to the active sub-account.
No
optionalIxs
TransactionInstruction[]
Extra instructions to prepend to the transaction.
No
isolatedPositionDepositAmount
any
If set and `params` has exactly one perp order that increases the position, a transfer into an isolated-margin position (token-mint precision) is prepended before placing. Ignored for batches of more than one order.
No
Returns
Promise<string>

Step 4: Monitor and update

Check for fills and cancel/replace orders when the oracle moves. This complete example runs a loop that refreshes quotes every 10 seconds.

import { PRICE_PRECISION, BASE_PRECISION, convertToNumber, MarketType, OrderType, PositionDirection, PostOnlyParams, } from "@velocity-exchange/sdk"; const marketIndex = 0; const spread = 0.5; const size = 0.1; setInterval(async () => { try { // Check current position const user = velocityClient.getUser(); const position = user.getPerpPosition(marketIndex); if (position) { const posSize = convertToNumber(position.baseAssetAmount, BASE_PRECISION); console.log(`Current position: ${posSize} SOL`); } // Cancel all existing orders for this market await velocityClient.cancelOrders(MarketType.PERP, marketIndex); // Re-fetch oracle price const oracle = velocityClient.getOracleDataForPerpMarket(marketIndex); const oraclePrice = convertToNumber(oracle.price, PRICE_PRECISION); const bidPrice = oraclePrice - spread; const askPrice = oraclePrice + spread; // Place fresh two-sided quotes await velocityClient.placeOrders([ { orderType: OrderType.LIMIT, marketType: MarketType.PERP, marketIndex, direction: PositionDirection.LONG, baseAssetAmount: velocityClient.convertToPerpPrecision(size), price: velocityClient.convertToPricePrecision(bidPrice), postOnly: PostOnlyParams.MUST_POST_ONLY, }, { orderType: OrderType.LIMIT, marketType: MarketType.PERP, marketIndex, direction: PositionDirection.SHORT, baseAssetAmount: velocityClient.convertToPerpPrecision(size), price: velocityClient.convertToPricePrecision(askPrice), postOnly: PostOnlyParams.MUST_POST_ONLY, }, ]); console.log(`Updated quotes: bid $${bidPrice.toFixed(2)} / ask $${askPrice.toFixed(2)}`); } catch (err) { console.error("Error updating quotes:", err); } }, 10_000); // Update every 10 seconds
Method VelocityClient.cancelOrdersReference ↗
ParameterTypeRequired
marketType
MarketType
Only cancel orders of this market type (`PERP`/`SPOT`); combined with `marketIndex` to scope to one perp or spot market.
No
marketIndex
number
Only cancel orders in this market index.
No
direction
PositionDirection
Only cancel orders on this side (`LONG`/`SHORT`).
No
txParams
TxParams
Optional compute-unit/priority-fee overrides.
No
subAccountId
number
Sub-account to cancel orders for; defaults to the active sub-account.
No
Returns
Promise<string>

Tip: This cancel-and-replace approach sends ~2 transactions every 10 seconds. For production, consider oracle offset orders which float with the oracle automatically and require only ~30 txs/day.

Next steps

This basic example gets you started, but production market makers need:

  • Oracle offset orders: orders that automatically track oracle price, drastically reducing transactions (DLOB MM)
  • Inventory management: adjust spread based on position size (DLOB MM)
  • Risk controls: position limits, health checks, emergency cancel (Bot Architecture)
  • JIT participation: compete in auctions for better fills (JIT-only MM)
  • Efficient subscriptions: WebSocket or gRPC for lower latency (Bot Architecture)
  • Multiple markets: quote across markets simultaneously

Common pitfalls

  • Forgetting PostOnlyParams: without it, your “maker” orders can cross the spread and execute as taker, paying fees instead of earning rebates
  • Using PRICE_PRECISION wrong: oracle prices are in PRICE_PRECISION (1e6), base amounts in BASE_PRECISION (1e9). Mixing them up causes orders at wildly wrong prices
  • Not initializing user account: first-time users must call velocityClient.initializeUserAccount() before placing orders. The SDK will throw User account not found otherwise
  • 32-order limit: each Velocity subaccount supports a maximum of 32 open orders. Cancel stale orders or use multiple subaccounts for multi-market strategies

For production patterns and best practices, see:

Last updated on