The Titan instructions module enables vault managers and allocators to swap tokens through Titan, a Solana DEX aggregator. The integration works in two steps: fetch a swap quote from Titan’s API, then wrap the resulting instruction in a Squads sync transaction.
Titan swap quotes are fetched over a WebSocket connection that requires authentication credentials (wsUrl and authToken).
Transaction Structure
Every Titan interaction goes through createVaultSyncTransaction, which returns three parts:
const { preInstructions, instruction, postInstructions } =
await createVaultSyncTransaction({
instructions, // Array of VaultInstruction descriptors
owner, // Vault PDA (the Squads smart account)
connection,
policyPda, // Policy authorizing this execution
vaultPda, // Squads vault PDA
signer, // The allocator or manager wallet
vaultAddress, // ExponentStrategyVault PDA (auto-resolves hook accounts)
});
// Send all three parts in order
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
| Part | What it contains | Why it’s separate |
|---|
preInstructions | Any permissionless setup instructions | Must be top-level instructions |
instruction | Squads sync transaction wrapping all vault-signed instructions | Executes with the vault’s smart account as signer |
postInstructions | Any post-operation instructions | Must be top-level instructions |
Fetching a Quote
getTitanQuote connects to Titan’s WebSocket API, requests a swap route, and returns a TransactionInstruction along with any Address Lookup Table addresses needed for transaction compilation.
import { getTitanQuote } from "@exponent-labs/exponent-sdk";
import { Connection, PublicKey } from "@solana/web3.js";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const quoteResult = await getTitanQuote(connection, {
wsUrl: "wss://...", // Titan WebSocket URL
authToken: "...", // Titan API auth token
}, {
inputMint: new PublicKey("..."), // Token to sell
outputMint: new PublicKey("..."), // Token to buy
amount: 1_000_000_000n, // Amount of input token in native units
slippageBps: 50, // Slippage tolerance in basis points
userPublicKey: vaultPda, // The vault's smart account (trader)
});
Parameters
| Parameter | Type | Description |
|---|
connection | Connection | Solana RPC connection |
auth.wsUrl | string | Titan WebSocket endpoint URL |
auth.authToken | string | Titan API authentication token |
params.inputMint | PublicKey | Mint address of the token to sell |
params.outputMint | PublicKey | Mint address of the token to buy |
params.amount | bigint | Amount of input token in native units |
params.slippageBps | number | Optional. Slippage tolerance in basis points |
params.userPublicKey | PublicKey | The trader’s public key — use the vault’s Squads PDA |
Return Value
| Field | Type | Description |
|---|
instruction | TransactionInstruction | The Titan SwapRouteV2 instruction to execute |
addressLookupTableAddresses | PublicKey[] | Address Lookup Table addresses from the Titan route |
The quote has a timeout of 15 seconds. Fetch the quote and submit the transaction promptly to avoid stale routes.
Executing a Swap
titanAction.swap wraps the instruction from getTitanQuote into a vault instruction descriptor for createVaultSyncTransaction.
import {
titanAction,
createVaultSyncTransaction,
} from "@exponent-labs/exponent-sdk";
const { preInstructions, instruction, postInstructions } =
await createVaultSyncTransaction({
instructions: [
titanAction.swap({
instruction: quoteResult.instruction,
}),
],
owner: vaultPda,
connection,
policyPda,
vaultPda,
signer: wallet.publicKey,
vaultAddress,
});
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);
Parameters
| Parameter | Type | Description |
|---|
instruction | TransactionInstruction | The Titan SwapRouteV2 instruction returned by getTitanQuote |
The addressLookupTableAddresses returned by getTitanQuote may be needed when compiling a V0 (versioned) transaction message. Fetch the lookup table accounts on-chain and include them in the TransactionMessage if using versioned transactions.
A matching policy must exist before executing. See Policy Builders.
Full Flow Example
This example demonstrates fetching a Titan swap quote and executing it through the vault.
Step 1: Fetch Swap Quote
import {
getTitanQuote,
titanAction,
createVaultSyncTransaction,
} from "@exponent-labs/exponent-sdk";
import { Connection, PublicKey, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const INPUT_MINT = new PublicKey("..."); // e.g., USDC
const OUTPUT_MINT = new PublicKey("..."); // e.g., SOL
const quoteResult = await getTitanQuote(connection, {
wsUrl: "wss://...",
authToken: "...",
}, {
inputMint: INPUT_MINT,
outputMint: OUTPUT_MINT,
amount: 1_000_000_000n,
slippageBps: 50,
userPublicKey: vaultPda,
});
Step 2: Execute Swap Through Vault
const { preInstructions, instruction, postInstructions } =
await createVaultSyncTransaction({
instructions: [
titanAction.swap({
instruction: quoteResult.instruction,
}),
],
owner: vaultPda,
connection,
policyPda,
vaultPda,
signer: wallet.publicKey,
vaultAddress,
});
const tx = new Transaction().add(...preInstructions, instruction, ...postInstructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);