Skip to Content
DevelopersVelocity SDKSwaps (Jupiter / Titan)

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 ↗
PropertyTypeRequired
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 | TitanClient
Get the underlying client instance
Yes
getClientType
() => SwapClientType
Get the client type
Yes
isJupiter
() => boolean
Check if this is a Jupiter client
Yes
isTitan
() => boolean
Check if this is a Titan client
Yes

The standalone JupiterClient remains available. Both JupiterClient and TitanClient implement the same SwapProvider interface as UnifiedSwapClient, so a raw JupiterClient can be passed as swapClient 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 ↗
PropertyTypeRequired
url
string
Yes
connection
Connection
Yes
lookupTableCahce
Map<string, AddressLookupTableAccount>
Yes
apiKey
any
No
getHeaders
any
Get 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

Jupiter Swap API v1 versus v2

JupiterClient takes an apiVersion of 'v1' or 'v2'. It defaults to 'v1'. UnifiedSwapClient forwards the same choice as jupiterApiVersion (ignored when clientType is 'titan').

'v1' (default)'v2'
EndpointsGET /swap/v1/quote, then POST /swap/v1/swapGET /swap/v2/build only
Round trips per swapTwo, plus deserializing the returned transactionOne, the quote carries the route instructions
userPublicKey on getQuoteOptionalRequired, v2 builds for a named taker
autoSlippageSupportedRejected, getQuote throws
swapMode'ExactIn' or 'ExactOut''ExactIn' only, anything else throws
onlyDirectRoutesSupportedRejected, getQuote throws
import { JupiterClient, UnifiedSwapClient } from "@velocity-exchange/sdk"; // Opt into v2 on the standalone client const jupiterV2 = new JupiterClient({ connection, apiKey: "<JUPITER_API_KEY>", apiVersion: "v2", }); // Or through the unified client const swapClient = new UnifiedSwapClient({ clientType: "jupiter", connection, authToken: "<JUPITER_API_KEY>", jupiterApiVersion: "v2", });
Example apiVersionReference ↗
TypeScript docs unavailable for apiVersion.

The v2 rejections are deliberate. Jupiter’s /swap/v2/build answers 200 for autoSlippage, onlyDirectRoutes, and ExactOut while ignoring them: auto-slippage comes back with zero slippage tolerance (any adverse move reverts the swap), direct-only still returns multi-hop routes, and ExactOut comes back as ExactIn with your amount spent as the input, which inverts the trade. The SDK throws instead of passing those through. If you need any of the three, construct the client with apiVersion: 'v1'.

The Rust SDK (velocity-rs) is v2 only. Its Jupiter path has no v1 mode and no version toggle: jupiter_swap_query has no swap_mode, transaction_config, or only_direct_routes parameters, and it takes max_accounts: Option<usize> (defaulting to 50) as the remaining routing lever. Rust consumers get the v2 behavior described above whether or not they opt in.

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: usdtMint, // PublicKey outputMint: solMint, // PublicKey amount: velocityClient.convertToSpotPrecision(0, 10), // 10 USDT, BN slippageBps: 50, userPublicKey: velocityClient.wallet.publicKey, // required for Titan, and for Jupiter's v2 API; ignored by Jupiter v1 (the default) }); console.log(quote);
Method UnifiedSwapClient.getQuoteReference ↗
ParameterTypeRequired
params
SwapQuoteParams
Yes
Returns
Promise<UnifiedQuoteResponse>

Executing the swap

VelocityClient.swap() accepts a swapClient (a UnifiedSwapClient, or a raw JupiterClient/TitanClient 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. USDT (spot market index) outMarketIndex: 1, // e.g. SOL (spot market index) amount: velocityClient.convertToSpotPrecision(0, 10), // 10 USDT slippageBps: 50, // 0.5% max slippage onlyDirectRoutes: false, // allow multi-hop routes for better pricing }); console.log(txSig);
Method VelocityClient.swapReference ↗
ParameterTypeRequired
__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:

ParameterDescriptionOptionalDefault
swapClientUnifiedSwapClient (preferred), or a raw JupiterClient/TitanClient for the deprecated legacy pathNo
inMarketIndexVelocity spot market index for the input tokenNo
outMarketIndexVelocity spot market index for the output tokenNo
amountAmount to swap as a BN, spot market precisionNo
slippageBpsMaximum allowed slippage in basis pointsYes50
swapMode'ExactIn' or 'ExactOut'Yes'ExactIn'
onlyDirectRoutesIf true, restricts to direct token pairs only (no multi-hop)Yesfalse
reduceOnlySwapReduceOnly: constrain the in/out token balance to reduce-only at swap endYes
quotePre-fetched quote (from getQuote()) to skip an extra round-tripYes
txParamsCompute-unit/priority-fee overridesYes

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.

Last updated on