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.comis 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 supportsaccountSubscribe.
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 ↗
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`.
| Property | Type | Required |
|---|---|---|
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 | booleanWhether 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) => stringBuilds 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) => UserConstructs (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 | () => PublicKeyReturns 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 | () => StateAccountReturns 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 | undefinedReturns 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) => PerpMarketAccountLike `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 | undefinedReturns the last account-subscriber-cached `SpotMarketAccount` for a market index. Does not hit
RPC. | Yes |
getSpotMarketAccountOrThrow | (marketIndex: number) => SpotMarketAccountLike `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 | () => SpotMarketAccountConvenience 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> | undefinedReturns 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 = { [newWallet.publicKey]: subAccountIds }`. | 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) => UserLooks up an already-loaded `User` from `this.users` (does not fetch or subscribe). | Yes |
hasUser | (subAccountId?: number | undefined, authority?: PublicKey | undefined) => booleanChecks 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 | undefinedReturns the `UserStats` instance for `this.authority`, if one was constructed (via
`config.userStats`, `updateWallet`, `emulateAccount`, or `switchActiveUser`). | Yes |
getUserStatsOrThrow | () => UserStatsLike `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 | () => PublicKeyReturns 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 | undefinedReturns the last subscriber-cached `UserAccount` data for a loaded sub-account. Does not hit RPC. | Yes |
getUserAccountOrThrow | (subAccountId?: number | undefined, authority?: PublicKey | undefined) => UserAccountLike `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> | undefinedLike `getUserAccount` but also returns the slot the data was last observed at. | Yes |
getSpotPosition | (marketIndex: number, subAccountId?: number | undefined) => SpotPosition | undefinedReturns a sub-account's spot balance entry for a market, if it holds one. | Yes |
getQuoteAssetTokenAmount | () => BNConvenience accessor for the active sub-account's quote (USDC) token amount. | Yes |
getIsolatedPerpPositionTokenAmount | (perpMarketIndex: number, subAccountId?: number | undefined) => BNReturns 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) => BNReturns 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) => BNConverts 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) => BNConverts a human-readable (UI) base-asset amount to `BASE_PRECISION` (1e9), the precision used for
perp/spot order base amounts. | Yes |
convertToPricePrecision | (amount: any) => BNConverts a human-readable (UI) price to `PRICE_PRECISION` (1e6). | Yes |
mustIncludeMarketsInIx | ({ perpMarketIndexes, spotMarketIndexes, }: { perpMarketIndexes: number[]; spotMarketIndexes: number[]; }) => voidEach 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<...>) => voidAdds 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>) => voidAdds 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[]) => voidAppends 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 | undefinedLook 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 | undefinedLook 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) => TransactionInstructionBuilds 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) => PublicKeyReturns the correct SPL token program (classic or Token-2022) for a spot market's mint, based on
its `tokenProgramFlag`. | Yes |
isToken2022 | (spotMarketAccount: SpotMarketAccount) => booleanChecks whether a spot market's mint belongs to the Token-2022 program. | Yes |
isTransferHook | (spotMarketAccount: SpotMarketAccount) => booleanChecks 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[]) => voidAppends 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) => TransactionInstructionBuilds 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 | anyReturns 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 | anyReturns 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) => SignedMsgOrderParamsBorsh-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) => BufferBorsh-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 | SignedMsgOrderParamsDelegateMessageDecodes 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) => BufferSigns 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) => voidManually 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) => OraclePriceDataReads 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) => MMOraclePriceDataResolves 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) => OraclePriceDataReads 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) => PerpMarketExtendedInfoComputes 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; } | undefinedReturns the market index and type for a given market name
E.g. "SOL-PERP" -> { marketIndex: 0, marketType: MarketType.PERP } | 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 | anyBelow 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) => booleanDetermines 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 ↗
Method VelocityClient.getOracleDataForPerpMarketReference ↗| Parameter | Type | Required |
|---|---|---|
marketIndex | numberPerp 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 ↗
Method VelocityClient.placeOrdersReference ↗| Parameter | Type | Required |
|---|---|---|
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 | TxParamsOptional compute-unit/priority-fee overrides. | No |
subAccountId | numberSub-account to place the orders for; defaults to the active sub-account. | No |
optionalIxs | TransactionInstruction[]Extra instructions to prepend to the transaction. | No |
isolatedPositionDepositAmount | anyIf 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 secondsMethod VelocityClient.cancelOrdersReference ↗
Method VelocityClient.cancelOrdersReference ↗| Parameter | Type | Required |
|---|---|---|
marketType | MarketTypeOnly cancel orders of this market type (`PERP`/`SPOT`); combined with
`marketIndex` to scope to one perp or spot market. | No |
marketIndex | numberOnly cancel orders in this market index. | No |
direction | PositionDirectionOnly cancel orders on this side (`LONG`/`SHORT`). | No |
txParams | TxParamsOptional compute-unit/priority-fee overrides. | No |
subAccountId | numberSub-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_PRECISIONwrong: oracle prices are inPRICE_PRECISION(1e6), base amounts inBASE_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 throwUser account not foundotherwise - 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:
- DLOB MM - comprehensive quoting strategies including oracle offset orders
- Bot Architecture - subscription loops, throttling, priority fees
- keeper-bots-v2
FloatingPerpMaker- production reference for oracle offset quoting