Swaps (Jupiter / Titan)
You can route spot swaps through Jupiter or Titan directly from your Velocity account. The SDK fetches a quote from the chosen provider, builds the swap transaction, and wraps it with begin_swap/end_swap so the input and output tokens flow through your Velocity spot balances in a single, atomically-checked transaction.
This is a collateral swap between two spot balances inside your Velocity account — unrelated to spot order placement. Velocity removed spot DLOB trading entirely (place_spot_order and friends no longer exist), but swapping the tokens backing your spot balances via an aggregator is a separate, still-supported code path.
Choosing a swap client
UnifiedSwapClient is the primary interface for swaps — it wraps either Jupiter or Titan behind one API, so you can switch providers without changing call sites:
import { Connection } from "@solana/web3.js";
import { UnifiedSwapClient } from "@velocity-exchange/sdk";
const connection = new Connection("<RPC_URL>", "confirmed");
// clientType: 'jupiter' | 'titan'
const swapClient = new UnifiedSwapClient({
clientType: "jupiter",
connection,
authToken: "<JUPITER_API_KEY_OR_TITAN_AUTH_TOKEN>", // Jupiter: API key (portal.jup.ag). Titan: auth token (not needed behind a proxy)
});Class UnifiedSwapClientReference ↗
Class UnifiedSwapClientReference ↗| Property | Type | Required |
|---|---|---|
client | any | Yes |
clientType | any | Yes |
getQuote | (params: SwapQuoteParams) => Promise<UnifiedQuoteResponse>Get a swap quote from the underlying client | Yes |
getSwap | (params: SwapTransactionParams) => Promise<SwapTransactionResult>Get a swap transaction from the underlying client | Yes |
getSwapInstructions | ({ inputMint, outputMint, amount, userPublicKey, slippageBps, swapMode, onlyDirectRoutes, quote, sizeConstraint, }: { inputMint: PublicKey; outputMint: PublicKey; amount: BN; userPublicKey: PublicKey; slippageBps?: number; swapMode?: SwapMode; onlyDirectRoutes?: boolean; quote?: UnifiedQuoteResponse; sizeConstraint?...Get swap instructions from the underlying client (Jupiter or Titan)
This is the core swap logic without any context preparation | Yes |
getClient | () => JupiterClient | TitanClientGet the underlying client instance | Yes |
getClientType | () => SwapClientTypeGet the client type | Yes |
isJupiter | () => booleanCheck if this is a Jupiter client | Yes |
isTitan | () => booleanCheck if this is a Titan client | Yes |
The standalone JupiterClient remains available and is accepted directly by VelocityClient.swap() for backward compatibility, but new integrations should prefer UnifiedSwapClient:
import { Connection } from "@solana/web3.js";
import { JupiterClient } from "@velocity-exchange/sdk";
const connection = new Connection("<RPC_URL>", "confirmed");
const jupiterClient = new JupiterClient({ connection });Class JupiterClientReference ↗
Class JupiterClientReference ↗| Property | Type | Required |
|---|---|---|
url | string | Yes |
connection | Connection | Yes |
lookupTableCahce | Map<string, AddressLookupTableAccount> | Yes |
apiKey | any | No |
getHeaders | anyGet the headers for API requests, including API key if configured | Yes |
getQuote | ({ inputMint, outputMint, amount, maxAccounts, slippageBps, swapMode, onlyDirectRoutes, excludeDexes, autoSlippage, maxAutoSlippageBps, usdEstimate, }: { inputMint: PublicKey; outputMint: PublicKey; amount: BN; maxAccounts?: number; slippageBps?: number; swapMode?: SwapMode; onlyDirectRoutes?: boolean; excludeDexes?...Get routes for a swap | Yes |
getSwap | ({ quote, userPublicKey, slippageBps, }: { quote: QuoteResponse; userPublicKey: PublicKey; slippageBps?: number; }) => Promise<VersionedTransaction>Get a swap transaction for quote | Yes |
getTransactionMessageAndLookupTables | ({ transaction, }: { transaction: VersionedTransaction; }) => Promise<{ transactionMessage: TransactionMessage; lookupTables: AddressLookupTableAccount[]; }>Get the transaction message and lookup tables for a transaction | Yes |
getLookupTable | (accountKey: PublicKey) => Promise<AddressLookupTableAccount | undefined> | Yes |
getJupiterInstructions | ({ transactionMessage, inputMint, outputMint, }: { transactionMessage: TransactionMessage; inputMint: PublicKey; outputMint: PublicKey; }) => TransactionInstruction[]Get the jupiter instructions from transaction by filtering out instructions to compute budget and associated token programs | Yes |
Getting a quote
Preview the expected output and route before committing. UnifiedSwapClient.getQuote() normalizes the request across both providers (Titan additionally requires userPublicKey):
const quote = await swapClient.getQuote({
inputMint: usdcMint, // PublicKey
outputMint: solMint, // PublicKey
amount: velocityClient.convertToSpotPrecision(0, 10), // 10 USDC, BN
slippageBps: 50,
userPublicKey: velocityClient.wallet.publicKey, // required for Titan, ignored by Jupiter
});
console.log(quote);Method UnifiedSwapClient.getQuoteReference ↗
Method UnifiedSwapClient.getQuoteReference ↗| Parameter | Type | Required |
|---|---|---|
params | SwapQuoteParams | Yes |
| Returns |
|---|
Promise<UnifiedQuoteResponse> |
Executing the swap
VelocityClient.swap() accepts a swapClient (a UnifiedSwapClient, or a raw JupiterClient for the deprecated legacy path), fetches/uses the route, and sends the transaction so tokens move in and out of your Velocity spot balances:
// Assumes `velocityClient` is subscribed.
const txSig = await velocityClient.swap({
swapClient,
inMarketIndex: 0, // e.g. USDC (spot market index)
outMarketIndex: 1, // e.g. SOL (spot market index)
amount: velocityClient.convertToSpotPrecision(0, 10), // 10 USDC
slippageBps: 50, // 0.5% max slippage
onlyDirectRoutes: false, // allow multi-hop routes for better pricing
});
console.log(txSig);Method VelocityClient.swapReference ↗
Method VelocityClient.swapReference ↗| Parameter | Type | Required |
|---|---|---|
__0 | { swapClient?: UnifiedSwapClient | SwapClient; jupiterClient?: JupiterClient; outMarketIndex: number; inMarketIndex: number; outAssociatedTokenAccount?: PublicKey; ... 8 more ...; quote?: UnifiedQuoteResponse; }Swap client used to fetch routes/instructions (`UnifiedSwapClient` or a
`TitanClient`); dispatches to `getSwapIxV2` or `getTitanSwapIx` respectively. | Yes |
| Returns |
|---|
Promise<string> |
Parameters:
| Parameter | Description | Optional | Default |
|---|---|---|---|
swapClient | UnifiedSwapClient (preferred) wrapping Jupiter or Titan | No* | |
jupiterClient | @deprecated legacy JupiterClient instance; use swapClient instead | No* | |
inMarketIndex | Velocity spot market index for the input token | No | |
outMarketIndex | Velocity spot market index for the output token | No | |
amount | Amount to swap as a BN, spot market precision | No | |
slippageBps | Maximum allowed slippage in basis points | Yes | 50 |
swapMode | 'ExactIn' or 'ExactOut' | Yes | 'ExactIn' |
onlyDirectRoutes | If true, restricts to direct token pairs only (no multi-hop) | Yes | false |
reduceOnly | SwapReduceOnly — constrain the in/out token balance to reduce-only at swap end | Yes | |
quote | Pre-fetched quote (from getQuote()) to skip an extra round-trip | Yes | |
txParams | Compute-unit/priority-fee overrides | Yes |
* Exactly one of swapClient or jupiterClient must be provided.
TitanClient itself is an internal implementation detail and is not exported from the SDK root — construct Titan-backed swaps through new UnifiedSwapClient({ clientType: "titan", ... }) rather than importing TitanClient directly.