# Table of Contents - [Home | Developer Docs | Titan](#home-developer-docs-titan) - [Introduction | Developer Docs | Titan](#introduction-developer-docs-titan) - [Quickstart | Developer Docs | Titan](#quickstart-developer-docs-titan) - [Authentication | Developer Docs | Titan](#authentication-developer-docs-titan) - [Get API Access | Developer Docs | Titan](#get-api-access-developer-docs-titan) - [Guides | Developer Docs | Titan](#guides-developer-docs-titan) - [API Reference | Developer Docs | Titan](#api-reference-developer-docs-titan) - [Overview | Developer Docs | Titan](#overview-developer-docs-titan) - [Get API Access | Developer Docs | Titan](#get-api-access-developer-docs-titan) - [How to Use | Developer Docs | Titan](#how-to-use-developer-docs-titan) - [Overview | Developer Docs | Titan](#overview-developer-docs-titan) - [Placing Taker Orders | Developer Docs | Titan](#placing-taker-orders-developer-docs-titan) - [Limit Order Events | Developer Docs | Titan](#limit-order-events-developer-docs-titan) - [Welcome to Titan | Titan](#welcome-to-titan-titan) - [Error Codes | Developer Docs | Titan](#error-codes-developer-docs-titan) - [Meta Aggregation | Titan](#meta-aggregation-titan) - [SDK Reference | Developer Docs | Titan](#sdk-reference-developer-docs-titan) - [DART Routing | Titan](#dart-routing-titan) - [Private Beta | Titan](#private-beta-titan) - [DEX Aggregators | Titan](#dex-aggregators-titan) - [How Swaps Work | Titan](#how-swaps-work-titan) - [Titan Private Swaps | Titan](#titan-private-swaps-titan) - [Analytics | Titan](#analytics-titan) - [Titan DEX Integrations | Titan](#titan-dex-integrations-titan) - [Titan's Unique Algorithm | Titan](#titan-s-unique-algorithm-titan) - [Quickstart | Titan](#quickstart-titan) - [Titan DART | Titan](#titan-dart-titan) - [Titan Direct vs Titan Gateway | Developer Docs | Titan](#titan-direct-vs-titan-gateway-developer-docs-titan) - [Titan Gateway | Developer Docs | Titan](#titan-gateway-developer-docs-titan) - [Connection & Negotiation | Developer Docs | Titan](#connection-negotiation-developer-docs-titan) - [Quote Swap | Developer Docs | Titan](#quote-swap-developer-docs-titan) - [Quote Price | Developer Docs | Titan](#quote-price-developer-docs-titan) - [Configure Routing | Developer Docs | Titan](#configure-routing-developer-docs-titan) - [Swap V2 vs Swap V3 | Developer Docs | Titan](#swap-v2-vs-swap-v3-developer-docs-titan) - [Transaction Template | Developer Docs | Titan](#transaction-template-developer-docs-titan) - [Fee Collection | Developer Docs | Titan](#fee-collection-developer-docs-titan) - [Error Handling & Reconnect | Developer Docs | Titan](#error-handling-reconnect-developer-docs-titan) - [Titan Direct | Developer Docs | Titan](#titan-direct-developer-docs-titan) - [GetInfo | Developer Docs | Titan](#getinfo-developer-docs-titan) - [Stream & Execute a Swap | Developer Docs | Titan](#stream-execute-a-swap-developer-docs-titan) - [Types Reference | Developer Docs | Titan](#types-reference-developer-docs-titan) - [Usernames and Referrals | Titan](#usernames-and-referrals-titan) - [StopStream | Developer Docs | Titan](#stopstream-developer-docs-titan) - [GetVenues / ListProviders | Developer Docs | Titan](#getvenues-listproviders-developer-docs-titan) - [Prime Mode and Custom Settings | Titan](#prime-mode-and-custom-settings-titan) - [GetSwapPrice | Developer Docs | Titan](#getswapprice-developer-docs-titan) - [Info / Venues / Providers | Developer Docs | Titan](#info-venues-providers-developer-docs-titan) - [Community & Support | Developer Docs | Titan](#community-support-developer-docs-titan) - [Wire Protocol | Developer Docs | Titan](#wire-protocol-developer-docs-titan) - [Titan Limit Orders | Titan](#titan-limit-orders-titan) - [AI / LLM Integration | Developer Docs | Titan](#ai-llm-integration-developer-docs-titan) - [NewSwapQuoteStream | Developer Docs | Titan](#newswapquotestream-developer-docs-titan) - [Error Codes | Developer Docs | Titan](#error-codes-developer-docs-titan) - [Titan](#titan) --- # Home | Developer Docs | Titan ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F3919091904-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FOcDzWOE77OJI2Qje9dcH%252Fuploads%252Fgit-blob-7ad244c7e4f10bcb574a05cddb166c010750826d%252Fimage.png%3Falt%3Dmedia&width=768&dpr=3&quality=100&sign=c03019a9&sv=2) Titan is the swap meta-aggregator behind the best execution on Solana. Quotes from multiple providers, simulated on-chain by **Argos**, returned as ready-to-sign transactions. **New: DART Swap API** — Try Titan's on-chain dynamic routing for free. No API key, JSON responses, instant quotes. [Get started →](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/overview) * * * [](https://titan-exchange.gitbook.io/titan/developer-doc#why-titan) Why Titan ---------------------------------------------------------------------------------- The same infrastructure that powers titan.ag is available to you as production-grade APIs. **Best Execution** 70–75% win rate vs all other routing sources. **No Platform Fees** Zero subscription or trading fees. Save ~20 bps. **Low Slippage** Active simulations and algorithmic route selection. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc#apis) APIs ------------------------------------------------------------------------ Two interfaces, same Argos routing engine. Pick the one that fits your architecture. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) **Titan Direct** WebSocket streaming quotes in real time. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap) **Titan Gateway** REST endpoints, same Argos routing. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway) **Direct vs Gateway** Choose the right interface for your use case. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc#get-started) Get Started -------------------------------------------------------------------------------------- Everything you need to make your first request. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart) **Quickstart** First swap quote in under 5 minutes. [](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/authentication) **Authentication** Pass your token via header or query param. [](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/api-access) **Get API Access** Get a token from Titan, Triton, or QuickNode. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc#guides) Guides ---------------------------------------------------------------------------- Step-by-step walkthroughs for common integration tasks. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) **Stream & Execute** Stream quotes, build tx, send on-chain. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) **Configure Routing** Filter venues, providers, and route types. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection) **Fee Collection** Collect platform fees with feeAccount. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc#resources) Resources ---------------------------------------------------------------------------------- SDKs, AI tools, and community channels. [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk) **SDK Reference** TypeScript and Rust SDKs. [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration) **AI / LLM Integration** Claude Code skill and llms.txt. [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/community-and-support) **Community & Support** Discord, GitHub, and support. Last updated 2 months ago --- # Introduction | Developer Docs | Titan Titan is a meta-aggregator for Solana. It collects quotes from multiple providers — DEX aggregators and RFQ providers — routes through Argos, and returns the best quotes. [](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/introduction#what-titan-offers) What Titan offers ------------------------------------------------------------------------------------------------------------------------------- **Titan Direct** is a WebSocket API that streams live swap quotes, updated continuously as on-chain state changes — **the only WebSocket-native trading API on Solana, built for traders who can't afford stale quotes.** Use it when you need real-time pricing — trading bots, live swap UIs, or any integration where quotes should refresh automatically. **Titan Gateway** is a REST API that returns quotes per request — no persistent connection required. **The fastest path from zero to production-grade swap execution on Solana.** Use it when a single quote per action is enough — one-click swap buttons, price displays, or backend services that request quotes on demand. Both paths deliver the same execution quality through Argos. The difference is interface and workflow — not routing quality. **Limit Orders** lets you place resting on-chain orders that fill fully or partially as liquidity becomes available. The program supports five time-in-force modes and charges fees to takers in the output token. [](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/introduction#routing-with-argos) Routing with Argos --------------------------------------------------------------------------------------------------------------------------------- Every swap request runs through **Argos**, Titan's proprietary routing algorithm. Where competing aggregators rely on shortest-path methods and chunk liquidity into percentage buckets, Argos resolves price impacts with machine-level precision — without fragmenting pools or excluding liquidity sources. The result is a true optimal on-chain price, which is why Titan beats competing aggregators 80% of the time. [](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/introduction#where-to-start) Where to start? -------------------------------------------------------------------------------------------------------------------------- Need a token first? Go to [Get API Access](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/api-access) . Ready to build? The [Quickstart](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart) gets you your first swap quote in minutes using both Titan Direct and Titan Gateway. [PreviousHome](https://titan-exchange.gitbook.io/titan/developer-doc) [NextAuthentication](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/authentication) Last updated 2 months ago --- # Quickstart | Developer Docs | Titan You'll need an API token and endpoint URL before starting. See [Get API Access](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/api-access) if you don't have one yet. This is a minimal example to get your first quote from the Titan API. For a complete integration with transaction building, signing, and error handling, see [Stream & Execute a Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) . Titan has two integration paths. **Titan Direct** uses WebSocket and streams live quotes continuously. **Titan Gateway** uses REST and returns a single set of quotes per request. Both deliver the same quote quality. Swap quote requests require a `userPublicKey` — a valid Solana wallet address. The server uses it to build transaction instructions scoped to that wallet. The [`@titanexchange/sdk-ts`](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk) SDK supports Titan Direct (WebSocket) only. Titan Direct Titan Gateway 1 **Install the SDK** Copy npm install @titanexchange/sdk-ts bs58 2 **Set your credentials** Copy export TITAN_ENDPOINT="wss://YOUR_ENDPOINT/api/v1/ws" export TITAN_API_KEY="YOUR_API_TOKEN" 3 **Connect and get a quote** Copy import { V1Client } from '@titanexchange/sdk-ts'; import bs58 from 'bs58'; const client = await V1Client.connect( `${process.env.TITAN_ENDPOINT}?auth=${process.env.TITAN_API_KEY}` ); const { stream } = await client.newSwapQuoteStream({ swap: { inputMint: bs58.decode('So11111111111111111111111111111111111111112'), outputMint: bs58.decode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'), amount: BigInt(1_000_000_000), // 1 SOL in lamports slippageBps: 50, }, transaction: { userPublicKey: bs58.decode('YOUR_WALLET_PUBLIC_KEY'), }, }); for await (const update of stream) { const quotes = update.quotes; if (!Object.keys(quotes).length) continue; for (const [provider, route] of Object.entries(quotes as Record)) { console.log(`${provider}: ${route.outAmount} out`); } break; // First update received — stop here } await client.close(); 1 **Install dependencies** Copy npm install @msgpack/msgpack 2 **Set your credentials** Copy export TITAN_ENDPOINT="https://YOUR_ENDPOINT" export TITAN_API_KEY="YOUR_API_TOKEN" 3 **Request a quote** Copy import { decode } from '@msgpack/msgpack'; const params = new URLSearchParams({ inputMint: 'So11111111111111111111111111111111111111112', outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', amount: '1000000000', // 1 SOL in lamports userPublicKey: 'YOUR_WALLET_PUBLIC_KEY', slippageBps: '50', }); const res = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/quote/swap?${params}`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', }, } ); if (!res.ok) throw new Error(`${res.status}: ${res.statusText}`); const data = decode(new Uint8Array(await res.arrayBuffer())) as any; for (const [provider, route] of Object.entries(data.quotes as Record)) { console.log(`${provider}: ${route.outAmount} out`); } [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart#what-a-quote-looks-like) What a quote looks like ---------------------------------------------------------------------------------------------------------------------------------- The response contains a `quotes` map keyed by provider ID — `"Titan"`, `"Metis"`, `"Okx"`, etc. Each entry is a `SwapRoute` with everything you need to build and send a transaction: * `**inAmount**` / `**outAmount**` — the input and output amounts for this route. * `**slippageBps**` — the slippage tolerance applied to this quote. * `**computeUnitsSafe**` — recommended compute budget that accounts for on-chain variance. * `**instructions**` — the swap instructions to include in your transaction. * `**addressLookupTables**` — ALT addresses needed to compile a V0 transaction. * **Quote expiry** — if a route expires, `expiresAtMs` contains the expiry as a millisecond UNIX timestamp and `expiresAfterSlot` contains the last valid slot. Check these before executing if present. Not every provider appears in every response. Iterate with `Object.entries(quotes)` and pick the route with the best `outAmount`. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart#next-steps) Next steps -------------------------------------------------------------------------------------------------------- * [Stream & Execute a Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) — full guide with transaction building, signing, and error handling * [Configure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) — filter venues and providers, set account limits * [Authentication](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/authentication) — JWT claims reference [PreviousGet API Access](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/api-access) [NextGuides](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides) Last updated 2 months ago --- # Authentication | Developer Docs | Titan The Titan API uses **JSON Web Tokens (JWTs)** for authentication. Every connection requires a valid token issued by Titan or a Titan distributor. [](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/authentication#submitting-your-token) Submitting your token ----------------------------------------------------------------------------------------------------------------------------------------- You can submit your JWT in two ways: As a **Bearer token** in the `Authorization` header — the recommended approach for server-side integrations: Copy Authorization: Bearer As a query parameter — for browser clients or environments where setting custom headers isn't possible (e.g. WebSocket clients that only support [`Sec-WebSocket-Protocol`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Sec-WebSocket-Protocol) ): Copy wss://YOUR_ENDPOINT/api/v1/ws?auth= https://YOUR_ENDPOINT/api/v1/quote/swap?auth= **Do not expose your JWT in client-side code.** Set up a middleware proxy that injects the token server-side. See the [middleware example](https://github.com/Titan-Pathfinder/titan-sdk-ts/blob/main/examples/middleware.ts) for a basic reference — you can build your own middleware to fit your stack and authentication flow. If your connection drops unexpectedly, check your token's expiration first — an **expired token is the most common cause** of authentication failures. [](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/authentication#getting-a-token) Getting a token ----------------------------------------------------------------------------------------------------------------------------- See [Get API Access](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/api-access) . [PreviousIntroduction](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/introduction) [NextGet API Access](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/api-access) Last updated 2 months ago --- # Get API Access | Developer Docs | Titan Titan API access is available directly from the team or through infrastructure providers. [](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/api-access#direct-access) Direct access --------------------------------------------------------------------------------------------------------------------- Email [info@titandex.io](mailto:info@titandex.io) or reach out via Telegram or Discord. The team will provision a JWT and endpoint URL for your integration. [](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/api-access#through-a-distributor) Through a distributor ------------------------------------------------------------------------------------------------------------------------------------- Titan is available through the following infrastructure providers: * [**Triton**](https://docs.triton.one/trading-apis/titan-swap-api) — Titan Swap API documentation on Triton * [**QuickNode**](https://marketplace.quicknode.com/add-on/titan-swap) — Titan Swap add-on on the QuickNode Marketplace If you're already on either platform, you can get access without contacting the Titan team directly. Once you have a token and endpoint, go to the [Quickstart](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart) to make your first request. [PreviousAuthentication](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/authentication) [NextQuickstart](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart) Last updated 2 months ago --- # Guides | Developer Docs | Titan **Practical walkthroughs for the most common Swap API workflows.** Each guide builds on the [Quickstart](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart) and assumes you have a working connection. [PreviousQuickstart](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart) [NextSwap V2 vs Swap V3](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/swap-v2-vs-v3) Last updated 2 months ago --- # API Reference | Developer Docs | Titan **Full reference for every RPC method, endpoint, type, and error code across both Titan interfaces.** Choose [Titan Direct](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway) for real-time WebSocket streams or [Titan Gateway](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway) for simple REST calls — both are backed by the same Argos routing engine. [PreviousError Handling & Reconnect](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling) [NextTitan Direct vs Titan Gateway](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway) Last updated 2 months ago --- # Overview | Developer Docs | Titan > **Beta** — The DART API is currently in beta. The DART API provides swap quotes for selected token pairs on Solana via Titan's **DART (Dynamically Allocated Real Time)** engine. This is a dedicated DART-only endpoint — it exclusively uses the Titan DART provider for routing. DART dynamically re-optimizes trades at the exact moment of execution, not just at quote time — **guaranteeing best execution when it matters most.** **Base URL:** `https://api.titan.exchange/dart` **Free to use** · No API key required · JSON responses · Up to 1 bps fee · 1 req/sec rate limit * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/overview#supported-pairs) Supported pairs --------------------------------------------------------------------------------------------------------------------- Use `GET /markets` to discover pairs programmatically, or reference the list below. * SOL/USDC * SOL/USDT * USDT/USDC * cbBTC/USDC * wETH/USDC * TRUMP/USDC * ZEC/USDC * USD1/USDC * HYPE/USDC * PUMP/USDC * PENGU/USDC * FARTCOIN/USDC * syrupUSD/USDC * PYUSD/USDC * USDG/USDC * CASH/USDC The `/swap` endpoint works on supported token pairs listed above. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/overview#rate-limits-and-fees) Rate limits & fees ----------------------------------------------------------------------------------------------------------------------------- * **1 request per second** per IP address. HTTP 429 if exceeded. * **Up to 1 bps fee** per swap, handled by the on-chain program. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/overview#related-pages) Related pages ----------------------------------------------------------------------------------------------------------------- * [Get API Access](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/get-api-access) — Free vs partner access, API keys * [How to Use](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/how-to-use) — Endpoints, request/response format, and transaction building [PreviousError Codes](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes) [NextGet API Access](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/get-api-access) Last updated 1 month ago --- # Get API Access | Developer Docs | Titan [](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/get-api-access#free-public-endpoint) Free public endpoint ------------------------------------------------------------------------------------------------------------------------------------- A public DART endpoint is available for testing and low-volume use. No API key required. **Base URL:** `https://api.titan.exchange/dart` * **1 request per second** per IP address * REST only, JSON responses * DART provider only * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/get-api-access#partner-access) Partner access ------------------------------------------------------------------------------------------------------------------------- For higher rate limits, pass your API key via header: Copy curl -X POST https://api.titan.exchange/dart/swap \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ ... }' Or using `X-API-Key`: Copy curl -X POST https://api.titan.exchange/dart/swap \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ ... }' To request a partner API key, fill out the application form: [**Apply for DART API Access**](https://tally.so/r/1AvYeL) * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/get-api-access#related-pages) Related pages ----------------------------------------------------------------------------------------------------------------------- * [Overview](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/overview) — What DART is, supported pairs, and fees * [How to Use](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/how-to-use) — Endpoints, request/response format, and transaction building [PreviousOverview](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/overview) [NextHow to Use](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/how-to-use) Last updated 2 months ago --- # How to Use | Developer Docs | Titan The DART API is a standard **JSON REST API** — no MessagePack, no WebSocket. Just HTTP requests. Free to use without an API key, or pass a key for higher rate limits (see [Get API Access](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/get-api-access) ). **Base URL:** `https://api.titan.exchange/dart` * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/how-to-use#get-health) `GET /health` ---------------------------------------------------------------------------------------------------------------- Health check. Copy curl https://api.titan.exchange/dart/health Copy { "status": "ok" } * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/how-to-use#get-markets) `GET /markets` ------------------------------------------------------------------------------------------------------------------ Returns the list of supported trading pairs. Copy curl https://api.titan.exchange/dart/markets Copy { "markets": [\ {\ "name": "SOL/USDC",\ "tokenA": "So11111111111111111111111111111111111111112",\ "tokenB": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"\ }\ ] } * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/how-to-use#post-swap) `POST /swap` -------------------------------------------------------------------------------------------------------------- Get a swap quote with transaction-ready instructions. Compute budget instructions are pre-configured for optimal execution. **Request body (JSON):** * `**inputMint**` (string, required) — Input token mint address (base58). * `**outputMint**` (string, required) — Output token mint address (base58). * `**amount**` (string, required) — Raw amount in smallest unit (e.g. lamports). * `**userPublicKey**` (string, required) — Wallet public key (base58). Must be on-curve. * `**slippageBps**` (number, optional) — Slippage tolerance in basis points. Default: `50`. * `**computeUnitPrice**` (number, optional) — Compute unit price in microLamports. Default: `10000`. * `**includeDexes**` (string\[\], optional) — Only use these DEX venues. * `**excludeDexes**` (string\[\], optional) — Exclude these DEX venues. **Example:** Copy curl -X POST https://api.titan.exchange/dart/swap \ -H "Content-Type: application/json" \ -d '{ "inputMint": "So11111111111111111111111111111111111111112", "outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "amount": "1000000000", "userPublicKey": "YourWalletPublicKeyHere" }' **Response:** Copy { "outputAmount": "84550000", "inputAmount": "1000000000", "provider": "Titan-DART", "slippageBps": 50, "instructions": [\ {\ "programId": "ComputeBudget111111111111111111111111111111",\ "accounts": [],\ "data": "AQAABAA="\ },\ {\ "programId": "ComputeBudget111111111111111111111111111111",\ "accounts": [\ {\ "pubkey": "jitodontfronttitandart111111111111111111111",\ "isSigner": false,\ "isWritable": false\ }\ ],\ "data": "AsBcFQA="\ },\ {\ "programId": "ComputeBudget111111111111111111111111111111",\ "accounts": [],\ "data": "AxAnAAAAAAAA"\ },\ {\ "programId": "T1TANpTeScyeqVzzgNViGDNrkQ6qHz9KrSBS4aNXvGT",\ "accounts": [\ {\ "pubkey": "YourWalletPublicKeyHere",\ "isSigner": true,\ "isWritable": true\ }\ ],\ "data": "..."\ }\ ], "addressLookupTables": [\ "RyXhBMnPkYJyWEkBmYAnW7A8LCKfrEgAABB2xVZrwy3"\ ] } **Response fields:** * `**outputAmount**` — Expected output in smallest unit. * `**inputAmount**` — Input amount in smallest unit. * `**provider**` — Always `Titan-DART`. * `**slippageBps**` — Slippage tolerance applied. * `**instructions**` — Swap instructions with compute budget pre-configured. `programId` and `pubkey` are base58, `data` is base64. * `**addressLookupTables**` — Base58 address lookup table keys for V0 transaction compilation. **Compute budget (prepended automatically):** * `**requestHeapFrame**` — 256 KB * `**setComputeUnitLimit**` — 1,400,000 CUs * `**setComputeUnitPrice**` — configurable (default 10,000 microLamports) **Errors:** * `**400**` — Missing required fields or invalid JSON. * `**404**` — No routes found for the given pair. * `**429**` — Rate limit exceeded. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/how-to-use#building-a-transaction) Building a transaction ------------------------------------------------------------------------------------------------------------------------------------- The response includes all instructions ready to go — deserialize, build a V0 transaction, sign, and send: Copy import { Connection, PublicKey, TransactionInstruction, TransactionMessage, VersionedTransaction, } from "@solana/web3.js"; // 1. Deserialize instructions from the response const instructions = response.instructions.map( (ix) => new TransactionInstruction({ programId: new PublicKey(ix.programId), keys: ix.accounts.map((acc) => ({ pubkey: new PublicKey(acc.pubkey), isSigner: acc.isSigner, isWritable: acc.isWritable, })), data: Buffer.from(ix.data, "base64"), }) ); // 2. Fetch address lookup tables const connection = new Connection("https://api.mainnet-beta.solana.com"); const altAccounts = await Promise.all( response.addressLookupTables.map(async (key) => { const alt = await connection.getAddressLookupTable(new PublicKey(key)); return alt.value; }) ); // 3. Build V0 transaction const { blockhash } = await connection.getLatestBlockhash(); const message = new TransactionMessage({ payerKey: walletPublicKey, recentBlockhash: blockhash, instructions, }).compileToV0Message(altAccounts.filter(Boolean)); const transaction = new VersionedTransaction(message); // 4. Sign and send transaction.sign([wallet]); const signature = await connection.sendTransaction(transaction); * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/how-to-use#related-pages) Related pages ------------------------------------------------------------------------------------------------------------------- * [Overview](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/overview) — What DART is, supported pairs, and fees * [Get API Access](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/get-api-access) — Rate limits and higher-rate access [PreviousGet API Access](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/get-api-access) [NextOverview](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview) Last updated 2 months ago --- # Overview | Developer Docs | Titan **Titan's Limit Orders are designed to thrive in a competitive environment where searchers play a central role.** By participating as a searcher, you gain access to a marketplace of on-chain limit orders. Limit orders are resting on-chain and can be partially or completely filled. **Fees are charged to takers** and are charged as `output_mint` tokens. **Program address:** `TitanLozLMhczcwrioEguG2aAmiATAPXdYpBg3DbeKK` * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview#order-structure) Order structure ------------------------------------------------------------------------------------------------------------------------------ Each limit order is a PDA derived from the maker's public key, input mint, output mint, and an order ID. Copy use pinocchio::pubkey::{create_program_address, Pubkey}; use bytemuck::{Pod, Zeroable}; /// Limit order structure #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] pub struct LimitOrder { // The public key of the order, pub maker: Pubkey, // Input mint of the limit order pub input_mint: Pubkey, // Output mint of the limit order pub output_mint: Pubkey, // Slot which the order was created pub creation_slot: u64, // The slot at which the order expires pub expiration_slot: u64, // The amount of input tokens to be exchanged pub amount: u64, // The amount of input tokens that have been filled pub amount_filled: u64, // The amount of output tokens that have been exchanged. pub out_amount_filled: u64, // The amount of output tokens that the maker has withdrawn. pub out_amount_withdrawn: u64, // The amount of fees paid in the smallest unit of from_token mint. pub fees_paid: u64, // Price base in the order, in the smallest unit of output token pub price_base: u64, // Price exponent, price is calculated as price_base * 10^(-price_exponent) pub price_exponent: u8, // The status of the order pub status: u8, // Bump seed for the limit order PDA pub bump: u8, // Unique identifier for the order, used to differentiate orders for same // (owner, input_mint, output_mint) tuple pub id: u8, // Bump seed for the input mint vault PDA pub input_mint_vault_bump: u8, // Bump seed for the output mint vault PDA pub output_mint_vault_bump: u8, // Time in order pub time_in_force: u8, // Fees ticks rate for the order from takers. pub fee_ticks: u8, } **PDA seeds:** `["order", maker, input_mint, output_mint, id, bump]` **Account size:** 168 bytes. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview#pda-derivation) PDA derivation Copy impl LimitOrder { pub const SEEDS: &'static [u8] = b"order"; pub const LEN: usize = 168; /// Get the pda address for the limit order, given the maker, input mint, /// output mint, id and bump. pub fn get_pda_address( maker: &Pubkey, input_mint: &Pubkey, output_mint: &Pubkey, id: u8, bump: u8, ) -> Result { let b0 = &[id]; let b1 = &[bump]; let seeds_with_bump = [\ LimitOrder::SEEDS,\ maker.as_ref(),\ input_mint.as_ref(),\ output_mint.as_ref(),\ b0,\ b1,\ ] .to_vec(); create_program_address(&seeds_with_bump, &crate::ID) } } * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview#price-calculation) Price calculation ---------------------------------------------------------------------------------------------------------------------------------- Price is stored as `price_base * 10^(-price_exponent)`. For example, a 100 USDC → 1 SOL order uses `price_base = 1` and `price_exponent = 2`, giving a price of `0.01` output tokens per input token. Copy impl LimitOrder { /// Calculate the costs and fees for a given amount and fee ticks. pub fn calculate_costs_and_fee( &self, amount: u64, fee_ticks: u8, ) -> Result<(u64, u64), ProgramError> { let amount_u128 = amount as u128; let price_base = self.price_base as u128; let price_exponent = 10u128.pow(self.price_exponent as u32); let fee_units_u128 = (fee_ticks as u16).saturating_mul(FEE_TICK_UNITS as u16) as u128; // Calculate the transfer amount and fee amount. // Should never overflow, since its u64 * u64 // Use method to perform ceiling math division: (a + b - 1) / b let cost_u128 = amount_u128 .saturating_mul(price_base) .checked_add(price_exponent.saturating_sub(1)) .ok_or(ProgramError::ArithmeticOverflow)? .saturating_div(price_exponent); let cost: u64 = cost_u128 .try_into() .map_err(|_| ProgramError::ArithmeticOverflow)?; let fees: u64 = cost_u128 .saturating_mul(fee_units_u128) .saturating_div(FEE_TICK_DIVISOR) .try_into() .map_err(|_| ProgramError::ArithmeticOverflow)?; Ok((cost, fees.max(1))) } /// Amount left to be filled in the order. pub fn get_remaining_amount(&self) -> u64 { self.amount.saturating_sub(self.amount_filled) } } * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview#fees) Fees -------------------------------------------------------------------------------------------------------- Fees are charged to takers in the **output token**. The fee rate is stored as `fee_ticks` on the order. Copy fee_units = fee_ticks × 25 fee = cost × fee_units / 1,000,000 **The minimum fee is always 1 unit of the output token.** Copy /// Fee tick units pub const FEE_TICK_UNITS: u8 = 25; /// 1e6 units = 0.0001, used to convert fee tick rate to fee basis points pub const FEE_TICK_DIVISOR: u128 = 1_000_000; **Fee receiver address:** `Bq5ZzfiU3vTiJPrBJFcr98BnUy9Wc1dg9ASeycB2tX1C` * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview#time-in-force) Time-in-force -------------------------------------------------------------------------------------------------------------------------- Each order carries a time-in-force policy that controls fill behavior. Copy /// Time in Force (TIF) for limit orders. Provides different behaviors for /// how long an order remains active and how it can be filled. #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum TimeInForce { /// Order is good until cancelled. Partial takes are allowed. GoodTillCancelled = 0, /// After taking any amount, order is closed. TakeCancelsOrder = 1, /// Takes must completely fill the order. AllOrNothing = 2, /// Same as TakeCancelsOrder but it must be filled at the same time of creation. ImmediateOrCancel = 3, /// Same as AllOrNothing but it must be filled at the same time of creation. FillOrKill = 4, } * `**GoodTillCancelled**` **(0)** — Remains open until fully filled or cancelled. **Partial fills allowed.** * `**TakeCancelsOrder**` **(1)** — Closes after any take, regardless of fill amount. * `**AllOrNothing**` **(2)** — Takes must completely fill the remaining amount. * `**ImmediateOrCancel**` **(3)** — Same as `TakeCancelsOrder`, but **must be filled in the same slot as creation.** * `**FillOrKill**` **(4)** — Same as `AllOrNothing`, but **must be filled in the same slot as creation.** * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview#order-status) Order status ------------------------------------------------------------------------------------------------------------------------ Copy /// Order status for limit orders. Indicates the current state of the order /// and how it can be interacted with. #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum OrderStatus { /// Order is open, can be partially filled, filled, cancelled Open = 0, /// Order is partially filled, can be filled or cancelled PartiallyFilled = 1, /// Order is filled, terminates, used for event logging Filled = 2, /// Order is cancelled, terminates, used for event logging Cancelled = 3, } * `**Open**` **(0)** — Can be partially filled, fully filled, or cancelled. * `**PartiallyFilled**` **(1)** — Some amount filled. Can still be filled or cancelled. * `**Filled**` **(2)** — Fully filled. **Terminal state.** * `**Cancelled**` **(3)** — Cancelled by maker. **Terminal state.** * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview#related-pages) Related pages -------------------------------------------------------------------------------------------------------------------------- * [Placing Taker Orders](https://github.com/Titan-Pathfinder/titan-gitbook-doc/blob/main/limit-orders/take-order.md) — TakeOrder instruction, accounts, WSOL handling, and full execution code * [Limit Order Events](https://github.com/Titan-Pathfinder/titan-gitbook-doc/blob/main/limit-orders/events.md) — Event structure and parsing from program logs * [Error Codes](https://github.com/Titan-Pathfinder/titan-gitbook-doc/blob/main/limit-orders/error-codes.md) — Program error codes [PreviousHow to Use](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/how-to-use) [NextPlacing Taker Orders](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order) Last updated 2 months ago --- # Placing Taker Orders | Developer Docs | Titan **Searchers fill orders by invoking the** `**TakeOrder**` **instruction (discriminator** `**2**`**).** Orders can be partially or fully fulfilled — in both cases the taker receives their tokens immediately. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order#fill-behavior) Fill behavior ---------------------------------------------------------------------------------------------------------------------------- ### [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order#full-fill) Full fill When an order is fully filled, the program automatically: 1. **Creates the maker's ATA** for the output tokens (if needed). 2. **Refunds the original rent** used in the Limit Order back to the maker. 3. **Reimburses any lamports** back to the taker if they had to pay for any ATA creation. 4. **For WSOL output** — returns funds back to the maker as SOL instead of WSOL. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order#partial-fill) Partial fill For partial fills, the taker receives their tokens immediately. The remaining input tokens stay in the program vault. **The maker can withdraw filled output tokens at any time.** ### [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order#example-100-usdc-1-sol-with-5-bps-fee) Example: 100 USDC → 1 SOL with 5 BPS fee 1. User creates a limit order paying the rent and depositing 100 USDC into the vault. Price is set to `0.01`. 2. Adjusting for fees — when it is favourable to trade 1.0005 SOL → 100 USDC, the taker comes in and takes the full order. 3. Under the hood, taker deposits 1.0005 SOL into the vault. 100 USDC is moved from the vault to the taker's ATA, 0.0005 WSOL fee is moved to the fee receiver's wallet. 4. Contract determines the limit order is fulfilled. Since the output is SOL, the special WSOL edge case is handled: * The contract expects a **taker-owned WSOL (non-ATA) token account** is passed into the call. * The WSOL vault sends 1 SOL to this token account and **closes it out to the maker**, crediting their wallet balance with the 1 SOL. * The limit order is closed and rent is sent to the taker. * The taker sends the rent funds to the maker subtracting any rent they paid for the WSOL token account. **For partial fills**, the above example holds — just skip step 4. **For non-WSOL trades**, only step 4 differs: the program initializes the maker's ATA with the taker as rent payer. When the limit order closes, the taker is rebated accordingly. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order#wsol-handling) WSOL handling ---------------------------------------------------------------------------------------------------------------------------- When the output mint is WSOL and the order will close: * The taker **must pass a seeded (non-ATA) WSOL token account** as the maker's output account. * The program sends SOL to this account and **closes it to the maker**, crediting their wallet balance directly. * The taker wraps SOL into their ATA before the take, and closes the ATA after. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order#takeorder-accounts) TakeOrder accounts -------------------------------------------------------------------------------------------------------------------------------------- * `**0**` **—** `**taker**` — Taker wallet. **Writable, signer.** * `**1**` **—** `**maker**` — Maker wallet (receives output tokens on full fill). **Writable.** * `**2**` **—** `**inputMint**` — Input token mint. Read-only. * `**3**` **—** `**outputMint**` — Output token mint. Read-only. * `**4**` **—** `**limitOrder**` — Limit order PDA. **Writable.** * `**5**` **—** `**takerInputMintTokenAccount**` — Taker's input token account (receives input tokens). **Writable.** * `**6**` **—** `**takerOutputMintTokenAccount**` — Taker's output token account (sends output tokens + fees). **Writable.** * `**7**` **—** `**makerOutputMintTokenAccount**` — Maker's output token account (or seeded account for WSOL). **Writable.** * `**8**` **—** `**makerInputMintTokenAccount**` — Maker's input token account (for remaining balance on close). **Writable.** * `**9**` **—** `**feeReceiverTokenAccount**` — Fee receiver's output token account. **Writable.** * `**10**` **—** `**vaultManager**` — Vault manager PDA (`["vault_manager"]`). Read-only. * `**11**` **—** `**inputMintVault**` — Vault's input token account. **Writable.** * `**12**` **—** `**outputMintVault**` — Vault's output token account. **Writable.** * `**13**` **—** `**systemProgram**` — System program. Read-only. * `**14**` **—** `**inputMintProgram**` — Token program for input mint (SPL or SPL-2022). Read-only. * `**15**` **—** `**outputMintProgram**` — Token program for output mint (SPL or SPL-2022). Read-only. * `**16**` **—** `**associatedTokenProgram**` — Associated Token Program. Read-only. * `**17**` **—** `**instructionsSysvar**` — Instructions sysvar. Read-only. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order#instruction-data) Instruction data ---------------------------------------------------------------------------------------------------------------------------------- * **Byte 0** — `discriminator` (`u8`) — Always `2` (TakeOrder). * **Bytes 1–8** — `amount` (`u64`, little-endian) — Input token amount to take. * **Bytes 9–16** — `max_cost_amount` (`u64`, little-endian) — Maximum output tokens the taker will pay. **Use** `**u64::MAX**` **for no limit.** * **Byte 17** — `output_mint_token_account_bump` (`u8`) — PDA bump for maker's output token account. * **Byte 18** — `input_mint_token_account_bump` (`u8`) — PDA bump for maker's input token account. * **Byte 19** — `fee_receiver_output_mint_bump` (`u8`) — PDA bump for fee receiver's output token account. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order#full-execution-code) Full execution code ---------------------------------------------------------------------------------------------------------------------------------------- The following code shows how to create a complete set of instructions to execute a `TakeOrder`, including setup (ATA creation, WSOL wrapping) and cleanup (WSOL unwrapping). Copy /// Fees to be paid to this address pub const FEE_RECEIVER_ADDRESS: Pubkey = pubkey!("Bq5ZzfiU3vTiJPrBJFcr98BnUy9Wc1dg9ASeycB2tX1C"); /// Derives the vault manager address and bump seed. pub fn get_vault_manager_address_and_bump_seed() -> (Pubkey, u8) { Pubkey::find_program_address(&[b"vault_manager"], &TITAN_LIMIT_ORDER_PROGRAM_ID) } /// Derives the associated token address and bump seed for a given wallet and token mint. pub fn get_associated_token_address_and_bump_seed( wallet_address: &Pubkey, token_mint_address: &Pubkey, token_program: &Pubkey, ) -> (Pubkey, u8) { Pubkey::find_program_address( &[\ &wallet_address.to_bytes(),\ &token_program.to_bytes(),\ &token_mint_address.to_bytes(),\ ], &ASSOCIATED_TOKEN_PROGRAM_ID, ) } /// Creates an instruction bundle to create a token account with a seed. pub fn create_token_account_with_seed_instructions( payer: &Pubkey, authority: &Pubkey, mint: &Pubkey, seed: &str, owner: &Pubkey, ) -> Result<(Pubkey, Vec), TitanSDKError> { let token_account = Pubkey::create_with_seed(payer, seed, owner) .map_err(|_| TitanSDKError::FailedToCreateInstruction)?; // Get minimum balance for rent exemption let token_account_space = spl_token::state::Account::LEN; let lamports = 2039280u64; // Create account with seed instruction let create_account_ix = create_account_with_seed( payer, &token_account, payer, seed, lamports, token_account_space as u64, owner, ); // Initialize token account instruction let init_account_ix = initialize_account(&spl_token::id(), &token_account, mint, authority) .map_err(|_| TitanSDKError::FailedToCreateInstruction)?; Ok((token_account, vec![create_account_ix, init_account_ix])) } /// Discriminator for TakeOrder instruction. mod TakeOrder { pub const DISCRIMINATOR: u8 = 2; } /// Represents a bundle of instructions, including setup instructions and the main instruction. pub struct InstructionBundle { /// A vector of setup instructions that need to be executed before the main instruction. pub setup: Vec, /// The main instruction to be executed. pub instruction: Instruction, /// Cleanup instructions to be executed after the main instruction. pub cleanup: Vec, } pub fn create_take_order_instruction( // Taker of the order, signer. taker: Pubkey, // Input mint token account taker_input_mint_token_account: Pubkey, // Output mint token account w/ taker authority taker_output_mint_token_account: Pubkey, // Limit order state. limit_order: &LimitOrder, // Input mint amount to recieve amount: u64, // Max cost taken from output mint token account // If this is breached the ixn will fail. max_cost_limit: Option, // Input token program [spl / spl-2022] input_mint_program: Pubkey, // Output token program [spl / spl-2022] output_mint_program: Pubkey, ) -> Result { let time_in_force = TimeInForce::try_from(limit_order.time_in_force)?; let max_cost_limit = max_cost_limit.unwrap_or(u64::MAX); let remaining_balance_left = amount != limit_order.get_remaining_amount(); let order_will_close = !remaining_balance_left || time_in_force == TimeInForce::ImmediateOrCancel || time_in_force == TimeInForce::TakeCancelsOrder; let fee_ticks = limit_order.fee_ticks; let (cost, fee) = limit_order .calculate_costs_and_fee(amount, fee_ticks)?; let output_is_wsol = limit_order.output_mint.eq(&WRAPPED_SOL); let input_is_wsol = limit_order.input_mint.eq(&WRAPPED_SOL); let limit_order_address = derive_limit_order_address(limit_order); let (vault_manager_address, _) = get_vault_manager_address_and_bump_seed(); let maker = Pubkey::new_from_array(limit_order.maker); let input_mint = Pubkey::new_from_array(limit_order.input_mint); let output_mint = Pubkey::new_from_array(limit_order.output_mint); let mut setup = vec![create_associated_token_account_idempotent(\ &taker,\ &Pubkey::new_from_array(FEE_RECEIVER_ADDRESS),\ &output_mint,\ &output_mint_program,\ )]; let mut cleanup = vec![]; if output_is_wsol { let wsol_ata = get_associated_token_address_with_program_id( &taker, &output_mint, &output_mint_program, ); setup.extend_from_slice(&[\ create_associated_token_account_idempotent(\ &taker,\ &taker,\ &output_mint,\ &output_mint_program,\ ),\ transfer(&taker, &wsol_ata, cost.saturating_add(fee)),\ sync_native(&output_mint_program, &wsol_ata)?,\ ]); cleanup.push( close_account(&output_mint_program, &wsol_ata, &taker, &taker, &[])?, ) } let (output_mint_token_account_address, output_mint_token_account_bump) = if order_will_close && output_is_wsol { // Handle the special case here let (pk, instructions) = create_token_account_with_seed_instructions( &taker, &taker, &output_mint, "token_seed", &output_mint_program, )?; setup.extend(instructions); (pk, 0) // Bump is not used in this case } else { // otherwise always assume its the makers output ata. get_associated_token_address_and_bump_seed(&maker, &output_mint, &output_mint_program) }; let (input_mint_token_account_address, input_mint_token_account_bump) = if order_will_close && remaining_balance_left && input_is_wsol { // Handle the special case here let (pk, instructions) = create_token_account_with_seed_instructions( &taker, &taker, &input_mint, "token_seed", &input_mint_program, )?; setup.extend(instructions); (pk, 0) // Bump is not used in this case } else { // otherwise always assume its the makers output ata. get_associated_token_address_and_bump_seed(&maker, &input_mint, &input_mint_program) }; let (input_mint_vault_address, _) = get_associated_token_address_and_bump_seed( &vault_manager_address, &input_mint, &input_mint_program, ); let (output_mint_vault_address, _) = get_associated_token_address_and_bump_seed( &vault_manager_address, &output_mint, &output_mint_program, ); // Create the vault manager output token account if it doesn't exist setup.push(create_associated_token_account_idempotent( &taker, &vault_manager_address, &output_mint, &output_mint_program, )); let fee_receiver = Pubkey::new_from_array(FEE_RECEIVER_ADDRESS); let (fee_receiver_output_mint_token_account, fee_reciever_output_mint_bump) = get_associated_token_address_and_bump_seed( &fee_receiver, &output_mint, &output_mint_program, ); let mut data = vec![*instructions::TakeOrder::DISCRIMINATOR]; data.extend_from_slice(&amount.to_le_bytes()); data.extend_from_slice(&max_cost_limit.to_le_bytes()); data.extend_from_slice(&[\ output_mint_token_account_bump,\ input_mint_token_account_bump,\ fee_reciever_output_mint_bump,\ ]); let accounts = vec![\ AccountMeta::new(taker, true),\ AccountMeta::new(maker, false),\ AccountMeta::new_readonly(input_mint, false),\ AccountMeta::new_readonly(output_mint, false),\ AccountMeta::new(limit_order_address, false),\ AccountMeta::new(taker_input_mint_token_account, false),\ AccountMeta::new(taker_output_mint_token_account, false),\ AccountMeta::new(output_mint_token_account_address, false),\ AccountMeta::new(input_mint_token_account_address, false),\ AccountMeta::new(fee_receiver_output_mint_token_account, false),\ AccountMeta::new_readonly(vault_manager_address, false),\ AccountMeta::new(input_mint_vault_address, false),\ AccountMeta::new(output_mint_vault_address, false),\ AccountMeta::new_readonly(solana_program::system_program::ID, false),\ AccountMeta::new_readonly(input_mint_program, false),\ AccountMeta::new_readonly(output_mint_program, false),\ AccountMeta::new_readonly(ASSOCIATED_TOKEN_PROGRAM_ID, false),\ AccountMeta::new_readonly(solana_program::sysvar::instructions::ID, false),\ ]; Ok(InstructionBundle { setup, instruction: Instruction { program_id: TITAN_LIMIT_ORDER_PROGRAM_ID, accounts, data, }, cleanup, }) } * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order#related-pages) Related pages ---------------------------------------------------------------------------------------------------------------------------- * [Limit Orders Overview](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview) — Order structure, price calculation, time-in-force, fees * [Limit Order Events](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/events) — Event structure and parsing from program logs * [Error Codes](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/error-codes) — Program error codes [PreviousOverview](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview) [NextLimit Order Events](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/events) Last updated 2 months ago --- # Limit Order Events | Developer Docs | Titan **You can listen to limit order events by parsing through the program logs for emitted data.** Events are Borsh-serialized and emitted in program logs for every order lifecycle operation. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/events#event-structure) Event structure ---------------------------------------------------------------------------------------------------------------------------- Copy #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize)] pub struct LimitOrderEvent { /// Event discriminator, used to identify the event type /// Create - 1, Take - 2, Cancel - 3, Modify - 4, Withdraw - 5, CloseExpired - 6 pub discriminator: u8, /// Instruction that triggered the event pub instruction: u8, /// The status of the order pub status: u8, /// Unique identifier for the order, used to differentiate orders for same /// (owner, input_mint, output_mint) tuple pub id: u8, /// The public key of the order pub maker: Pubkey, /// The mint of the input token pub input_mint: Pubkey, /// The mint of the output token pub output_mint: Pubkey, /// The slot at which the event was emitted pub slot: u64, /// The slot at which the order was created pub creation_slot: u64, /// The slot at which the order expires pub expiration_slot: u64, /// The amount of input tokens to be exchanged pub amount: u64, /// The amount of input tokens that have been filled pub amount_filled: u64, /// The amount of output tokens that have been exchanged pub out_amount_filled: u64, /// The amount of fees paid in the smallest unit of from_token mint pub fees_paid: u64, /// Price base in the order, in the smallest unit of output token pub price_base: u64, /// Price exponent, price is calculated as price_base * 10^(-price_exponent) pub price_exponent: u8, /// Time in order, used to determine how long the order is valid pub time_in_force: u8, /// Fee rate in ticks, used to determine the fee charged for the order pub fee_ticks: u8, } * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/events#instruction-discriminators) Instruction discriminators -------------------------------------------------------------------------------------------------------------------------------------------------- The `discriminator` field is always `0`. The `instruction` field identifies which operation triggered the event: * `**1**` **—** `**PlaceOrder**` — A new limit order was created. * `**2**` **—** `**TakeOrder**` — A searcher filled (partially or fully) an order. * `**3**` **—** `**CancelOrder**` — The maker cancelled the order. * `**4**` **—** `**ModifyOrder**` — The maker modified the order parameters. * `**5**` **—** `**WithdrawFilled**` — The maker withdrew filled output tokens from a partially filled order. * `**6**` **—** `**CloseExpired**` — An expired order was closed and rent reclaimed. The `status` field in the event reflects the order's state **after** the operation. Use [OrderStatus](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview#order-status) values to interpret it. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/events#related-pages) Related pages ------------------------------------------------------------------------------------------------------------------------ * [Limit Orders Overview](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview) — Order structure, time-in-force, order status, fees * [Placing Taker Orders](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order) — TakeOrder instruction and execution code * [Error Codes](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/error-codes) — Program error codes [PreviousPlacing Taker Orders](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order) [NextError Codes](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/error-codes) Last updated 2 months ago --- # Welcome to Titan | Titan ![Page cover](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FWxdi8oOhGoM2YwKx3SRu%252Fgitbook%2520background.png%3Falt%3Dmedia%26token%3D48a343f2-5bca-4adc-968b-1a9fc85deb81&width=1248&dpr=3&quality=100&sign=b4526886&sv=2) [](https://titan-exchange.gitbook.io/titan#outperformance-on-your-token-swaps) Outperformance on your Token Swaps ---------------------------------------------------------------------------------------------------------------------- Start swapping your tokens now at [https://app.titan.exchange/](https://app.titan.exchange/) . Titan is driven by one overarching goal to help all users within the Solana ecosystem: ### [](https://titan-exchange.gitbook.io/titan#experience-outperformance) _Experience Outperformance._ With Solana powering low latency low cost transactions, people can finally take back control, find the best prices, and minimize unnecessary middle man costs. The challenge is that with so much data living on-chain, how can users be sure that they are getting the best deal? #### [](https://titan-exchange.gitbook.io/titan#titans-products) Titan's Products To achieve this goal, Titan currently has 3 main features: * Unique Spot Swap Routes (DEX Aggregator) * Titan has developed its own unique algorithm called Argos that fixes problems associated with current solutions in finding the best trade routes. This has resulted in better prices for users 80% of the time. * Meta Aggregation on Solana * To ensure that users always get the best deal, Titan aggregates multiple aggregators and will route the user to the best quote with no fees attached. * Titan Prime Mode * Titan Prime automatically optimizes your swap settings — including slippage and transaction landing — to deliver the best execution through Titan’s meta-aggregator. Everything on Titan is dedicated to getting you the outperformance you deserve. The statistics on how much you have gained by using Titan's platform will be shown on the UI page, along with volume and referrals. Titan's API for integrations and systematic traders will be released soon. Please contact us for more details. [NextQuickstart](https://titan-exchange.gitbook.io/titan/getting-started/quickstart) Last updated 5 months ago --- # Error Codes | Developer Docs | Titan **These are the custom error codes thrown by the Titan Limit Order program.** Each maps to a specific on-chain validation failure. Copy #[repr(u8)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum LimitOrderError { InvalidOrderStatus, // 0 InvalidAmount, // 1 InvalidMaker, // 2 InvalidMint, // 3 InvalidPrice, // 4 InvalidTokenAccountAuthority, // 5 InvalidTokenProgramId, // 6 InvalidAssociatedTokenAccountAddress, // 7 InvalidExtension, // 8 EventDeserializationError, // 9 ExpirationSlotExceeded, // 10 ExecutionTimeInForceViolation, // 11 MaxCostLimitExceeded, // 12 OrderNotExpired, // 13 } * `**0**` **—** `**InvalidOrderStatus**` — Order is not in a valid state for this operation. Check the order's [status](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview#order-status) before interacting. * `**1**` **—** `**InvalidAmount**` — Amount is zero or exceeds the remaining balance. * `**2**` **—** `**InvalidMaker**` — Maker public key does not match the order. * `**3**` **—** `**InvalidMint**` — Token mint does not match the order's input or output mint. * `**4**` **—** `**InvalidPrice**` — Price parameters are invalid (e.g. zero `price_base`). * `**5**` **—** `**InvalidTokenAccountAuthority**` — Token account authority does not match the expected owner. * `**6**` **—** `**InvalidTokenProgramId**` — Wrong token program passed for the mint. **Use SPL Token for SPL mints, SPL Token-2022 for Token-2022 mints.** * `**7**` **—** `**InvalidAssociatedTokenAccountAddress**` — ATA address does not match the expected derivation. * `**8**` **—** `**InvalidExtension**` — Token extension is not supported by the program. * `**9**` **—** `**EventDeserializationError**` — Failed to deserialize event data. * `**10**` **—** `**ExpirationSlotExceeded**` — Order has expired. **Cannot be filled after the** `**expiration_slot**`**.** * `**11**` **—** `**ExecutionTimeInForceViolation**` — Take violates the order's [time-in-force](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview#time-in-force) policy. For example, attempting a partial fill on an `AllOrNothing` order. * `**12**` **—** `**MaxCostLimitExceeded**` — Cost exceeds the taker's `max_cost_amount`. Increase the limit or reduce the take amount. * `**13**` **—** `**OrderNotExpired**` — Attempted to close an order that has not yet expired. Wait until `expiration_slot` is reached. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/error-codes#related-pages) Related pages ----------------------------------------------------------------------------------------------------------------------------- * [Limit Orders Overview](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/overview) — Order structure, time-in-force, order status * [Placing Taker Orders](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/take-order) — TakeOrder instruction and execution code * [Limit Order Events](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/events) — Event structure and parsing from program logs [PreviousLimit Order Events](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/events) [NextSDK Reference](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk) Last updated 2 months ago --- # Meta Aggregation | Titan DEX Aggregation is the way to go for low cost chains, but every DEX Aggregator provides different quotes. This is due to different algorithms being used, as well as different data sets. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FPuVUTFjGnrpv8HEVZlfv%252F2.jpg%3Falt%3Dmedia%26token%3Dcbeb8631-1eb1-4fc7-beaa-75f7e2143f1a&width=768&dpr=3&quality=100&sign=d33d5743&sv=2) Regardless of the technique being used or aggregator in question, Titan will combine DEX Aggregators for users, thus becoming a Meta Aggregator. A Meta Aggregator utilises quotes from each individual Aggregator and then provides the best quote to the end user. This way, the user can be confident that they will always receive the best price on offer at any time. This would be very similar to your traditional broker in equity markets. When an order is placed, the broker would contact different market makers who would supply the liquidity. These market makers would make the trades on the individual exchanges. The broker would then select the best quote and send it to the user. In this scenario, the players translated over to the crypto ecosystem would be: * Exchange -> DEX * Market Maker -> DEX Aggregator * Broker -> Meta Aggregator Titan is sitting at this Meta Aggregator level to guarantee users the best price possible. #### [](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/markdown#how-to-compare-and-verify) How to Compare and Verify In order for Meta Aggregation to work, aggregator quotes have to be accurate, as well as be on the same block for them to be comparable. We have to be able to weed out inaccurate quotes as well as compensate for latency factors. Thankfully the solution for both problems is the same. Titan simulates all quotes directly on the blockchain. This shows the real amount out that a user would get if executed at that point in time. This also allows quotes to be compared as it removes the latency impacts of quotes arriving at different times. A given quote is simulated throughout its valid period to provide users the most up to date information. [PreviousTitan's Unique Algorithm](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/editor) [NextDART Routing](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/dart-routing) Last updated 9 months ago --- # SDK Reference | Developer Docs | Titan **Titan provides official SDKs for TypeScript and Rust.** Both connect to Titan Direct over WebSocket using MessagePack encoding with optional compression. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#typescript-sdk) TypeScript SDK ---------------------------------------------------------------------------------------------------------- **A high-level client with built-in connection management, compression negotiation, and full type safety.** * **Package:** `@titanexchange/sdk-ts` * **Source:** [github.com/Titan-Pathfinder/titan-sdk-ts](https://github.com/Titan-Pathfinder/titan-sdk-ts) * **Node.js:** >=18.19 ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#installation) Installation Copy npm install @titanexchange/sdk-ts ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#connecting) Connecting Copy import { V1Client } from '@titanexchange/sdk-ts'; // The SDK automatically negotiates compression (zstd, brotli, gzip, or none) const url = `wss://${process.env.TITAN_ENDPOINT}/ws?auth=${process.env.TITAN_API_KEY}`; const client = await V1Client.connect(url); **Connection state:** * `**client.closed**` — `boolean`, `true` if the connection is closed. * `**client.listen_closed()**` — Returns a `Promise` that resolves with the close event. * `**client.close()**` — Gracefully closes the connection. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#api-methods) API methods * `**client.getInfo()**` → `ServerInfo` — Protocol version and server settings. * `**client.newSwapQuoteStream(params)**` → `{ response, stream, streamId }` — Opens a streaming quote. * `**client.stopStream(streamId)**` → `StopStreamResponse` — Stops a stream by ID. * `**client.getVenues(params?)**` → `VenueInfo` — Lists available on-chain venues. * `**client.listProviders(params?)**` → `ProviderInfo[]` — Lists active quote providers. * `**client.getSwapPrice(params)**` → `SwapPrice` — One-shot price check without streaming. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#streaming-quotes) Streaming quotes Copy import bs58 from 'bs58'; const { stream, streamId } = await client.newSwapQuoteStream({ swap: { inputMint: bs58.decode('So11111111111111111111111111111111111111112'), outputMint: bs58.decode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'), amount: 1_000_000_000n, // 1 SOL — must be BigInt slippageBps: 50, }, transaction: { userPublicKey: bs58.decode('YOUR_WALLET_PUBLIC_KEY'), }, }); // Async iterator — yields SwapQuotes on each update for await (const quotes of stream) { // Use metadata.ExpectedWinner for the best slippage-adjusted route const winner = quotes.metadata?.ExpectedWinner; const best = winner && quotes.quotes[winner]; if (best?.instructions?.length) { console.log(`Best: ${winner} — ${best.outAmount} out`); } } ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#stopping-a-stream) Stopping a stream Copy // Method 1: via client await client.stopStream(streamId); // Method 2: via stream — calls stopStream() internally await stream.cancel('done'); ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#types) Types Copy import { types } from '@titanexchange/sdk-ts'; types.v1.SwapQuoteRequest; types.v1.SwapParams; types.v1.TransactionParams; ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#error-handling) Error handling All error classes are exported from the SDK: * `**ConnectionClosed**` — WebSocket connection closed. Properties: `code`, `reason`, `wasClean`. * `**ConnectionError**` — WebSocket error event. Property: `cause`. * `**ErrorResponse**` — Server rejected a request. Property: `response` (with `code`, `message`, `requestId`). * `**StreamError**` — Stream ended with an error. Properties: `streamId`, `errorCode`, `errorMessage`. * `**ProtocolError**` — Implementation bug — **report to Titan.** Properties: `reason`, `data`. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#reconnection) Reconnection **The SDK does not include built-in reconnect logic.** Handle reconnection manually: Copy client.listen_closed().then(async (event) => { if (!event.wasClean) { // Reconnect and re-establish streams const newClient = await V1Client.connect(url); // Re-open your streams on newClient } }); See [Error Handling & Reconnect](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling) for backoff strategies. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#browser-usage) Browser usage Copy import { V1Client } from '@titanexchange/sdk-ts/browser'; **Do not expose your API key in client-side code.** Use a middleware proxy that accepts user connections, validates authentication, and forwards to Titan with the API key server-side. See `examples/middleware.ts` in the SDK repository. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#key-details) Key details * **BigInt amounts** — Pass `amount` as `BigInt` (e.g. `1_000_000_000n`). Numbers >= 2^32 may be encoded as float64, **which the server rejects.** * `**quotes**` **is a map** — `SwapQuotes.quotes` is `Record`, keyed by provider ID. Not every provider appears in every update. * `**num_quotes**` **uses snake\_case** — In `QuoteUpdateParams`, the field is `num_quotes` (not `numQuotes`). **Logging BigInt values:** Copy JSON.stringify(data, (key, value) => { if (typeof value === 'bigint') return value.toString() + 'n'; if (value instanceof Uint8Array) return ``; return value; }, 2); * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#rust-sdk) Rust SDK ---------------------------------------------------------------------------------------------- **Low-level type definitions and MessagePack codec — you manage the WebSocket connection yourself.** * **Crates:** [crates.io/search?q=titan-api-types](https://crates.io/search?q=titan-api-types) * `**titan-api-types**` — Type definitions for all WebSocket request and response messages. * `**titan-api-codec**` — MessagePack encoding/decoding with compression support (zstd, brotli, gzip). ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#installation-1) Installation Copy [dependencies] titan-api-types = "5" titan-api-codec = "1.2" There is **no high-level client** in the Rust SDK. You manage the WebSocket connection using `tokio-tungstenite` (or any async WebSocket library) and use the codec for serialization. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#connecting-1) Connecting Copy use titan_api_codec::codec::{ws::v1::ClientCodec, Codec}; use titan_api_types::ws::v1; use tokio_tungstenite::{ connect_async, tungstenite::{ client::IntoClientRequest, http::header::{AUTHORIZATION, SEC_WEBSOCKET_PROTOCOL}, http::HeaderValue, }, }; let mut request = url.into_client_request()?; // Set protocol negotiation header let protocols = HeaderValue::from_str( &v1::WEBSOCKET_SUBPROTOCOLS.join(", ") )?; request.headers_mut().insert(SEC_WEBSOCKET_PROTOCOL, protocols); // Set auth header let bearer = HeaderValue::from_str(&format!("Bearer {}", token))?; request.headers_mut().insert(AUTHORIZATION, bearer); // Connect and create codec from negotiated protocol let (stream, response) = connect_async(request).await?; let protocol_str = response .headers() .get(SEC_WEBSOCKET_PROTOCOL) .and_then(|v| v.to_str().ok()) .unwrap(); let codec = ClientCodec::from_str(protocol_str)?; let (sink, stream) = stream.split(); ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#sending-requests) Sending requests Copy use titan_api_types::ws::v1::*; use titan_api_codec::codec::Codec; let encoder = codec.encoder(); let decoder = codec.decoder(); // GetInfo request let request = ClientRequest { id: 0, data: RequestData::GetInfo(GetInfoRequest::default()), }; // Encode to MessagePack and send as binary frame let bytes = encoder.encode(&request)?; sink.send(Message::Binary(bytes)).await?; ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#streaming-quotes-1) Streaming quotes Copy let request = ClientRequest { id: 1, data: RequestData::NewSwapQuoteStream(SwapQuoteRequest { swap: SwapParams { input_mint: sol_mint, output_mint: usdc_mint, amount: 1_000_000_000u64, slippage_bps: Some(50), ..Default::default() }, transaction: TransactionParams { user_public_key: wallet, ..Default::default() }, update: None, }), }; ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#processing-responses) Processing responses Copy while let Some(msg) = stream.next().await { let msg = msg?; if let Message::Binary(data) = msg { let server_msg: ServerMessage = decoder.decode(data.into())?; match server_msg { ServerMessage::Response(resp) => { // Handle RPC response } ServerMessage::StreamData(data) => { if let StreamDataPayload::SwapQuotes(quotes) = data.payload { for (provider, route) in "es.quotes { println!("{}: {} out", provider, route.out_amount); } } } ServerMessage::Error(err) => { eprintln!("Error {}: {}", err.code, err.message); } ServerMessage::StreamEnd(end) => { println!("Stream {} ended", end.id); } } } } ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#field-naming) Field naming The Rust SDK uses standard **snake\_case** field names. Serde handles the conversion to camelCase on the wire: * `input_mint` → `inputMint` * `output_mint` → `outputMint` * `slippage_bps` → `slippageBps` * `user_public_key` → `userPublicKey` * `only_direct_routes` → `onlyDirectRoutes` ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#reconnection-1) Reconnection **No built-in reconnect logic.** Handle connection drops and re-establish streams manually, same as the TypeScript SDK. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#dependencies) Dependencies * `**tokio-tungstenite**` — Async WebSocket client. * `**rmp-serde**` — MessagePack serialization. * `**zstd**` — Zstandard compression. * `**brotli**` — Brotli compression. * `**flate2**` — Gzip compression. * `**five8**` **/** `**five8_const**` — Base58 pubkey encoding. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk#related-pages) Related pages -------------------------------------------------------------------------------------------------------- * [Quickstart](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart) — End-to-end integration example * [Stream & Execute a Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) — Full guide with transaction building * [Wire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) — Encoding rules and message envelopes * [Error Codes](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes) — Error codes and SDK error classes [PreviousError Codes](https://titan-exchange.gitbook.io/titan/developer-doc/searchers-limit-orders/error-codes) [NextCommunity & Support](https://titan-exchange.gitbook.io/titan/developer-doc/resources/community-and-support) Last updated 20 days ago --- # DART Routing | Titan **DART** (Dynamic Allocation and Real Time) Routing is Titan's onchain routing engine and the world's first router that dynamically re-optimizes a trade at the exact moment of execution, not seconds before. ### [](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/dart-routing#the-quote-to-execution-gap) The Quote to Execution Gap ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FeWfMEJaN9h06OygNExW8%252Fimage.png%3Falt%3Dmedia%26token%3Dce997a9b-cb57-4c22-aa76-ef61212d49f1&width=768&dpr=3&quality=100&sign=db5491e4&sv=2) Aggregators typically compute the route for a trade before the transaction is submitted to the blockchain. A route is calculated, a quote is returned to the user, and the transaction is then broadcast to the network. By the time that transaction lands in a block, anywhere from hundreds of milliseconds to several seconds may have passed. In that window, liquidity conditions across pools change. Prices shift. Other trades execute against the same routes. The route that was optimal at quote time is no longer optimal at execution time. This gap between when a route is computed and when it actually executes is an inherent limitation of all pre-execution routing systems. For small trades this gap may be small. For larger trades, the cost of this staleness compounds quickly, as the price impact and route quality have both moved in the time it took for the transaction to settle. ### [](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/dart-routing#how-dart-works) How DART Works DART operates on a straightforward principle: at execution time, the combination of pools offering the best available prices for your trade wins the order. Market makers need the flexibility to adjust spreads in either direction when required. DART ensures your trade always selects the best venues, regardless of market maker's adjustments. Before the transaction is built, Titan's offchain infrastructure determines the optimal route shape: which pools to include, which venues have the deepest liquidity for your trade size, and which paths are worth considering. This is the foundation that DART builds on. At execution time, **DART dynamically re-optimizes how your volume is split across a large number of pools in real time**, onchain. It utilizes the full liquidity universe including: ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FXc2LQcBi4litvQ66kabB%252Fimage.png%3Falt%3Dmedia%26token%3D224aa04f-784d-4b2b-9bdd-f172c46f3f71&width=768&dpr=3&quality=100&sign=8792a9d0&sv=2) ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252F2uLMvrMnSu5qwA7P67CQ%252Fimage.png%3Falt%3Dmedia%26token%3D535bc05a-9746-40a5-ba06-15681bdc0169&width=768&dpr=3&quality=100&sign=534d37d0&sv=2) * Prop AMMs * Non-prop AMMs (Orca, Meteora) * Orderbook-based DEXes * Mint/redeem pools More pools, smarter weight optimization, better execution. Working alongside **Argos**, Titan's offchain router and already the most advanced on Solana, the combination forms a hybrid routing engine. Together, they close the gap as close as possible to deliver the best execution available on Solana today. ### [](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/dart-routing#best-bid-offer-guarantee) Best Bid Offer Guarantee Because DART resolves routing at execution time against actual onchain state, it provides a **Best Bid Offer (BBO)** guarantee. This means users are always filled by the market makers offering the best available quotes at the precise moment their trade executes. In traditional financial markets, BBO is the standard that regulated venues are required to achieve. It means that when you submit an order, the exchange must fill it at the best available price across all connected liquidity sources at that moment. DART brings this same guarantee onchain for the first time on Solana. The result is that users are not just getting the best route that could be found before their transaction was sent. They are getting the best route that exists at the moment their transaction lands, computed in real time from live market conditions. > **DART is the de-facto standard for onchain execution on Solana.** [PreviousMeta Aggregation](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/markdown) Last updated 2 months ago --- # Private Beta | Titan As Titan gets ready to invite all users onboard, a select group of users will be onboarded onto a private beta. This beta is necessary to facilitate user feedback, make optimizations, and ensure that the required infrastructure is set up to support user demand. To sign up for the private beta, please visit [https://titan.exchange/](https://titan.exchange/) where an email can be submitted to the private beta. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FpOAq9izBUKWAoJCJ3elS%252FScreen%2520Shot%25202025-08-13%2520at%25201.42.47%2520PM.png%3Falt%3Dmedia%26token%3D78ede8de-7252-4ede-a408-6d1f7816b81b&width=768&dpr=3&quality=100&sign=72191c1c&sv=2) After submission, please sit back and wait for a confirmation email that you have been enrolled into the Titan Private Beta. ### [](https://titan-exchange.gitbook.io/titan/getting-started/publish-your-docs#invite-codes) Invite Codes An invite code will be provided to you through email. To access the beta, please go to [https://app.titan.exchange](https://app.titan.exchange/swap) . There you will be asked to connect your wallet. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FDFhySOIyRWWVez5ZOr7D%252FScreen%2520Shot%25202025-08-13%2520at%25201.43.44%2520PM.png%3Falt%3Dmedia%26token%3D9e4cb9cd-7468-4bc7-9c56-0f772dd8bf84&width=768&dpr=3&quality=100&sign=6f5a5aa7&sv=2) After you have connected your wallet, the platform will check if that wallet address has already been whitelisted. If not, then a popup appears notifying you to either sign up for the waitlist or proceed with an invite code. If you have an invite code, please click Proceed and go to the next screen. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FRUJVmLxPMSb2M4xdPkuy%252FScreen%2520Shot%25202025-08-13%2520at%25201.45.23%2520PM.png%3Falt%3Dmedia%26token%3D7eff43e3-9bd3-4a1c-b756-1a147b86e184&width=768&dpr=3&quality=100&sign=1e85d458&sv=2) After entering the invite code, your connected wallet will be whitelisted and you can start to use the Titan platform. Please note that the wallet you connect will be the only one allowed to access the beta. If there has been a mistake, please submit a support ticket on Titan's discord. We look forwards to hearing your feedback on Titan! Last updated 10 months ago --- # DEX Aggregators | Titan There are multiple ways to do spot trades on Solana. You can either trade directly with a centralized exchange (CEX) such as Binance or Coinbase, a decentralized exchange (DEX) such as Orca or Raydium, or a DEX Aggregator like Titan or Jupiter. If you trade through a CEX/DEX, you are only sourcing liquidity for your trade from one venue, which may not offer the best price. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FnjSSCrEKB7vODKKmryZn%252FTitan%2520Argos.jpg%3Falt%3Dmedia%26token%3D91aa70cb-d8ea-499e-a9c8-30dc3c4b9770&width=768&dpr=3&quality=100&sign=e80e361a&sv=2) In traditional finance markets, brokers are connected to multiple sources of liquidity to source you the best price if you have an account. In crypto, the only way to do this without dedicated infrastructure and multiple compliance checks is to aggregate the liquidity among DEXes. Platforms that offer these are called DEX Aggregators. The problem that DEX Aggregators face are fairly unique. In traditional markets, the speed is so fast (nanoseconds) that order flow must be processed almost instantly, but in crypto markets, there is enough distributed liquidity and enough time to deploy advanced analytics to find the best possible route. DEX Aggregation on Solana is especially strong due to the network's low fees. This makes it feasible to find complex routes that provide better prices without it being absorbed by extremely high gas prices as in Ethereum. Due to this, DEX Aggregators are the preferred way for users to trade on low cost chains in order to maximize their asset's value. [PreviousHow Swaps Work](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/how-swaps-work) [NextTitan's Unique Algorithm](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/editor) Last updated 9 months ago --- # How Swaps Work | Titan A swap is how users on a blockchain trade one token for another. A straight token to token trade without the use of leverage is called a spot swap/trade as the underlying token is the one being traded. In DeFi, a user signs a transaction through their wallet for their trade to execute on the desired platform. This transaction propagates throughout the entire blockchain worldwide and after a short delay, the trade is confirmed and you have the results of your trade in your wallet. An advantage here is that the funds are transferred immediately without waiting for the lag time that is present in traditional markets. In addition, Solana does this at very low costs (sub cent), thus making it more efficient than many money transmitting networks, especially internationally. [PreviousTitan DART](https://titan-exchange.gitbook.io/titan/getting-started/titan-dart) [NextDEX Aggregators](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/dex-aggregators) Last updated 3 months ago --- # Titan Private Swaps | Titan Titan Private Swaps add a private execution layer to your token swaps on Solana. Trade with confidence knowing your activity isn't publicly tied to your main wallet history. Each swap is routed through a one-time intermediary wallet generated fresh per trade. This one-time wallet is the on-chain signer — not your primary address. This breaks the on-chain link between your trading activity and your main wallet ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FdlFFNm198hdiAo8krec2%252Fimage.png%3Falt%3Dmedia%26token%3D859d2986-618f-4703-93ae-94fe9d60255d&width=768&dpr=3&quality=100&sign=c2f5869c&sv=2) ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-private-swaps#how-its-different) How It's Different Regular swaps on Solana are fully public — anyone can trace your wallet address and see every trade you've made. Titan Private Swaps change this by routing each trade through a one-time intermediary wallet generated fresh per swap. This one-time wallet is the on-chain signer, not your primary address. Chain analysis tools cannot link the trade back to you. This is powered by the **Vanish wallet** — a separate wallet generated for your private swaps. Funds sit in your Vanish wallet and are used to execute trades, while your main wallet stays untouched and disconnected from your trading activity. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252F8F8APjlxO5iMujS4nLA6%252Fimage.png%3Falt%3Dmedia%26token%3D160d01ff-68f9-4b7a-9328-7e73a2ce4736&width=768&dpr=3&quality=100&sign=c9093482&sv=2) * **Unlinked activity** — Your main wallet never appears as the trader in any swap transaction. On-chain, only a one-time intermediary wallet is visible, and that wallet is discarded after each trade — making it extremely difficult to build a picture of your trading activity. * **Private trading** — Every swap is routed through a fresh intermediary address that is generated specifically for that trade and never reused. This means no single address accumulates your trading history or token balances, and your activity can't be traced back to a single source. * **Full control, anytime** — Your funds are always in your custody. Deposits are constructed and signed by your own wallet, and you can move funds back to your main wallet at any time with no protocol fees. Vanish can be used or skipped entirely — it's your choice on every swap. * * * ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-private-swaps#getting-to-private-swaps) Getting to Private Swaps On the swap page, click the **Private** tab in the navigation bar alongside Instant and Limit. If this is your first time, you will be walked through a quick one-time setup to get your Vanish wallet ready. Once set up, the full swap interface loads automatically every time you navigate to the Private tab. #### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-private-swaps#enable-vanish) Enable Vanish If you haven't set up your Vanish wallet yet, you'll land on the onboarding screen first. Click **Enable Vanish** to generate your Vanish wallet. This is a one-time step. Once enabled, you'll be prompted to sign a message with your wallet to authenticate your Vanish session. This signature is verified server-side and stored securely — your API key is never exposed to the browser. Sessions are valid for 24 hours. You'll receive a warning 5 minutes before your session expires, and can re-sign to continue without any disruption. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FnZ0qnGEP6sCLXUzYDNBx%252Fimage.png%3Falt%3Dmedia%26token%3D3fafb145-905c-464e-b33f-50e8f5a463d2&width=768&dpr=3&quality=100&sign=f55dc372&sv=2) #### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-private-swaps#fund-your-vanish-wallet) Fund Your Vanish Wallet Once your Vanish wallet is active, you'll need to transfer funds into it before you can swap. Click **Fund From Main Wallet** on the Private swap page. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FRefCvR9CSlTvpKmZ0rKy%252Fimage.png%3Falt%3Dmedia%26token%3D3d1485d8-ddea-45c1-9044-5d31a776436e&width=768&dpr=3&quality=100&sign=3640e77c&sv=2) A modal will appear showing your **Main wallet** and **Vanish wallet** side by side with their current balances. Enter the amount of SOL you want to transfer and confirm. The transfer transaction is built and signed entirely client-side by your own wallet — Titan never takes custody of your funds during this step. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FZynZUFcGJvUIScC4kSZh%252Fimage.png%3Falt%3Dmedia%26token%3D04c79bc6-617e-4655-9bd3-333be039dab7&width=768&dpr=3&quality=100&sign=a6a5e2e0&sv=2) There are no Protocol fees for this transfer. **Minimum SOL balance** — Your Vanish wallet must always hold at least ~0.012 SOL. This covers the account rent that Vanish loans per trade to set up the one-time intermediary wallet. This minimum is required on top of any SOL you intend to sell. If your balance drops below this threshold, the Swap button will show "Insufficient SOL For Private Swap" and you'll need to top up before continuing. * * * ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-private-swaps#executing-a-swap) Executing a Swap With your Vanish wallet funded, you're ready to go. The swap interface works similarly to Instant swaps, with a few things specific to Private Swaps to keep in mind. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FyN3uvNYHwZWxgNtt7xRY%252Fimage.png%3Falt%3Dmedia%26token%3Dbce125cb-73e0-456c-a75e-50b34b20b821&width=768&dpr=3&quality=100&sign=69e52c58&sv=2) **Sell** — Select the token and amount you want to sell. The balance shown is your Vanish wallet balance, not your main wallet. **Buy** — Select the token you want to receive. **SOL pairing** — SOL must be on one side of every Private Swap — either the token you're selling or the token you're buying. This is a protocol requirement tied to how the one-time wallet mechanism works. Both SPL tokens and Token-2022 tokens are supported on the non-SOL side. Once you've set your tokens and amounts, review the **Summary** panel before confirming: * **You sell** — the exact amount leaving your Vanish wallet * **You buy (est.)** — the estimated amount you will receive * **Total Vanish points** — points earned from this swap * Protocol **fee** — 0.25% The **Quotes** section shows how Titan's price compares against other aggregators in real time. Titan will always highlight the best available price across routes. **Signing** — Each swap requires a separate wallet signature before it executes. This is by design. Every signature is cryptographically bound to the exact parameters of that trade — token pair, amount, and timestamp — so nothing can be replayed or modified after you sign. Expect one signing prompt per swap. Once signed, click **Swap** to execute. All Private Swaps are submitted via Jito bundles and broadcast in MEV-protected mode, protecting your trade from front-running. **After execution** — There is a short finalization step after the on-chain transaction confirms, where Titan settles the trade internally and updates your balance and trade history. This typically completes quickly but can take up to 2 minutes. If finalization doesn't complete within your session, Titan will automatically pick it up and retry the next time you authenticate. * * * ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-private-swaps#what-happens-if-a-swap-fails) What Happens if a Swap Fails? Occasionally a Private Swap may not go through — this can happen due to slippage limits being exceeded, network congestion, or the Jito bundle not landing in time. If this happens, your funds are not lost. Since the swap is routed through a one-time intermediary wallet, any funds that were staged for the trade will be returned to your Vanish wallet automatically. This typically happens within a few minutes. You do not need to take any action — the process is handled by Titan in the background. Once your balance is restored you'll see it reflected in your Vanish wallet and can retry the swap. If funds don't appear after a few minutes, check your order history for the status of the failed trade or reach out to the team. * * * ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-private-swaps#managing-your-vanish-wallet) Managing Your Vanish Wallet You can move funds between your main wallet and Vanish wallet freely at any time in either direction. Click **Move funds** at the bottom of the Private swap page. There are no fees for transfers in either direction. Withdrawals back to your main wallet are handled by a Vanish-constructed transaction that you sign and submit — your destination address is always your own wallet. Your current Vanish wallet balance is always visible on the swap interface so you know exactly what's available to trade. * * * ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-private-swaps#analytics-points) Analytics / Points Vanish points are earned on every Private Swap and tracked per trade. Your points balance and swap history will be reflected on your profile page and the rewards leaderboard. You can also track individual swap progress from your order history. [PreviousTitan Limit Orders](https://titan-exchange.gitbook.io/titan/getting-started/titan-limit-orders) [NextAnalytics](https://titan-exchange.gitbook.io/titan/getting-started/analytics) Last updated 3 months ago --- # Analytics | Titan Titan will provide extra analytics to users to help them process their swap information. As we continue to process more trades, we will launch more features that users demand to give them access to timely information about their on-chain trades. After doing a trade, users will be able to see the total outperformance as well as total fee savings that they have obtained from using Titan. This in total makes up the total trading edge that a user gets, meaning the total dollar value that a trader has gained just from using Titan. Outperformance refers to the benefit the trader gets from being able to compare a variety of quotes for their desired trade, especially with quotes unique to Titan. Total fee savings totals up the fees that a trader would have had to pay on other platforms if they had traded there. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252F0Hw9lVa1sXNGyvatMKz9%252FScreen%2520Shot%25202025-09-12%2520at%25206.22.23%2520PM.png%3Falt%3Dmedia%26token%3D5fa7fd83-d457-4475-adfe-6d4f3f319151&width=768&dpr=3&quality=100&sign=e28dcbc&sv=2) Additional statistics such as total volume and the number of trades will also be displayed. In addition, once you have referred 2 or more people, you can see an aggregate view of your referred group's data as well. In addition, the badges that have been earned will also display here. [PreviousTitan Private Swaps](https://titan-exchange.gitbook.io/titan/getting-started/titan-private-swaps) [NextUsernames and Referrals](https://titan-exchange.gitbook.io/titan/getting-started/usernames-and-referrals) Last updated 9 months ago --- # Titan DEX Integrations | Titan If you are interested in integrating your AMM or liquidity source into Titan, please see our guidelines at [https://github.com/Titan-Pathfinder/integration-template](https://github.com/Titan-Pathfinder/integration-template) . We handle all types of integrations, from traditional swaps to specialized mint/redeem integrations. If you have questions or a request, please reach out directly to the team on telegram or discord. [PreviousUsernames and Referrals](https://titan-exchange.gitbook.io/titan/getting-started/usernames-and-referrals) [NextTitan DART](https://titan-exchange.gitbook.io/titan/getting-started/titan-dart) Last updated 5 months ago --- # Titan's Unique Algorithm | Titan Historically, DEX aggregators have relied on shortest path algorithms to determine routes between liquidity. In doing so, they have benefited from battle tested algorithms that are simple to implement. However, given the nature of the crypto markets, latency requirements and underlying assumptions of shortest path algorithms, liquidity sources are often temporarily removed when these types of algorithms are used in order to make routing possible. In addition to this, a specific route in a network may not have significant capacity. If the pools involved have a small TVL then the price can change rapidly as more of the users’ funds are swapped through each relevant exchange. To capture the effects of price impact, the liquidity is frequently fragmented into pieces and each pool is broken into many parts with an average price and a certain capacity. This is frequently reflected both in the algorithm and its outputs. For example, currently Jupiter, another DEX aggregator, generally chunks their routes into neat 1% buckets. This fragmentation of liquidity increases the size of the network being searched and leads to inaccuracies when the pool is poorly resolved. These two challenges are among the main obstacles in applying shortest path methods for DEX aggregation. To address them, Titan leverages a different set of algorithms that focus on optimization, which resulted in the development of the Argos algorithm. These algorithms can efficiently resolve price impacts with machine-level precision without fragmenting pools and eliminates the need to exclude various liquidity sources, thus leading to a true optimal on-chain price. [PreviousDEX Aggregators](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/dex-aggregators) [NextMeta Aggregation](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/markdown) Last updated 3 months ago --- # Quickstart | Titan Titan does not charge any fees on basic swaps. The underlying DEXes or DEX Aggregators that have been incorporated may charge fees To start interacting with the platform, please connect your wallet. There is a large selection of wallets that you may choose from. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252Fb1me2FmTzPV8tEWvj75h%252FScreen%2520Shot%25202025-09-21%2520at%252011.03.22%2520AM.png%3Falt%3Dmedia%26token%3Df4a17ce3-1bf4-4b26-91bb-3ac777222d34&width=768&dpr=3&quality=100&sign=5779744f&sv=2) Once connected, you are able to interact with the swap interface. You can also see the cumulative total of your trading volume with Titan, as well as your total outperformance and edge gained as a result of using Titan over other platforms. Please note that ledger wallet integrations are supported with these wallets. ### [](https://titan-exchange.gitbook.io/titan/getting-started/quickstart#how-to-do-a-swap) How to do a Swap You must first select your input and output tokens that you want to trade. The input tokens are sorted based on the USD value of the tokens in your wallet, while the output tokens are shown based on popularity and relevance. Once the tokens are selected, you can select the input token amount you want to trade and quotes will populate to fill in the estimated amount out. Please note that specifying the amount out as of this time is not allowed. You will receive quotes from multiple aggregators. Titan will populate the estimated amount out as well as the relevant transaction details from the best quote. Users can then approve and execute the transaction. Please note that quotes refresh every second. The quotes themselves are simulated live on the blockchain to provide a live stream of the most up to date output given the routes. Titan provides the best on-chain estimate of the actual output of a given quote. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252Ff3adxeLunL4sYzold0gq%252FScreen%2520Shot%25202025-08-13%2520at%25201.36.05%2520PM.png%3Falt%3Dmedia%26token%3D61b7e4e1-1933-4c30-af22-5a3694c30bda&width=768&dpr=3&quality=100&sign=d40495b4&sv=2) The number of pools and DEXes involved in the chosen route will also be shown. Users can then click on the Swap button to execute through their connected wallet application. ### [](https://titan-exchange.gitbook.io/titan/getting-started/quickstart#trade-settings) Trade Settings In addition, trades can be sized quickly by selecting the Max or % buttons in the input bar. The % button allows users to have fine grain control over the amount of the input tokens they want to trade. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FpiigCK2Ucdc2yWLEREEU%252FScreen%2520Shot%25202025-09-21%2520at%252011.04.47%2520AM.png%3Falt%3Dmedia%26token%3De79beba0-34e7-4296-9f15-ac261cc9e84c&width=768&dpr=3&quality=100&sign=845f3d9f&sv=2) Users can further customize their settings as described in the Custom Settings page. [PreviousWelcome to Titan](https://titan-exchange.gitbook.io/titan) [NextPrime Mode and Custom Settings](https://titan-exchange.gitbook.io/titan/getting-started/quickstart-1) Last updated 8 months ago --- # Titan DART | Titan [](https://titan-exchange.gitbook.io/titan/getting-started/titan-dart#dart-settings) DART Settings ------------------------------------------------------------------------------------------------------- Control how Titan routes your swaps — configure DART directly from the swap interface. ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-dart#configuration) Configuration Above the swap box, users can configure their DART settings by clicking on the DART box. For DART eligible pairs, DART defaults to **Auto**. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FpqpForzkDsTtEF9eglWu%252Fimage.png%3Falt%3Dmedia%26token%3Df239cf5b-66b0-4af9-8839-3aa00bc9460d&width=768&dpr=3&quality=100&sign=8b169b1b&sv=2) Mode Behavior **Auto** Titan uses a combination of both Argos and DART to determine the optimal execution. Recommended setting. **Only** Titan only uses DART routing. **Off** Titan only will use off-chain Argos routing. ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-dart#dart-available-pairs) DART Available Pairs DART routing is currently available for the following pairs, with more coming online soon. * SOL/USDC * SOL/USDT * USDT/USDC * cbBTC/USDC * wETH/USDC * TRUMP/USDC * ZEC/USDC * USD1/USDC * HYPE/USDC * PUMP/USDC * PENGU/USDC * FARTCOIN/USDC * syrupUSD/USDC * PYUSD/USDC * USDG/USDC * CASH/USDC * AAVE/USDC * MEGA/USDC ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-dart#dart-fees) DART Fees Titan DART charges up to maximum 1 bps per swap. Users on Titan only get routed via DART if the end execution including fees and expected slippage is better than all other routers. ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-dart#dart-status-indicator) DART Status Indicator The colored dot on the DART swap page is a visual indicator that tells you the live execution status of DART at any moment. It stays static with no animation or flickering for clarity. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FovdVS5mfp3dPbA55PwN7%252Fimage.png%3Falt%3Dmedia%26token%3De0ab4da4-5b23-4916-a2a0-326db95474d5&width=768&dpr=3&quality=100&sign=dfa90240&sv=2) DART set to **Only** with the green status indicator confirming DART is actively executing the swap. Titan returns the best price across all quoted routes ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FX1NGA0trOgRpIpj94ftC%252Fimage.png%3Falt%3Dmedia%26token%3D0e402374-413f-48aa-9973-e313c1224c4e&width=768&dpr=3&quality=100&sign=c0f3da5d&sv=2) DART is set to **Off** — the red indicator confirms your transaction will be executed via non-DART routes Color Meaning **Green** DART is live and active — it is the selected route that will actually execute your swap. **Red** DART is not executing the trade — either it's not available, or another route is being used instead. > **Note:** The dot does not turn green just because DART shows up in the quotes list. It only turns green when DART is the winning/selected quote that will be executed. Green truly means DART is handling your trade, not just participating in the comparison. A single glance tells you whether you're getting the DART execution experience or not, without needing to dig into route details. [PreviousTitan DEX Integrations](https://titan-exchange.gitbook.io/titan/getting-started/titan-dex-integrations) [NextHow Swaps Work](https://titan-exchange.gitbook.io/titan/codex-of-knowledge/how-swaps-work) Last updated 1 month ago --- # Titan Direct vs Titan Gateway | Developer Docs | Titan Two interfaces to the same execution infrastructure. Both route through Titan's advanced algorithms, return the same quote types, and produce identical quote quality and transaction output. **The difference is interface and workflow, not routing quality.** [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway#titan-direct-websocket-api) Titan Direct — WebSocket API ----------------------------------------------------------------------------------------------------------------------------------------------------------- Titan Direct is a WebSocket API built for users where latency and execution are critical to their operations. Market makers, prop trading desks, and quant/algo traders operate in an environment where quote freshness and fill latency are existential. A persistent WebSocket connection eliminates the overhead of repeated HTTP handshakes and allows Titan to push live quote updates without polling. Routes are served by Argos, Titan's proprietary routing engine — giving users the best available price across the full liquidity landscape. **Titan Direct is the only WebSocket-native trading API on Solana. Built for traders who can't afford stale quotes.** **Use Direct when you need:** * Real-time streaming quotes that refresh automatically as on-chain state changes * Persistent connections for trading bots, market making, or algorithmic strategies * The lowest possible latency between quote and execution [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway#titan-gateway-rest-api) Titan Gateway — REST API --------------------------------------------------------------------------------------------------------------------------------------------------- Titan Gateway is a REST API built for developers and projects integrating swap functionality into products — wallets, aggregators, DeFi protocols, and consumer apps. These teams work in REST environments and do not need to redesign their architecture for a WebSocket connection. **Titan Gateway is the fastest path from zero to production-grade swap execution on Solana.** **Gateway is not a simplified version of Direct.** It is purpose-built for integration workflows, backed by the same Argos routing engine that powers Direct — **the routing quality is identical.** The differentiation is purely about interface and integration workflow. **Use Gateway when you need:** * Standard REST endpoints that fit into existing backend infrastructure * A single quote per user action — one-click swap buttons, price displays, or backend services * Drop-in integration without WebSocket infrastructure [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway#comparison) Comparison ------------------------------------------------------------------------------------------------------------------------- Titan Direct Titan Gateway Interface WebSocket REST Quote delivery Streaming — continuous updates Per-request — one response per call Connection Persistent Stateless [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway#api-endpoint-mapping) API endpoint mapping --------------------------------------------------------------------------------------------------------------------------------------------- Every Titan Direct RPC method has a corresponding Gateway REST endpoint. The request parameters and response types are the same. Titan Gateway Titan Direct `GET /api/v1/info` `GetInfo` `GET /api/v1/providers` `ListProviders` `GET /api/v1/venues` `GetVenues` `GET /api/v1/quote/swap` `NewSwapQuoteStream` [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway#which-should-i-use) Which should I use? ------------------------------------------------------------------------------------------------------------------------------------------ If you're not sure, start with Titan Direct. The [`@titanexchange/sdk-ts`](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk) SDK handles the WebSocket connection, MessagePack encoding, and compression negotiation for you. If your architecture requires REST or a persistent connection isn't practical, use Titan Gateway — you get the same routing quality through a familiar request/response pattern. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway#related-pages) Related pages ------------------------------------------------------------------------------------------------------------------------------- * [Quickstart](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart) — first quote with both Direct and Gateway * [Stream & Execute a Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) — full Titan Direct guide * [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) — WebSocket protocol details * [Wire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) — MessagePack encoding and compression [PreviousAPI Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference) [NextTitan Direct](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct) Last updated 2 months ago --- # Titan Gateway | Developer Docs | Titan **The fastest path from zero to production-grade swap execution on Solana.** Titan Gateway exposes the same Argos routing engine as Titan Direct through simple REST endpoints. All responses are [MessagePack](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) \-encoded. [PreviousGetSwapPrice](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price) [NextQuote Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap) Last updated 2 months ago --- # Connection & Negotiation | Developer Docs | Titan **Titan Direct is a persistent WebSocket connection.** All messages are binary frames encoded with [MessagePack](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) . Before the first request, the client and server negotiate a protocol version and optional compression scheme via the `Sec-WebSocket-Protocol` header. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#protocol-negotiation) Protocol negotiation --------------------------------------------------------------------------------------------------------------------------------------------- The client lists supported protocols in order of preference via the `Sec-WebSocket-Protocol` header. The server selects the best mutual match and confirms it in the response header. All version 1 protocols begin with `v1.api.titan.ag`, optionally suffixed with `+zstd`, `+brotli`, or `+gzip` for compression. Without a suffix, no compression is used. **Compression is applied after MessagePack encoding and must be reversed before decoding on the receiving end.** All Titan SDK examples and guides use zstd. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#authentication) Authentication --------------------------------------------------------------------------------------------------------------------------------- **The server requires authentication before any requests can be made.** Credentials are submitted via a signed **JWT (JSON Web Token)** when opening the connection: * **Authorization header** (recommended) — `Authorization: Bearer ` * **Query parameter** — `wss://YOUR_ENDPOINT/api/v1/ws?auth=` — for clients that cannot set custom headers (e.g. browsers) ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#jwt-claims) JWT claims **Required:** * `**iss**` — Issuer of the JWT. * `**sub**` — Subject, a unique identifier for the authenticated user. * `**aud**` — Audience, **must be** `**api.titan.ag**`. * `**exp**` — Expiration time. Connections are refused if this time is in the past. * `**iat**` — Issued-at time. Tokens with issue times in the future are rejected. **Optional:** * `**nbf**` — Not-before time. Connections are refused if this time is in the future. * `**jti**` — JWT ID. If supported by the server, only one connection per unique `jti` value is accepted. * `**https://api.titan.ag/upk_b58**` — A Solana public key as a Base58 string. If set, this key is used for transaction generation and **any attempt to submit a different** `**userPublicKey**` **will result in an error**. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#connecting) Connecting ------------------------------------------------------------------------------------------------------------------------- Copy import WebSocket from 'ws'; import { Encoder, Decoder } from '@msgpack/msgpack'; import { zstdCompress, zstdDecompress } from 'http-encoding'; // useBigInt64 is required — u64 values (amounts, timestamps) exceed Number.MAX_SAFE_INTEGER const encoder = new Encoder({ useBigInt64: true }); const decoder = new Decoder({ useBigInt64: true }); let useCompression = false; // Pass your API key as a query parameter const url = `${process.env.TITAN_ENDPOINT}?auth=${process.env.TITAN_API_KEY}`; // Offer zstd compression with a plaintext fallback const ws = new WebSocket(url, [\ 'v1.api.titan.ag+zstd',\ 'v1.api.titan.ag',\ ]); ws.on('open', () => { // Check which protocol the server selected useCompression = ws.protocol !== 'v1.api.titan.ag'; console.log('Connected. Negotiated protocol:', ws.protocol); }); [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#message-format) Message format --------------------------------------------------------------------------------------------------------------------------------- **All messages are binary WebSocket frames — text frames are ignored.** Every message is MessagePack encoded. For encoding conventions, data types, and serialization details, see [Wire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) . [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#rpc-interface) RPC interface ------------------------------------------------------------------------------------------------------------------------------- The client interacts with the server by making requests with a given set of parameters and receiving a response (success or error) for each request. Procedure Parameters Response Stream `GetInfo` `GetInfoRequest` `ServerInfo` — `NewSwapQuoteStream` `SwapQuoteRequest` `QuoteSwapStreamResponse` `SwapQuotes` `StopStream` `StopStreamRequest` `StopStreamResponse` — `GetVenues` `GetVenuesRequest` `VenueInfo` — `ListProviders` `ListProvidersRequest` `ProviderInfo[]` — Every client request is a [`ClientRequest`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#message-envelope-types) with a numeric `id` and a `data` field containing one of the RPC methods above. The server matches responses to requests via `requestId` and responds with one of four message types: `**Response**`, `**Error**`, `**StreamData**`, or `**StreamEnd**`. See [Types Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#message-envelope-types) for the full type definitions. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#sending-a-request) Sending a request Copy // Monotonically increasing counter — server echoes this back in responses let requestId = 0; // Encode and optionally compress before sending async function sendRequest(ws: WebSocket, id: number, data: Record) { const encoded = encoder.encode({ id, data }); ws.send(useCompression ? await zstdCompress(encoded) : encoded); } // Decompress (if needed) and decode incoming messages async function decodeMessage(raw: Buffer): Promise { const data = useCompression ? await zstdDecompress(raw) : raw; return decoder.decode(data); } // Send GetInfo to confirm the connection is live await sendRequest(ws, requestId++, { GetInfo: {} }); // Handle all four server message types ws.on('message', async (raw: Buffer) => { const msg = await decodeMessage(raw); if ('Response' in msg) { // Successful RPC response — correlate via requestId console.log('Response to request', msg.Response.requestId, msg.Response.data); } if ('Error' in msg) { // RPC error — contains requestId, code, and message console.error('Error on request', msg.Error.requestId, msg.Error.code, msg.Error.message); } if ('StreamData' in msg) { // Stream update — contains id, seq, and payload } if ('StreamEnd' in msg) { // Stream closed — check errorCode/errorMessage for abnormal termination } }); Use a single incrementing `requestId` counter per connection. The server returns the same `requestId` in its response, so you can correlate requests and responses without additional bookkeeping. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#ping-pong) Ping / Pong ------------------------------------------------------------------------------------------------------------------------- The client and server both support standard WebSocket Ping/Pong frames. The `ws` library handles these automatically — **no explicit handling needed** unless you want to monitor connection health manually. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#related-pages) Related pages ------------------------------------------------------------------------------------------------------------------------------- * [GetInfo](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) — confirm the server is reachable and read default settings * [Wire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) — MessagePack encoding and serialization details * [Titan Direct vs Titan Gateway](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway) — choosing between WebSocket and REST [PreviousTitan Direct](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct) [NextGetInfo](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) Last updated 2 months ago --- # Quote Swap | Developer Docs | Titan **Returns swap quotes with executable instructions and address lookup tables — the Gateway equivalent of** [**NewSwapQuoteStream**](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) **.** A single REST call instead of a WebSocket stream. Copy GET /api/v1/quote/swap **Authentication** — `Authorization: Bearer ` header or `?auth=` query param. See [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#authentication) for JWT details. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#query-parameters) Query parameters ---------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#required) Required * `**inputMint**` — Input token mint address (base58). * `**outputMint**` — Output token mint address (base58). * `**amount**` — Amount in the smallest unit (e.g. lamports for SOL). **Not scaled by decimals.** * `**userPublicKey**` — Wallet public key (base58). Required for transaction/instruction generation. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#swap-options) Swap options * `**slippageBps**` — Maximum allowed slippage, in basis points. Server default applies if omitted. * `**dexes**` — Comma-separated venue labels to **include**. See [GetVenues](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#venues) for valid labels. * `**excludeDexes**` — Comma-separated venue labels to **exclude**. * `**providers**` — Comma-separated provider IDs. See [ListProviders](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#providers) for valid IDs. * `**onlyDirectRoutes**` — `"true"` to skip multi-hop routes. Only direct swaps between input and output mint. * `**addSizeConstraint**` — `"true"` to only return quotes that fit within the transaction size limit. * `**sizeConstraint**` — Custom max transaction size in bytes. Default is set by the server (normally slightly less than 1232). * `**accountsLimitTotal**` — Max total accounts per route. Default: 64. * `**accountsLimitWritable**` — Max writable accounts per route. Default: 64. * `**transactionTemplate**` — A [`TransactionTemplate`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#transaction-template) encoded via **MessagePack then Base64**, passed as a query-string value. Reserves room in the transaction for instructions and ALTs you plan to prepend/append yourself, so Titan sizes routes to fit alongside them. **Incompatible with** `**accountsLimitTotal**`**,** `**accountsLimitWritable**`**, and** `**sizeConstraint**`**.** ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#transaction-options) Transaction options * `**feeAccount**` — Token account for collecting platform fees (base58). **Must already exist on-chain.** * `**feeBps**` — Fee amount in basis points. * `**feeFromInputMint**` — `"true"` to take fee from input mint. Default: `"false"` (fee taken from output mint). * `**closeInputTokenAccount**` — `"true"` to close the input token account as part of the transaction. * `**createOutputTokenAccount**` — `"true"` to add an idempotent ATA creation instruction. * `**outputAccount**` — Custom output token account (base58). Defaults to the user's ATA. * `**outputWsol**` — `"true"` to leave the output as **wrapped SOL** (the wSOL SPL token) instead of unwrapping it to native SOL. Default: `"false"` (output is unwrapped to native SOL). **Only has an effect when** `**outputMint**` **is wSOL** (`So11111111111111111111111111111111111111112`); ignored for any other output mint. Use it when the next step in your flow expects a wSOL token account rather than native lamports. **Requires** `**titanSwapVersion=3**`**.** * `**payer**` (base58) — Separate funder that covers the SOL-denominated costs of the swap: network fees, rent for any ATA the router creates (wSOL wrap ATA, output ATA), and the destination for the rent refund when the wSOL ATA is closed. **The payer must sign the transaction alongside the user for it to land.** **Requires** `**titanSwapVersion=3**`**.** * `**positiveSlippageFeeReceiver**` (base58) — Token account that receives any surplus when realized DEX output exceeds the quoted `outAmount`. **The skim is capped at 10 bps of** `**outAmount**` — any surplus beyond that stays with the user. **Must be a token account of the** `**outputMint**` — a wallet pubkey or wrong-mint token account fails the transaction at execution. If you want the surplus to land in a specific wallet, pass that wallet's ATA under `outputMint` (and make sure it exists before the tx runs — the router does not auto-create this account). **Requires** `**titanSwapVersion=3**`**.** ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#v3-router) V3 router * `**titanSwapVersion**` — `"3"` to opt into the V3 router. Titan returns V2 by default and will switch to V3 in a future release. See [NewSwapQuoteStream → Swap V3](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#swap-v3) for details. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#performance-options) Performance options * `**simulate**` — `"true"` (default) or `"false"`. Simulated quotes give **more reliable execution and tighter realized slippage** because the server has verified the route against current on-chain state before returning it. **Set to** `**"false"**` **to skip simulations** — significantly reduces latency by removing an RPC round-trip, at the cost of that pre-flight check. * `**maxPriceDeviationBps**` — Max allowed deviation from reference price, in basis points. Default: `1000` (10%). **Set to** `**10000**` **or higher to disable price checking entirely.** * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#simulation-and-price-checking) Simulation & price checking ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- By default, all quotes are **simulated before being returned** to verify they execute correctly against current on-chain state. This gives **more reliable execution and tighter realized slippage** — the server has already confirmed the route works with the latest account data. Setting `simulate=false` disables this — **significantly reducing latency** by removing an entire round of RPC calls, at the cost of that pre-flight check. To safeguard quotes without simulations, the server subscribes to **reference prices** for the requested tokens and checks that returned quotes are within a reasonable range. The `maxPriceDeviationBps` parameter controls this threshold: * **Default (**`**1000**` **/ 10%)** — Quotes must provide at least 90% of the expected value based on reference rates. Tuned to reject clearly bad quotes without being overly restrictive. * `**10000**` **or higher (≥ 100%)** — Price checking is **disabled entirely**. To avoid adding latency, the price check **fails open** — if the server doesn't have up-to-date price data for both tokens (e.g. the first time a particular token is quoted), quotes are passed through without checking. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#response) Response ------------------------------------------------------------------------------------------------------------------------------ **The response body is MessagePack-encoded.** Set `Accept: application/vnd.msgpack` in your request headers. The response is a [`SwapQuotes`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#stream-updates) object — **the same type returned by Titan Direct stream updates.** It contains a `quotes` map keyed by provider ID where each value is a [`SwapRoute`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#stream-updates) with instructions and address lookup tables. `**quotes**` **is a map, not an array.** Not every provider appears in every response — iterate with `Object.entries`. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#metadata.expectedwinner) `metadata.ExpectedWinner` The response includes a `metadata` object with an `ExpectedWinner` field — **this is Titan's recommendation for the best slippage-adjusted route.** Copy { "metadata": { "ExpectedWinner": "Titan-DART" }, "quotes": { ... } } Rather than sorting quotes by raw `outAmount` (which doesn't account for slippage, execution quality, or on-chain conditions), **use** `**metadata.ExpectedWinner**` **to select the route Titan expects to deliver the best actual execution.** The winner is determined by Titan's routing engine after factoring in simulation results, slippage estimates, and route reliability. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#example) Example ---------------------------------------------------------------------------------------------------------------------------- Copy import { Decoder } from '@msgpack/msgpack'; // useBigInt64 required — amounts and timestamps are u64 const decoder = new Decoder({ useBigInt64: true }); // 1 SOL → USDC swap quote const params = new URLSearchParams({ inputMint: 'So11111111111111111111111111111111111111112', // SOL outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC amount: '1000000000', // 1 SOL in lamports userPublicKey: 'YOUR_WALLET_PUBLIC_KEY', slippageBps: '50', // 0.5% slippage tolerance }); // Request swap quotes from Gateway const res = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/quote/swap?${params}`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', // Required for MessagePack response }, } ); if (!res.ok) { throw new Error(`${res.status}: ${res.statusText}`); } // Decode the MessagePack response const buffer = await res.arrayBuffer(); const quotes = decoder.decode(new Uint8Array(buffer)) as any; // Use metadata.ExpectedWinner to pick the best slippage-adjusted route const winner = quotes.metadata?.ExpectedWinner; const route = winner && quotes.quotes[winner]; if (route?.instructions?.length) { console.log(`Best route: ${winner} — ${route.outAmount} out`); // route.instructions and route.addressLookupTables are ready for transaction building } * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#error-responses) Error responses -------------------------------------------------------------------------------------------------------------------------------------------- * `**400**` — **Invalid parameters.** Malformed pubkey, missing required field, or value out of bounds. * `**401**` — **Missing or invalid authentication token.** Check your JWT and its claims. * `**404**` — **No routes found** for this swap pair. Try relaxing routing constraints (`dexes`, `excludeDexes`, `onlyDirectRoutes`). * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap#related-pages) Related pages ---------------------------------------------------------------------------------------------------------------------------------------- * [NewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) — Direct (WebSocket) equivalent with real-time streaming updates and full `SwapQuotes` / `SwapRoute` type definitions * [Quote Price](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price) — Lightweight price-only endpoint without transaction instructions * [Fee Collection](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection) — Collect platform fees on swaps using `feeAccount` and `feeBps` * [Configure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) — Venue and provider filtering strategies [PreviousTitan Gateway](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway) [NextQuote Price](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price) Last updated 8 days ago --- # Quote Price | Developer Docs | Titan **Returns a price quote without instructions or transaction data.** Use it when you need to **display prices** without the overhead of building executable transactions. The Gateway equivalent of [GetSwapPrice](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price) . Copy GET /api/v1/quote/price **Authentication** — `Authorization: Bearer ` header or `?auth=` query param. See [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#authentication) for JWT details. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price#query-parameters) Query parameters ----------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price#required) Required * `**inputMint**` — Input token mint address (base58). * `**outputMint**` — Output token mint address (base58). * `**amount**` — Amount in the smallest unit (e.g. lamports for SOL). **Not scaled by decimals.** ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price#routing-options) Routing options * `**dexes**` — Comma-separated venue labels to **include**. See [GetVenues](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#venues) for valid labels. * `**excludeDexes**` — Comma-separated venue labels to **exclude**. This endpoint **does not** accept `userPublicKey`, `feeAccount`, or any transaction-related parameters. To get executable swap data, use [Quote Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap) . * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price#response) Response ------------------------------------------------------------------------------------------------------------------------------- **The response body is MessagePack-encoded.** Set `Accept: application/vnd.msgpack` in your request headers. The response is a [`SwapPrice`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price) object — **the same type returned by the Titan Direct** `**GetSwapPrice**` **RPC method.** See [GetSwapPrice](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price) for the full type definition. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price#example) Example ----------------------------------------------------------------------------------------------------------------------------- Copy import { Decoder } from '@msgpack/msgpack'; // useBigInt64 required — amounts are u64 const decoder = new Decoder({ useBigInt64: true }); // 1 SOL → USDC price check const params = new URLSearchParams({ inputMint: 'So11111111111111111111111111111111111111112', // SOL outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC amount: '1000000000', // 1 SOL in lamports }); // Fetch price from Gateway const res = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/quote/price?${params}`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', // Required for MessagePack response }, } ); if (!res.ok) { throw new Error(`${res.status}: ${res.statusText}`); } // Decode the MessagePack response const buffer = await res.arrayBuffer(); const price = decoder.decode(new Uint8Array(buffer)) as any; console.log('Output amount:', price.amountOut); * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price#error-responses) Error responses --------------------------------------------------------------------------------------------------------------------------------------------- * `**400**` — **Invalid parameters.** Malformed pubkey, missing required field, or value out of bounds. * `**401**` — **Missing or invalid authentication token.** Check your JWT and its claims. * `**404**` — **No routes found** for this swap pair. Try relaxing routing constraints. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price#related-pages) Related pages ----------------------------------------------------------------------------------------------------------------------------------------- * [Quote Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap) — Full quote with executable transaction instructions, ready to sign and send * [GetSwapPrice](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price) — Direct (WebSocket) equivalent; returns the same `SwapPrice` type * [Configure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) — Venue filtering strategies using `dexes` and `excludeDexes` [PreviousQuote Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap) [NextInfo / Venues / Providers](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info) Last updated 2 months ago --- # Configure Routing | Developer Docs | Titan Titan routes through [Argos](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/introduction) across all available venues and providers by default. You can restrict or filter routing using the parameters below — all go into the `swap` or `transaction` object of your request. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing#routing-parameters) Routing parameters -------------------------------------------------------------------------------------------------------------------------------------- These fields are part of [`SwapParams`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) : * `**dexes**` (`string[]`) — Only route through these venues. Venues are on-chain liquidity sources — Raydium, Phoenix, Meteora, Orca, Whirlpool, PumpFun, and others. * `**excludeDexes**` (`string[]`) — Exclude these venues from routing. All other venues remain available. * `**providers**` (`string[]`) — Only use these quote providers. Providers are the quote sources that compete to give you the best price — `Titan`, `Metis`, `Okx`, and others. * `**onlyDirectRoutes**` (`bool`) — Skip multi-hop routes. Useful when you want predictable gas costs or need to avoid complex route topologies. * `**addSizeConstraint**` (`bool`) — If true, only quotes with transactions that fit within the size constraint are returned. * `**sizeConstraint**` (`u32`) — Maximum transaction size in bytes when `addSizeConstraint` is set. Default is set by the server, normally slightly less than 1232 to allow room for additional instructions like compute budgets. * `**accountsLimitTotal**` (`u16`) — Max total accounts per route. If not set, any number that still allows an executable transaction is allowed (currently 256). _Available since v1.1._ * `**accountsLimitWritable**` (`u16`) — Max writable accounts per route. If not set, any number that still allows an executable transaction is allowed (currently 64). _Available since v1.1._ Providers and venues are independent filters. Providers decide _who computes_ the route; venues decide _where liquidity is sourced_. You can combine both. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing#example-combining-multiple-filters) Example: combining multiple filters ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Titan Direct Titan Gateway Copy import WebSocket from 'ws'; import { Encoder } from '@msgpack/msgpack'; import bs58 from 'bs58'; import { zstdCompress } from 'http-encoding'; const encoder = new Encoder({ useBigInt64: true }); const url = `${process.env.TITAN_ENDPOINT}?auth=${process.env.TITAN_API_KEY}`; const ws = new WebSocket(url, [\ 'v1.api.titan.ag+zstd',\ 'v1.api.titan.ag',\ ]); let useCompression = false; let requestId = 0; ws.on('open', async () => { useCompression = ws.protocol !== 'v1.api.titan.ag'; const encoded = encoder.encode({ id: requestId++, data: { NewSwapQuoteStream: { swap: { inputMint: bs58.decode('So11111111111111111111111111111111111111112'), outputMint: bs58.decode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'), amount: 1_000_000_000n, slippageBps: 50, dexes: ['Raydium', 'Whirlpool', 'Phoenix'], // Only these venues providers: ['Titan', 'Metis'], // Only these providers onlyDirectRoutes: true, // No multi-hop addSizeConstraint: true, accountsLimitTotal: 40, }, transaction: { userPublicKey: bs58.decode('YOUR_WALLET_PUBLIC_KEY'), }, }, }, }); ws.send(useCompression ? await zstdCompress(encoded) : encoded); }); Copy import { decode } from '@msgpack/msgpack'; const params = new URLSearchParams({ inputMint: 'So11111111111111111111111111111111111111112', outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', amount: '1000000000', userPublicKey: 'YOUR_WALLET_PUBLIC_KEY', slippageBps: '50', dexes: 'Raydium,Whirlpool,Phoenix', providers: 'Titan,Metis', onlyDirectRoutes: 'true', addSizeConstraint: 'true', accountsLimitTotal: '40', }); const res = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/quote/swap?${params}`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', }, } ); const buffer = await res.arrayBuffer(); const quotes = decode(new Uint8Array(buffer)) as any; [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing#list-available-venues-and-providers) List available venues and providers ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Query the server at runtime to discover which venues and providers are currently active. Titan Direct Titan Gateway Copy // List all venues with their program IDs sendRequest({ GetVenues: { includeProgramIds: true } }); // List all active providers sendRequest({ ListProviders: {} }); Copy import { decode } from '@msgpack/msgpack'; const venuesRes = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/venues?includeProgramIds=true`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', }, } ); const venues = decode(new Uint8Array(await venuesRes.arrayBuffer())) as any; console.log('Available venues:', venues.labels); const providersRes = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/providers`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', }, } ); const providers = decode(new Uint8Array(await providersRes.arrayBuffer())) as any[]; console.log('Active providers:', providers.map((p: any) => p.id)); [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing#related-pages) Related pages ---------------------------------------------------------------------------------------------------------------------------- * [Stream & Execute a Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) — full guide with transaction building and error handling * [Fee Collection](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection) — add platform fees to swap transactions * [Types Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) — `SwapParams`, `TransactionParams`, and all type definitions * [GetVenues / ListProviders Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers) — complete response schemas [PreviousStream & Execute a Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) [NextFee Collection](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection) Last updated 2 months ago --- # Swap V2 vs Swap V3 | Developer Docs | Titan Swap V3 is the newer version of the Titan Exchange Router. V2 is the current default; V3 is opt-in via `titanSwapVersion: 3`. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/swap-v2-vs-v3#whats-new-in-v3) What's new in V3 ----------------------------------------------------------------------------------------------------------------------------- **Account handling moved inside the instruction.** Output ATA creation and wSOL wrapping/unwrapping are all handled inside the swap instruction itself. This leads to smaller transaction sizes and lower compute-unit usage. **Separate fee payer (**`**payer**`**).** A distinct account can fund all SOL-denominated costs — network fees, ATA rent (wSOL wrap, output ATA), and rent refunds — instead of the user paying them. The payer must co-sign the transaction. Defaults to the user if not set. Enables sponsored / gasless-style swap flows. **Positive-slippage capture (**`**positiveSlippageFeeReceiver**`**).** When realized output beats the quoted amount, the surplus can be skimmed to a designated account, capped at 10 bps of the output. The receiver must be an existing token account of the output mint. Anything above the cap stays with the user. **Keep output as wSOL (**`**outputWsol**`**).** When the output mint is wrapped SOL (`So11111111111111111111111111111111111111112`), the router unwraps the result to native SOL by default. Set `outputWsol: true` to leave the output as the wSOL SPL token instead — useful when the next step in your flow expects a token account rather than native lamports. Boolean, defaults to `false`. Only has an effect when `outputMint` is wSOL. Copy { "transaction": { "userPublicKey": "72neGwRAi6QWsFQjy3PkDuYBC5GNCRwC2aUMGcrkoJuP", "outputWsol": true } } [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/swap-v2-vs-v3#selecting-a-version) Selecting a version ------------------------------------------------------------------------------------------------------------------------------------ V3 is selected per request via the `titanSwapVersion` field in `TransactionParams`. Leave it unset for V2 (the default); set it to `3` to opt into V3 and unlock `payer`, `positiveSlippageFeeReceiver`, and `outputWsol`. Copy { "transaction": { "userPublicKey": "72neGwRAi6QWsFQjy3PkDuYBC5GNCRwC2aUMGcrkoJuP", "titanSwapVersion": 3 } } > `titanSwapVersion` is the integer `3`, **not** the string `"V3"`. A string is rejected with `Failed to deserialize query string: titanSwapVersion: invalid digit found in string`. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/swap-v2-vs-v3#comparison) Comparison ------------------------------------------------------------------------------------------------------------------ Swap V2 Swap V3 Status Current default Opt-in (`titanSwapVersion: 3`) ATA creation + SOL wrap/unwrap Separate instructions around the swap Handled inside the swap instruction (smaller tx, less CU) Separate fee payer No Yes (`payer`, must co-sign) Positive-slippage capture No Yes (≤ 10 bps, output-mint token account) Keep output as wSOL No Yes (`outputWsol`) [PreviousGuides](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides) [NextStream & Execute a Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) Last updated 6 days ago * [What's new in V3](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/swap-v2-vs-v3#whats-new-in-v3) * [Selecting a version](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/swap-v2-vs-v3#selecting-a-version) * [Comparison](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/swap-v2-vs-v3#comparison) --- # Transaction Template | Developer Docs | Titan When you build a swap transaction, you usually want to add instructions of your own — a compute-budget setting, a memo, a custom fee transfer, an oracle update, an app-specific log. The problem: every byte you add eats into the **1232-byte Solana transaction limit**, and the route Titan returned may no longer fit. `transactionTemplate` solves this. You tell Titan upfront what extra instructions, ALTs, and account metas will share the final transaction with the swap. Titan then sizes the route so the **assembled** transaction fits inside Solana's limits when you splice everything together. `**transactionTemplate**` **is incompatible with** `**accountsLimitTotal**`**,** `**accountsLimitWritable**`**, and** `**sizeConstraint**`**.** The template **is** the sizing constraint — passing both returns an error. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#when-to-use-it) When to use it --------------------------------------------------------------------------------------------------------------------------------- * You're prepending or appending instructions that aren't part of the swap (compute-budget settings, memos, app-specific logs, oracle pokes, custom fee transfers). * You're using your own ALTs (rebate program, fee program, app-specific routing). * You're hitting tx-size errors after combining the route with your own instructions. For everything else, the default sizing (`accountsLimitTotal` / `accountsLimitWritable`) is enough. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#pair-with-v3) Pair with V3 ----------------------------------------------------------------------------------------------------------------------------- **Use** `**titanSwapVersion: 3**` **whenever you use** `**transactionTemplate**`**.** V3 manages input and output token accounts internally, so the router does **not** insert ATA create/close instructions around the swap — the full residual byte budget goes to the route. With V2, the router still adds wSOL wrap/unwrap and ATA-creation instructions, which makes templates less predictable. `**titanSwapVersion**` **is the integer** `**3**`**, not the string** `**"V3"**`**.** Apollo rejects strings with `Failed to deserialize query string: titanSwapVersion: invalid digit found in string`. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#the-template) The template ----------------------------------------------------------------------------------------------------------------------------- See [`TransactionTemplate`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#transaction-template) for the full struct. Three fields: * `**i**` — Instructions that will sit in the final transaction **before** the swap. Include any ATA creation/deletion for the input and output mints yourself if you need them — the template doesn't assume the router will add them. (V3 doesn't need them; V2 might.) * `**a**` — ALTs the surrounding transaction already references. **Order matters** — Solana resolves ALTs greedily. Provide them in the order you'll use when compiling the message. Titan extends this array with any ALTs it uses for the swap. * `**m**` — Extra account metas that belong to the surrounding transaction but aren't reachable from any instruction in `i`. Rare — leave empty unless you need it. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#wire-format) Wire format The MessagePack wire format uses **single-letter field names** for space efficiency. Type Wire field Meaning `TransactionTemplate` `i` `instructions` (array) `TransactionTemplate` `a` `alts` (array) `TransactionTemplate` `m` `accountMetas` (array) `Instruction` `p` `programId` (32-byte pubkey) `Instruction` `a` `accounts` (array of `AccountMeta`) `Instruction` `d` `data` (raw bytes) `AccountMeta` `p` `pubkey` (32-byte pubkey) `AccountMeta` `s` `isSigner` (bool) `AccountMeta` `w` `isWritable` (bool) `AddressLookupTableAccount` `p` `key` (32-byte ALT account address) `AddressLookupTableAccount` `a` `addresses` (array of 32-byte pubkeys _inside_ the ALT, in order) **All pubkeys and instruction** `**data**` **are raw byte arrays, not Base58 or Base64 strings.** [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#rest-vs-websocket-transport) REST vs WebSocket transport ----------------------------------------------------------------------------------------------------------------------------------------------------------- The template payload is the same shape on both transports, but the wrapping is different: * **REST (Gateway):** MessagePack-encode the template, then **Base64-encode the bytes**, and pass as the `transactionTemplate` query-string value. * **WebSocket (Direct):** Embed the template **inline** inside the `swap` object of your `NewSwapQuoteStream` request. The whole frame is MessagePack already — no Base64 wrapping. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#example-v3--compute-budget-template) Example: V3 + compute-budget template ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A USDC → SOL swap on V3 with a minimal template containing only the two compute-budget instructions. This is the canonical real-world pattern. Titan Gateway (REST) Titan Direct (WebSocket) On the WebSocket transport, the whole frame is already MessagePack — embed the template **inline** in the request body, no Base64 wrapping needed. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#what-changes-in-the-route) What changes in the route ------------------------------------------------------------------------------------------------------------------------------------------------------- Without a template, Titan sizes routes assuming the swap is the only thing in the transaction — up to the server's defaults (currently 1168 bytes, 64 accounts). With a template, Titan **subtracts the template's footprint** from those budgets before choosing a route: * A compute-budget template (14 bytes, 0 accounts) barely shifts routing — V3 routes usually return as a single instruction with the ALTs the router would have used anyway. * A larger template (custom program calls, multiple ALTs, many account metas) pushes the router toward shorter routes — fewer hops, fewer venues — to leave room. Providers that can't fit a route within the remaining budget are silently dropped from the response. * If no provider can fit a route, you get a 404 (Gateway) or an empty `quotes` map (Direct). [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#pitfalls) Pitfalls --------------------------------------------------------------------------------------------------------------------- * **Don't pair with** `**accountsLimitTotal**` **/** `**accountsLimitWritable**` **/** `**sizeConstraint**`**.** The template replaces them. Passing both returns 400. * `**titanSwapVersion**` **is integer** `**3**`**, not string** `**"V3"**`**.** Strings get rejected with `invalid digit found in string`. * **Use wire-format field names.** Long-form names (`programId`, `accounts`, etc.) return `400 Bad Request: missing field 'p'`. * **Splice the template instructions BEFORE the route instructions** when building the final v0 message. The template represents what the surrounding transaction looks like; the swap sits after it. * **ALT order is load-bearing.** Solana resolves ALTs greedily; the first ALT containing an account wins. If your custom ALT and a Titan ALT both contain the same account, ordering decides which gets used. * **Encode binary as bytes, not Base58.** Inside the MessagePack-encoded template, pubkeys and instruction `data` are raw bytes (msgpack `bin`) — don't pre-encode them to strings. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#related-pages) Related pages ------------------------------------------------------------------------------------------------------------------------------- * [NewSwapQuoteStream → Transaction Template](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#transaction-template) — type definition * [NewSwapQuoteStream → Swap V3](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#swap-v3) — V3 router details * [Quote Swap (Gateway)](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap) — Gateway swap reference * [Stream & Execute a Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) — full transaction-building walkthrough * [Configure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) — `accountsLimitTotal`, `accountsLimitWritable`, and other size controls [PreviousFee Collection](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection) [NextError Handling & Reconnect](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling) Last updated 20 days ago * [When to use it](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#when-to-use-it) * [Pair with V3](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#pair-with-v3) * [The template](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#the-template) * [Wire format](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#wire-format) * [REST vs WebSocket transport](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#rest-vs-websocket-transport) * [Example: V3 + compute-budget template](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#example-v3--compute-budget-template) * [What changes in the route](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#what-changes-in-the-route) * [Pitfalls](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#pitfalls) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template#related-pages) Copy import { Encoder, decode } from '@msgpack/msgpack'; import bs58 from 'bs58'; import { Connection, MessageV0, PublicKey, TransactionInstruction, VersionedTransaction, } from '@solana/web3.js'; const encoder = new Encoder({ useBigInt64: true }); // --- Step 1: build the two compute-budget instructions --- const CB_PROGRAM_ID = new PublicKey('ComputeBudget111111111111111111111111111111'); function setComputeUnitLimitData(units: number): Uint8Array { // Discriminator 0x02 + u32 LE const data = new Uint8Array(5); data[0] = 0x02; new DataView(data.buffer).setUint32(1, units, true); return data; } function setComputeUnitPriceData(microLamports: bigint): Uint8Array { // Discriminator 0x03 + u64 LE const data = new Uint8Array(9); data[0] = 0x03; new DataView(data.buffer).setBigUint64(1, microLamports, true); return data; } // --- Step 2: assemble the TransactionTemplate using wire-format field names --- const template = { i: [\ { p: CB_PROGRAM_ID.toBytes(), a: [], d: setComputeUnitLimitData(1_400_000) },\ { p: CB_PROGRAM_ID.toBytes(), a: [], d: setComputeUnitPriceData(0n) }, // sub real priority fee in prod\ ], a: [], m: [], }; // --- Step 3: MessagePack-encode, then Base64-encode --- const transactionTemplate = Buffer.from(encoder.encode(template)).toString('base64'); // --- Step 4: send the quote request --- const USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; const SOL = 'So11111111111111111111111111111111111111112'; const USER = 'Affd7LDkUY9fjWjjQSr9bvises1Cku4WSwdLNGBhgVW3'; const params = new URLSearchParams({ inputMint: USDC, outputMint: SOL, amount: '100000000', // 100 USDC userPublicKey: USER, slippageBps: '50', titanSwapVersion: '3', // integer 3, not "V3" simulate: 'false', transactionTemplate, }); const res = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/quote/swap?${params}`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', }, } ); const quotes = decode(new Uint8Array(await res.arrayBuffer())) as any; const winner = quotes.metadata?.ExpectedWinner; const route = winner && quotes.quotes[winner]; // --- Step 5: assemble [templateInstructions, ...routeInstructions] --- function titanIxToTransactionIx(ix: any): TransactionInstruction { return new TransactionInstruction({ programId: new PublicKey(ix.p), data: Buffer.from(ix.d), keys: ix.a.map((a: any) => ({ pubkey: new PublicKey(a.p), isSigner: a.s, isWritable: a.w, })), }); } const templateIxs = template.i.map(titanIxToTransactionIx); const swapIxs = route.instructions.map(titanIxToTransactionIx); const allIxs = [...templateIxs, ...swapIxs]; // Compile into a v0 message with the route's ALTs, sign and send Copy import WebSocket from 'ws'; import { Encoder, decode } from '@msgpack/msgpack'; import { PublicKey } from '@solana/web3.js'; const encoder = new Encoder({ useBigInt64: true }); const CB_PROGRAM_ID = new PublicKey('ComputeBudget111111111111111111111111111111'); function setComputeUnitLimitData(units: number) { const data = new Uint8Array(5); data[0] = 0x02; new DataView(data.buffer).setUint32(1, units, true); return data; } function setComputeUnitPriceData(microLamports: bigint) { const data = new Uint8Array(9); data[0] = 0x03; new DataView(data.buffer).setBigUint64(1, microLamports, true); return data; } const template = { i: [\ { p: CB_PROGRAM_ID.toBytes(), a: [], d: setComputeUnitLimitData(1_400_000) },\ { p: CB_PROGRAM_ID.toBytes(), a: [], d: setComputeUnitPriceData(0n) },\ ], a: [], m: [], }; const ws = new WebSocket( `${process.env.TITAN_WS_ENDPOINT}/api/v1/ws`, ['v1.api.titan.ag'], { headers: { Authorization: `Bearer ${process.env.TITAN_API_KEY}` } }, ); ws.on('open', () => { ws.send(encoder.encode({ id: 1, data: { NewSwapQuoteStream: { swap: { inputMint: new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v').toBytes(), outputMint: new PublicKey('So11111111111111111111111111111111111111112').toBytes(), amount: 100_000_000n, slippageBps: 50, providers: ['Metis', 'Titan'], transactionTemplate: template, // inline, no Base64 }, transaction: { userPublicKey: new PublicKey('Affd7LDkUY9fjWjjQSr9bvises1Cku4WSwdLNGBhgVW3').toBytes(), titanSwapVersion: 3, // integer 3 }, update: { intervalMs: 60_000, numQuotes: 1 }, }, }, })); }); ws.on('message', (raw) => { const msg = decode(raw as Uint8Array) as any; if ('StreamData' in msg && 'SwapQuotes' in msg.StreamData.payload) { const quotes = msg.StreamData.payload.SwapQuotes; const winner = quotes.metadata?.ExpectedWinner; const route = winner && quotes.quotes[winner]; // Assemble [template.i, ...route.instructions] as in the REST tab } }); --- # Fee Collection | Developer Docs | Titan If you're building a product on top of Titan, you can collect a fee on every swap. Fees are deducted from the swap output (or input) and sent to a token account you control. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#how-fees-work) How fees work ------------------------------------------------------------------------------------------------------------------------- The fee is taken from the **output token** by default. If you'd rather take the fee from the input side, set `feeFromInputMint: true`. Your fee account must be a token account for the correct mint — output mint by default, or input mint when `feeFromInputMint` is true. This account must already exist, or you must add the ATA creation instruction yourself. When fees are active, every [`SwapRoute`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) in the quote response includes a `platformFee` field with the exact fee amount and rate. Show this to your users before they sign. These fields are part of [`TransactionParams`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) : * `**feeAccount**` (`Pubkey`) — ATA to receive the fee. Must already exist on-chain, or you must add the ATA creation instruction yourself. * `**feeBps**` (`u16`) — Fee rate in basis points (1 bps = 0.01%). If not specified, the default fee for your account is used. * `**feeFromInputMint**` (`bool`) — If `true`, fee is taken from the input mint. Default `false`. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#collect-fees-on-output-token-default) Collect fees on output token (default) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Create an ATA for the output mint before your first request, then pass `feeAccount` and `feeBps` in your transaction parameters. Titan Direct Titan Gateway Copy import WebSocket from 'ws'; import { Encoder, Decoder } from '@msgpack/msgpack'; import bs58 from 'bs58'; import { zstdCompress, zstdDecompress } from 'http-encoding'; const encoder = new Encoder({ useBigInt64: true }); const decoder = new Decoder({ useBigInt64: true }); const url = `${process.env.TITAN_ENDPOINT}?auth=${process.env.TITAN_API_KEY}`; const ws = new WebSocket(url, [\ 'v1.api.titan.ag+zstd',\ 'v1.api.titan.ag',\ ]); const SOL = bs58.decode('So11111111111111111111111111111111111111112'); const USDC = bs58.decode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); const userPublicKey = bs58.decode('YOUR_WALLET_PUBLIC_KEY'); // Your ATA for the output mint (USDC in this case) const feeAccount = bs58.decode('YOUR_USDC_FEE_ATA'); let useCompression = false; let requestId = 0; ws.on('open', async () => { useCompression = ws.protocol !== 'v1.api.titan.ag'; const id = requestId++; const encoded = encoder.encode({ id, data: { NewSwapQuoteStream: { swap: { inputMint: SOL, outputMint: USDC, amount: 1_000_000_000n, // 1 SOL slippageBps: 50, }, transaction: { userPublicKey, feeAccount, feeBps: 100, // 1% fee }, }, }, }); ws.send(useCompression ? await zstdCompress(encoded) : encoded); }); [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#collect-fees-on-input-token) Collect fees on input token ----------------------------------------------------------------------------------------------------------------------------------------------------- Set `feeFromInputMint: true` and make sure your fee account is an ATA for the **input** mint instead of the output mint. Titan Direct Titan Gateway [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#read-the-fee-from-quote-response) Read the fee from quote response --------------------------------------------------------------------------------------------------------------------------------------------------------------- Every [`SwapRoute`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) that includes a fee has a `platformFee` object. Check it before your user signs — this is what you should display in your UI. The [`PlatformFee`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) type: * `**amount**` (`u64`) — Absolute fee amount in the token's smallest unit. * `**fee_bps**` (`u8`) — Fee rate in basis points. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#important-notes) Important notes ----------------------------------------------------------------------------------------------------------------------------- Only validated users can specify a `feeAccount`. Contact the Titan team to get your account approved for fee collection. The fee is taken **from** the swap amount, not added on top. If a user swaps 1 SOL and the fee is 1%, the user receives the output for 0.99 SOL worth of input (when `feeFromInputMint` is true) or gets 1% less output (when fees are taken from the output side, the default). [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#related-pages) Related pages ------------------------------------------------------------------------------------------------------------------------- * [Stream & Execute a Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) — full guide with transaction building, signing, and error handling * [Configure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) — filter venues and providers * [Types Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) — `SwapRoute`, `PlatformFee`, `TransactionParams`, and all type definitions * [Wire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) — MessagePack encoding and compression [PreviousConfigure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) [NextTransaction Template](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template) Last updated 2 months ago * [How fees work](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#how-fees-work) * [Collect fees on output token (default)](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#collect-fees-on-output-token-default) * [Collect fees on input token](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#collect-fees-on-input-token) * [Read the fee from quote response](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#read-the-fee-from-quote-response) * [Important notes](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#important-notes) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection#related-pages) Copy import { decode } from '@msgpack/msgpack'; const SOL = 'So11111111111111111111111111111111111111112'; const USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; const params = new URLSearchParams({ inputMint: SOL, outputMint: USDC, amount: '1000000000', userPublicKey: 'YOUR_WALLET_PUBLIC_KEY', slippageBps: '50', feeAccount: 'YOUR_USDC_FEE_ATA', // ATA for the output mint feeBps: '100', // 1% fee }); const res = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/quote/swap?${params}`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', }, } ); const buffer = await res.arrayBuffer(); const quotes = decode(new Uint8Array(buffer)) as any; Copy import WebSocket from 'ws'; import { Encoder, Decoder } from '@msgpack/msgpack'; import bs58 from 'bs58'; import { zstdCompress, zstdDecompress } from 'http-encoding'; const encoder = new Encoder({ useBigInt64: true }); const decoder = new Decoder({ useBigInt64: true }); const url = `${process.env.TITAN_ENDPOINT}?auth=${process.env.TITAN_API_KEY}`; const ws = new WebSocket(url, [\ 'v1.api.titan.ag+zstd',\ 'v1.api.titan.ag',\ ]); const SOL = bs58.decode('So11111111111111111111111111111111111111112'); const USDC = bs58.decode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); const userPublicKey = bs58.decode('YOUR_WALLET_PUBLIC_KEY'); // Fee from input — ATA must be for SOL (wrapped SOL), not USDC const feeAccount = bs58.decode('YOUR_SOL_FEE_ATA'); let useCompression = false; let requestId = 0; ws.on('open', async () => { useCompression = ws.protocol !== 'v1.api.titan.ag'; const id = requestId++; const encoded = encoder.encode({ id, data: { NewSwapQuoteStream: { swap: { inputMint: SOL, outputMint: USDC, amount: 1_000_000_000n, slippageBps: 50, }, transaction: { userPublicKey, feeAccount, feeBps: 50, // 0.5% fee feeFromInputMint: true, }, }, }, }); ws.send(useCompression ? await zstdCompress(encoded) : encoded); }); Copy import { decode } from '@msgpack/msgpack'; const SOL = 'So11111111111111111111111111111111111111112'; const USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'; const params = new URLSearchParams({ inputMint: SOL, outputMint: USDC, amount: '1000000000', userPublicKey: 'YOUR_WALLET_PUBLIC_KEY', slippageBps: '50', feeAccount: 'YOUR_SOL_FEE_ATA', feeBps: '50', feeFromInputMint: 'true', }); const res = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/quote/swap?${params}`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', }, } ); const buffer = await res.arrayBuffer(); const quotes = decode(new Uint8Array(buffer)) as any; Copy const best = Object.values(quotes.quotes as Record) .reduce((a: any, b: any) => BigInt(b.outAmount) > BigInt(a.outAmount) ? b : a); if (best.platformFee) { const feeAmount = BigInt(best.platformFee.amount); const fee_bps = best.platformFee.fee_bps; console.log(`Platform fee: ${feeAmount} tokens (${fee_bps} bps)`); // Example: "Platform fee: 1428570 tokens (100 bps)" } // Show the fee to your user before they sign console.log(`Output after fee: ${best.outAmount}`); --- # Error Handling & Reconnect | Developer Docs | Titan Titan Direct is a persistent WebSocket connection. Connections drop, tokens expire, and streams end unexpectedly. This guide covers every failure mode and how to build a reconnect loop that keeps your integration running. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#server-messages) Server messages ----------------------------------------------------------------------------------------------------------------------------- The server sends one of four message types — `Response`, `Error`, `StreamData`, or `StreamEnd`. See [Types Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) for the full type definitions. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#server-errors) Server errors ------------------------------------------------------------------------------------------------------------------------- When a request fails, the server sends an [`Error`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) instead of a `Response`. Check for the `Error` key in every message handler: Copy ws.on('message', async (raw: Buffer) => { const msg = await decodeMessage(raw); if ('Error' in msg) { const { code, message, requestId } = msg.Error; console.error(`Request ${requestId} failed — code ${code}: ${message}`); return; } }); [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#stream-errors) Stream errors ------------------------------------------------------------------------------------------------------------------------- A stream can end abnormally. [`StreamEnd`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) carries an optional `errorCode` and `errorMessage` — if present, the stream did not terminate cleanly: [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#connection-drops) Connection drops ------------------------------------------------------------------------------------------------------------------------------- When the WebSocket closes, all active streams are dead. Listen for the `close` event and trigger your reconnect logic: [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#token-expiry) Token expiry ----------------------------------------------------------------------------------------------------------------------- The server refuses connections where the JWT `exp` claim is in the past. If your connection is rejected immediately, check that your token is still valid before reconnecting: Refresh your token before calling `connect()` if it's close to expiry. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#reconnect-with-exponential-backoff) Reconnect with exponential backoff ------------------------------------------------------------------------------------------------------------------------------------------------------------------- The SDK has no built-in reconnect — it's your responsibility. Here's a complete reconnect loop: Stream IDs do not survive reconnects. After reconnecting, you must open a new stream — the previous stream ID is no longer valid. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#best-practices) Best practices --------------------------------------------------------------------------------------------------------------------------- * Call [`GetInfo`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) after every reconnect to confirm the server is reachable before opening streams. * If a route has `expiresAtMs` or `expiresAfterSlot` set, check these before building a transaction — a quote valid when received can go stale by the time it lands on-chain. * Keep your reconnect loop separate from your quote processing logic so a stream error doesn't silently kill the reconnect handler. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#related-pages) Related pages ------------------------------------------------------------------------------------------------------------------------- * [Stream & Execute a Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) — full guide with transaction building and error handling * [Error Codes](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes) — numeric error code reference * [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) — protocol negotiation details * [Types Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) — `ServerMessage`, `ResponseError`, `StreamEnd`, and all type definitions [PreviousTransaction Template](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template) [NextAPI Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference) Last updated 2 months ago * [Server messages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#server-messages) * [Server errors](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#server-errors) * [Stream errors](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#stream-errors) * [Connection drops](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#connection-drops) * [Token expiry](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#token-expiry) * [Reconnect with exponential backoff](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#reconnect-with-exponential-backoff) * [Best practices](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#best-practices) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling#related-pages) Copy ws.on('message', async (raw: Buffer) => { const msg = await decodeMessage(raw); if ('StreamEnd' in msg) { const { id, errorCode, errorMessage } = msg.StreamEnd; if (errorCode !== undefined) { console.error(`Stream ${id} ended with error ${errorCode}: ${errorMessage}`); // Restart the stream or reconnect } else { console.log(`Stream ${id} ended cleanly`); } } }); Copy ws.on('close', (code: number, reason: Buffer) => { console.warn(`Connection closed — code: ${code}, reason: ${reason.toString()}`); if (code !== 1000) { // Abnormal close — reconnect scheduleReconnect(); } }); ws.on('error', (err: Error) => { console.error('WebSocket error:', err.message); // 'close' will fire after this }); Copy function isTokenExpired(token: string): boolean { const [, payload] = token.split('.'); const claims = JSON.parse(Buffer.from(payload, 'base64').toString()); return Date.now() / 1000 > claims.exp; } Copy import WebSocket from 'ws'; import { Encoder, Decoder } from '@msgpack/msgpack'; import bs58 from 'bs58'; import { zstdCompress, zstdDecompress } from 'http-encoding'; const encoder = new Encoder({ useBigInt64: true }); const decoder = new Decoder({ useBigInt64: true }); const BASE_DELAY_MS = 1_000; const MAX_DELAY_MS = 30_000; let useCompression = false; async function sendRequest(ws: WebSocket, id: number, data: Record) { const encoded = encoder.encode({ id, data }); ws.send(useCompression ? await zstdCompress(encoded) : encoded); } async function decodeMessage(raw: Buffer): Promise { const data = useCompression ? await zstdDecompress(raw) : raw; return decoder.decode(data); } async function connect(): Promise { const url = `${process.env.TITAN_ENDPOINT}?auth=${process.env.TITAN_API_KEY}`; return new Promise((resolve, reject) => { const ws = new WebSocket(url, [\ 'v1.api.titan.ag+zstd',\ 'v1.api.titan.ag',\ ]); ws.once('open', () => { useCompression = ws.protocol !== 'v1.api.titan.ag'; resolve(ws); }); ws.once('error', reject); }); } async function runWithReconnect() { let attempt = 0; while (true) { try { const ws = await connect(); console.log('Connected'); attempt = 0; // reset backoff on success // Set up your message handler and streams here await setupStreams(ws); // Wait for connection to close await new Promise((resolve) => ws.once('close', resolve)); } catch (err) { attempt++; const delay = Math.min(BASE_DELAY_MS * 2 ** (attempt - 1), MAX_DELAY_MS); console.warn(`Reconnect attempt ${attempt} in ${delay}ms...`); await new Promise((resolve) => setTimeout(resolve, delay)); } } } async function setupStreams(ws: WebSocket) { let requestId = 0; // Call GetInfo first to confirm connection sendRequest(ws, requestId++, { GetInfo: {} }); ws.on('message', async (raw: Buffer) => { const msg = await decodeMessage(raw); if ('Response' in msg && 'GetInfo' in msg.Response.data) { // Connection confirmed — open your streams openQuoteStream(ws, requestId++); } if ('Error' in msg) { console.error(`Error ${msg.Error.code}: ${msg.Error.message}`); } if ('StreamEnd' in msg && msg.StreamEnd.errorCode !== undefined) { console.error(`Stream error: ${msg.StreamEnd.errorMessage}`); ws.close(); // trigger reconnect } }); } async function openQuoteStream(ws: WebSocket, id: number) { const SOL = bs58.decode('So11111111111111111111111111111111111111112'); const USDC = bs58.decode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); sendRequest(ws, id, { NewSwapQuoteStream: { swap: { inputMint: SOL, outputMint: USDC, amount: 1_000_000_000n, slippageBps: 50, }, transaction: { userPublicKey: bs58.decode('YOUR_WALLET_PUBLIC_KEY'), }, }, }); } runWithReconnect(); --- # Titan Direct | Developer Docs | Titan **Built for traders who can't afford stale quotes.** Titan Direct is a persistent WebSocket connection that streams live swap quotes as on-chain state changes. All messages are binary frames encoded with [MessagePack](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) . [PreviousTitan Direct vs Titan Gateway](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway) [NextConnection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) Last updated 2 months ago --- # GetInfo | Developer Docs | Titan `**GetInfo**` **returns the server's protocol version and the default/min/max values for all configurable settings.** Call it after connecting to confirm the server is reachable and to read the bounds you'll need for stream configuration. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info#request) Request ----------------------------------------------------------------------------------------------------------------- `GetInfoRequest` is an empty object — no parameters. The server ignores any unknown fields. Copy // Empty request — no parameters needed await sendRequest(ws, requestId++, { GetInfo: {} }); See [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#sending-a-request) for `sendRequest` and `decodeMessage` setup. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info#response) Response ------------------------------------------------------------------------------------------------------------------- The server responds with a [`ServerInfo`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) object containing the protocol version and all server settings with their defaults and bounds. Copy ws.on('message', async (raw: Buffer) => { const msg = await decodeMessage(raw); if ('Response' in msg && 'GetInfo' in msg.Response.data) { const info = msg.Response.data.GetInfo; // Protocol version — major changes are backwards-incompatible console.log('Protocol version:', info.protocolVersion); // { major: 1, minor: 2, patch: 0 } // Quote stream settings — use these bounds when configuring NewSwapQuoteStream console.log('Update interval — min/max/default (ms):', info.settings.quoteUpdate.intervalMs.min, info.settings.quoteUpdate.intervalMs.max, info.settings.quoteUpdate.intervalMs.default, ); console.log('Max quotes per update — default:', info.settings.quoteUpdate.numQuotes.default ); // How many streams you can open simultaneously on this connection console.log('Concurrent streams allowed:', info.settings.connection.concurrentStreams ); } }); [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info#serverinfo) ServerInfo ----------------------------------------------------------------------------------------------------------------------- Rust TypeScript [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info#related-pages) Related pages ----------------------------------------------------------------------------------------------------------------------------- * [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) — WebSocket setup, authentication, and the `sendRequest`/`decodeMessage` helpers used above * [NewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) — open a streaming swap quote using the settings from GetInfo * [Wire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) — MessagePack encoding and serialization details [PreviousConnection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) [NextNewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) Last updated 2 months ago * [Request](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info#request) * [Response](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info#response) * [ServerInfo](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info#serverinfo) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info#related-pages) Copy struct ServerInfo { /// Server protocol version information. protocolVersion: VersionInfo, /// Server settings and parameter bounds. settings: ServerSettings, } struct VersionInfo { /// Major version — incremented for backwards-incompatible changes. major: u16, /// Minor version — incremented for backwards-compatible changes. minor: u16, /// Patch version — informational, no data format changes. patch: u16, } struct ServerSettings { /// Settings and parameter bounds for quote updates. quoteUpdate: QuoteUpdateSettings, /// Settings and parameter bounds for swaps. swap: SwapSettings, /// Settings and parameter bounds for transaction generation. transaction: TransactionSettings, /// Settings and limits for the connection. connection: ConnectionSettings, } struct BoundedValueWithDefault { /// Minimum allowed value. min: T, /// Maximum allowed value. max: T, /// Default value when not specified in request. default: T, } struct QuoteUpdateSettings { /// Bounds and default for the `intervalMs` parameter. intervalMs: BoundedValueWithDefault, /// Bounds and default for the `numQuotes` parameter. numQuotes: BoundedValueWithDefault, } struct SwapSettings { /// Default and bounds for `slippageBps`. slippageBps: BoundedValueWithDefault, /// Default value for `onlyDirectRoutes`. onlyDirectRoutes: bool, /// Default value for `addSizeConstraint`. addSizeConstraint: bool, } struct TransactionSettings { /// Default value for `closeInputTokenAccount`. closeInputTokenAccount: bool, /// Default value for `createOutputTokenAccount`. createOutputTokenAccount: bool, } struct ConnectionSettings { /// Number of concurrent streams the user is allowed. concurrentStreams: u32, } Copy interface ServerInfo { // Server protocol version information. protocolVersion: VersionInfo; // Server settings and parameter bounds. settings: ServerSettings; } interface VersionInfo { // Major version — incremented for backwards-incompatible changes. major: number; // Minor version — incremented for backwards-compatible changes. minor: number; // Patch version — informational, no data format changes. patch: number; } interface ServerSettings { // Settings and parameter bounds for quote updates. quoteUpdate: QuoteUpdateSettings; // Settings and parameter bounds for swaps. swap: SwapSettings; // Settings and parameter bounds for transaction generation. transaction: TransactionSettings; // Settings and limits for the connection. connection: ConnectionSettings; } interface QuoteUpdateSettings { // Bounds and default for `intervalMs` parameter. intervalMs: { min: number; max: number; default: number }; // Bounds and default for `numQuotes` parameter. numQuotes: { min: number; max: number; default: number }; } interface SwapSettings { // Default and bounds for `slippageBps`. slippageBps: { min: number; max: number; default: number }; // Default value for `onlyDirectRoutes`. onlyDirectRoutes: boolean; // Default value for `addSizeConstraint`. addSizeConstraint: boolean; } interface TransactionSettings { // Default value for `closeInputTokenAccount`. closeInputTokenAccount: boolean; // Default value for `createOutputTokenAccount`. createOutputTokenAccount: boolean; } interface ConnectionSettings { // Number of concurrent streams the user is allowed. concurrentStreams: number; } --- # Stream & Execute a Swap | Developer Docs | Titan This guide covers **Titan Direct** — the WebSocket path. For a single-request flow using Titan Gateway, see the [Quickstart](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart) . It walks through the complete lifecycle — connecting over WebSocket, streaming live quotes, picking the best one, building and signing a transaction, then shutting down cleanly. This guide uses raw WebSocket and MessagePack directly. If you prefer a higher-level interface, see the [`@titanexchange/sdk-ts`](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk) SDK. You need an API token and endpoint URL before starting. See [Get API Access](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/api-access) if you don't have one yet. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute#prerequisites) Prerequisites ----------------------------------------------------------------------------------------------------------------------------- Copy npm install ws @msgpack/msgpack bs58 @solana/web3.js http-encoding Set your environment variables: Copy export TITAN_ENDPOINT="wss://YOUR_ENDPOINT/api/v1/ws" export TITAN_API_KEY="YOUR_API_TOKEN" export SOLANA_RPC_URL="https://YOUR_RPC_ENDPOINT" * * * 1 **Connect and negotiate the protocol** Titan Direct uses [MessagePack](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) over WebSocket. List your supported compression schemes in the [`Sec-WebSocket-Protocol`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) header — the server selects the best match and confirms it on open. Copy import WebSocket from 'ws'; import { Encoder, Decoder } from '@msgpack/msgpack'; import bs58 from 'bs58'; import { zstdCompress, zstdDecompress, brotliCompress, brotliDecompress, gzipCompress, gzipDecompress, } from 'http-encoding'; // useBigInt64 ensures amounts encode as int64, not float64 const encoder = new Encoder({ useBigInt64: true }); const decoder = new Decoder({ useBigInt64: true }); // Build the WebSocket URL with auth token as query param const url = `${process.env.TITAN_ENDPOINT}?auth=${process.env.TITAN_API_KEY}`; // List supported protocols in preference order — server picks the best match // zstd gives the best compression ratio, fallback to brotli, gzip, or none const ws = new WebSocket(url, [\ 'v1.api.titan.ag+zstd', // preferred — best ratio + speed\ 'v1.api.titan.ag+brotli', // fallback\ 'v1.api.titan.ag+gzip', // fallback\ 'v1.api.titan.ag', // no compression\ ]); // Compress/decompress default to identity (no-op) — overwritten on open let compress: (data: Uint8Array) => Promise | Uint8Array = (d) => d; let decompress: (data: Uint8Array) => Promise | Uint8Array = (d) => d; let requestId = 0; ws.on('open', () => { // The server confirms which protocol it selected via ws.protocol const proto = ws.protocol; console.log('Connected — protocol:', proto); // Match the negotiated protocol to the correct codec if (proto.endsWith('+zstd')) { compress = zstdCompress; decompress = zstdDecompress; } else if (proto.endsWith('+brotli')) { compress = brotliCompress; decompress = brotliDecompress; } else if (proto.endsWith('+gzip')) { compress = gzipCompress; decompress = gzipDecompress; } // If none matched, no compression — identity functions stay in place }); // Encode a request as MessagePack, compress, and send async function sendRequest(data: Record): Promise { const id = requestId++; const encoded = encoder.encode({ id, data }); ws.send(await compress(encoded)); return id; } // Decompress an incoming binary frame and decode from MessagePack async function decodeMessage(raw: Buffer): Promise { const data = await decompress(raw); return decoder.decode(data); } ws.on('error', (err) => { console.error('WebSocket error:', err.message); }); 2 **Call GetInfo** Send [`GetInfo`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) right after connecting to confirm the connection and read the server's current defaults — update interval, slippage bounds, and stream limits. Copy ws.on('open', () => { sendRequest({ GetInfo: {} }); }); ws.on('message', async (raw: Buffer) => { const msg = await decodeMessage(raw); if ('Response' in msg && 'GetInfo' in msg.Response.data) { const info = msg.Response.data.GetInfo; console.log('Protocol version:', info.protocolVersion); console.log('Default update interval:', info.settings.quoteUpdate.intervalMs.default, 'ms'); } }); 3 **Open a quote stream** Send [`NewSwapQuoteStream`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) to start receiving live quotes. The `swap` object defines what to quote, `transaction` provides the wallet context needed to build executable instructions. Copy const SOL = bs58.decode('So11111111111111111111111111111111111111112'); const USDC = bs58.decode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); const userPublicKey = bs58.decode('YOUR_WALLET_PUBLIC_KEY'); sendRequest({ NewSwapQuoteStream: { swap: { inputMint: SOL, outputMint: USDC, amount: 1_000_000_000n, // 1 SOL in lamports slippageBps: 50, }, transaction: { userPublicKey, }, }, }); The server responds with a `stream.id` — save it to stop the stream later. Use `BigInt` for `amount`. Numbers above 2^32 encode as float64 in MessagePack, which the server rejects. 4 **Read quotes and pick the best** The server pushes [`StreamData`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) messages at the negotiated interval. Each update includes `metadata.ExpectedWinner` — **Titan's recommendation for the best slippage-adjusted route.** Copy let streamId: number | undefined; ws.on('message', async (raw: Buffer) => { const msg = await decodeMessage(raw); if ('Response' in msg && 'NewSwapQuoteStream' in msg.Response.data) { streamId = msg.Response.stream.id; console.log(`Stream ${streamId} open`); return; } if ('StreamData' in msg) { const swapQuotes = msg.StreamData.payload.SwapQuotes; // Use metadata.ExpectedWinner for the best slippage-adjusted route const winner = swapQuotes.metadata?.ExpectedWinner; const bestRoute = winner && swapQuotes.quotes[winner]; if (bestRoute?.instructions?.length) { console.log(`Best: ${winner} — ${bestRoute.outAmount} out`); } } }); 5 **Build, sign, and send** Each quote returns `instructions` and `addressLookupTables` as part of the [`SwapRoute`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) type. Fetch the ALT accounts, compile a V0 message, sign, and send. Use `computeUnitsSafe` for your compute budget — it accounts for on-chain variance and gives your transaction room to land without failing on a slightly heavier slot. Copy import { Connection, VersionedTransaction, TransactionMessage, AddressLookupTableAccount, TransactionInstruction, PublicKey, } from '@solana/web3.js'; const connection = new Connection(process.env.SOLANA_RPC_URL!); function toSolanaInstruction(ix: any): TransactionInstruction { return new TransactionInstruction({ programId: new PublicKey(ix.p), keys: ix.a.map((acc: any) => ({ pubkey: new PublicKey(acc.p), isSigner: acc.s, isWritable: acc.w, })), data: Buffer.from(ix.d), }); } async function executeQuote(route: any): Promise { const altAccounts: AddressLookupTableAccount[] = []; for (const altPubkey of (route.addressLookupTables ?? [])) { const { value } = await connection.getAddressLookupTable(new PublicKey(altPubkey)); if (value) altAccounts.push(value); } const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash(); const message = new TransactionMessage({ payerKey: new PublicKey(userPublicKey), recentBlockhash: blockhash, instructions: route.instructions.map(toSolanaInstruction), }).compileToV0Message(altAccounts); const tx = new VersionedTransaction(message); // Sign the transaction — use your wallet adapter or Keypair // Client-side: const signed = await signTransaction(tx); // Server-side: tx.sign([keypair]); try { const sig = await connection.sendRawTransaction(tx.serialize()); await connection.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }); console.log('Confirmed:', sig); if (streamId !== undefined) { sendRequest({ StopStream: { id: streamId } }); } } catch (err: any) { console.error('Send failed:', err.message); } } If a route expires, `expiresAtMs` contains the expiry as a millisecond UNIX timestamp and `expiresAfterSlot` contains the last slot at which the route is valid. If present, check these before executing — a route may no longer be valid by the time your transaction lands on-chain. 6 **Stop the stream** Once you've executed, send [`StopStream`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream) to free up the connection for other streams. Copy sendRequest({ StopStream: { id: streamId! } }); 7 **Handle StreamEnd and errors** Copy ws.on('message', async (raw: Buffer) => { const msg = await decodeMessage(raw); if ('Error' in msg) { console.error(`Request ${msg.Error.requestId} failed [${msg.Error.code}]: ${msg.Error.message}`); } if ('StreamEnd' in msg) { const { id, errorCode, errorMessage } = msg.StreamEnd; if (errorCode) { console.error(`Stream ${id} error ${errorCode}: ${errorMessage}`); } else { console.log(`Stream ${id} closed`); } ws.close(); } }); For reconnect patterns see [Error Handling & Reconnect](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling) . * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute#key-details) Key details ------------------------------------------------------------------------------------------------------------------------- * `**quotes**` **shape** — `Record` keyed by provider ID, not an array. * **Transaction building** — Build a V0 transaction from `instructions` + `addressLookupTables`. * **Compute budget** — Use `computeUnitsSafe` — accounts for on-chain variance. * **Quote expiry** — If a route expires, `expiresAtMs` and `expiresAfterSlot` will be set. Check these before executing. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute#related-pages) Related pages ----------------------------------------------------------------------------------------------------------------------------- * [Configure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) — filter venues and providers * [Error Handling & Reconnect](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling) — error codes and reconnect patterns * [Wire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) — MessagePack encoding and compression * [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) — protocol negotiation details * [Types Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) — `SwapRoute`, `StreamData`, and all type definitions * [NewSwapQuoteStream Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) * [CPI Example (Anchor)](https://github.com/Titan-Pathfinder/titan-v2-cpi-example) — Example Anchor program demonstrating cross-program invocation into Titan's `swap_route_v2` instruction [PreviousSwap V2 vs Swap V3](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/swap-v2-vs-v3) [NextConfigure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) Last updated 1 month ago * [Prerequisites](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute#prerequisites) * [Key details](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute#key-details) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute#related-pages) --- # Types Reference | Developer Docs | Titan All type definitions live inline on the page where they're used. This page is an index for quick navigation. **Field names are** `**camelCase**` **on the wire (MessagePack) unless otherwise specified.** Rust SDK types use `snake_case` with serde renaming. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#wire-protocol-and-common-types) Wire protocol & common types --------------------------------------------------------------------------------------------------------------------------------------------------- Defined on [Wire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) : * `**Pubkey**` — 32-byte Solana public key * `**AccountMeta**` — compact account descriptor (`p`, `s`, `w`) * `**Instruction**` — on-chain instruction (`p`, `a`, `d`) * `**SwapMode**` — `ExactIn` or `ExactOut` * `**ClientRequest**` — request envelope with `id` and `data` * `**ServerMessage**` — `Response`, `Error`, `StreamData`, or `StreamEnd` * `**ResponseSuccess**` / `**ResponseError**` — success and error response types * `**StreamData**` / `**StreamEnd**` / `**StreamStart**` — stream lifecycle types * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#server-info-types) Server info types --------------------------------------------------------------------------------------------------------------------------- Defined on [GetInfo](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) : * `**ServerInfo**` — protocol version and server settings * `**VersionInfo**` — `major`, `minor`, `patch` * `**ServerSettings**` — quote update, swap, transaction, and connection settings * `**BoundedValueWithDefault**` — `min`, `max`, `default` * `**QuoteUpdateSettings**` / `**SwapSettings**` / `**TransactionSettings**` / `**ConnectionSettings**` * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#request-types) Request types ------------------------------------------------------------------------------------------------------------------- Defined on [NewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) : * `**SwapQuoteRequest**` — `swap` + `transaction` + `update` * `**SwapParams**` — input/output mints, amount, slippage, routing filters * `**TransactionParams**` — wallet key, fee config, token account options * `**QuoteUpdateParams**` — stream interval and quote count * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#quote-and-stream-data-types) Quote & stream data types --------------------------------------------------------------------------------------------------------------------------------------------- Defined on [NewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#stream-updates) : * `**SwapQuotes**` — quote batch with provider-keyed `quotes` map * `**SwapRoute**` — single route with instructions, ALTs, expiry, compute budget * `**RoutePlanStep**` — one hop in a multi-step route * `**PlatformFee**` — `amount` and `fee_bps` * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#discovery-types) Discovery types ----------------------------------------------------------------------------------------------------------------------- Defined on [GetVenues / ListProviders](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers) : * `**VenueInfo**` — venue labels and optional program IDs * `**ProviderInfo**` — provider id, name, kind, optional icon * `**ProviderKind**` — `"DexAggregator"` or `"RFQ"` * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#stop-stream-types) Stop stream types --------------------------------------------------------------------------------------------------------------------------- Defined on [StopStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream) : * `**StopStreamRequest**` — stream ID to stop * `**StopStreamResponse**` — confirmed stream ID * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#related-pages) Related pages ------------------------------------------------------------------------------------------------------------------- * [Wire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) — encoding rules, common types, and message envelope types * [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) — WebSocket setup and authentication * [NewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) — request, response, and stream data types * [GetInfo](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) — server info and settings types * [GetVenues / ListProviders](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers) — discovery types * [StopStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream) — stop stream types [PreviousWire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) [NextError Codes](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes) Last updated 2 months ago * [Wire protocol & common types](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#wire-protocol-and-common-types) * [Server info types](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#server-info-types) * [Request types](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#request-types) * [Quote & stream data types](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#quote-and-stream-data-types) * [Discovery types](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#discovery-types) * [Stop stream types](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#stop-stream-types) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#related-pages) --- # Usernames and Referrals | Titan Titan will also allow you set your username that can be used to represent your profile. This username will also be used to refer other users to access the platform by giving them invite codes. Users who refer others will be able to get a view of the total aggregate volume and outperformance from themselves as well as their referred users. Referral invite codes can be found in the wallet panel at the top right of the panel ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252Fem4osBWHX3mHuyy7W3oe%252FScreen%2520Shot%25202025-08-13%2520at%25201.38.47%2520PM.png%3Falt%3Dmedia%26token%3D91c725c0-91fe-4e0f-a2ae-695114cb4529&width=768&dpr=3&quality=100&sign=a21a6145&sv=2) There may be additional benefits for both the referred and the referrer in the future. [PreviousAnalytics](https://titan-exchange.gitbook.io/titan/getting-started/analytics) [NextTitan DEX Integrations](https://titan-exchange.gitbook.io/titan/getting-started/titan-dex-integrations) Last updated 8 months ago --- # StopStream | Developer Docs | Titan **Tells the server to stop sending data on an active stream.** Use it when you no longer need quotes — after executing a swap, when the user navigates away, or before opening a new stream for a different pair. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream#request) Request -------------------------------------------------------------------------------------------------------------------- Rust TypeScript Copy struct StopStreamRequest { /// ID of the stream to stop. id: u32, } Copy interface StopStreamRequest { // ID of the stream to stop. id: number; } [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream#response) Response ---------------------------------------------------------------------------------------------------------------------- The server replies with `StreamStopped` containing the ID of the stopped stream. Rust TypeScript Copy struct StopStreamResponse { /// Identifier of the stream that was stopped. id: u32, } Copy interface StopStreamResponse { // Identifier of the stream that was stopped. id: number; } [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream#behavior) Behavior ---------------------------------------------------------------------------------------------------------------------- * **Queued data may still arrive.** After sending `StopStream`, the server may deliver one or more `StreamData` messages that were already queued. Handle them gracefully. * `**StreamEnd**` **always follows.** The server sends a `StreamEnd` message once all queued data has been flushed. **Only after receiving** `**StreamEnd**` **is the stream fully closed.** * **Stream IDs do not survive reconnects.** If the WebSocket connection drops, all streams are implicitly ended. Old IDs are no longer valid — do not call `StopStream` for streams from a previous connection. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream#example) Example -------------------------------------------------------------------------------------------------------------------- See [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#sending-a-request) for `sendRequest` and `decodeMessage` setup. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream#related-pages) Related pages -------------------------------------------------------------------------------------------------------------------------------- * [NewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) — open a streaming swap quote * [Error Handling & Reconnect](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling) — handle connection drops and stream errors * [Wire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) — MessagePack encoding and message envelope types [PreviousNewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) [NextGetVenues / ListProviders](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers) Last updated 2 months ago * [Request](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream#request) * [Response](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream#response) * [Behavior](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream#behavior) * [Example](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream#example) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream#related-pages) Copy // Capture stream ID when a quote stream opens if ('Response' in msg && 'NewSwapQuoteStream' in msg.Response.data) { streamId = msg.Response.stream.id; } // After receiving quotes, stop the stream if ('StreamData' in msg && streamId !== undefined) { console.log('Got quotes, stopping stream', streamId); await sendRequest(ws, requestId++, { StopStream: { id: streamId } }); streamId = undefined; } // Server confirms the stream was stopped if ('Response' in msg && 'StreamStopped' in msg.Response.data) { console.log('Stream stopped:', msg.Response.data.StreamStopped.id); } // Stream is fully closed — no more data will arrive for this stream if ('StreamEnd' in msg) { console.log('Stream ended:', msg.StreamEnd.id); } --- # GetVenues / ListProviders | Developer Docs | Titan **Use** `**GetVenues**` **to list every on-chain venue Titan can route through, and** `**ListProviders**` **to list the quote providers that compete for best execution.** Both are lightweight lookups you can issue at any time on an open connection. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#getvenues) GetVenues ----------------------------------------------------------------------------------------------------------------------------- Returns venue labels (and optionally their Solana program IDs) that are valid values for the `dexes` and `excludeDexes` routing parameters. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#request) Request Rust TypeScript Copy struct GetVenuesRequest { /// Whether to include the program ID for each venue. includeProgramIds: Option, } Copy interface GetVenuesRequest { // Whether to include the program ID for each venue. includeProgramIds?: boolean; } ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#response) Response Rust TypeScript Copy struct VenueInfo { /// List of venue labels. Each is a valid value for `dexes` and `excludeDexes`. labels: Vec, /// Program ID for each label, same order. Only present when `includeProgramIds` is true. programIds: Option>, } Copy interface VenueInfo { // Venue labels, valid for `dexes` and `excludeDexes` parameters. labels: string[]; // Program ID for each label. Only present when `includeProgramIds` is true. programIds?: Pubkey[]; } ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#example) Example See [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#sending-a-request) for `sendRequest` and `decodeMessage` setup. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#listproviders) ListProviders ------------------------------------------------------------------------------------------------------------------------------------- **Returns the list of quote providers currently active on the server.** Each provider independently competes to deliver the best-priced route for every quote stream. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#request-1) Request Rust TypeScript ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#response-1) Response Rust TypeScript ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#example-1) Example See [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#sending-a-request) for `sendRequest` and `decodeMessage` setup. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#related-pages) Related pages ------------------------------------------------------------------------------------------------------------------------------------- * [Configure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) — filter by venue or provider when opening a quote stream * [GetInfo](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) — server settings and protocol version * [NewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) — open a streaming swap quote [PreviousStopStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream) [NextGetSwapPrice](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price) Last updated 2 months ago * [GetVenues](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#getvenues) * [Request](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#request) * [Response](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#response) * [Example](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#example) * [ListProviders](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#listproviders) * [Request](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#request-1) * [Response](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#response-1) * [Example](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#example-1) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers#related-pages) Copy // Request all venues with their on-chain program IDs await sendRequest(ws, requestId++, { GetVenues: { includeProgramIds: true }, }); ws.on('message', async (raw: Buffer) => { const msg = await decodeMessage(raw); if ('Response' in msg && 'GetVenues' in msg.Response.data) { const venues = msg.Response.data.GetVenues; console.log('Venue count:', venues.labels.length); console.log('Labels:', venues.labels); // e.g. ['Raydium', 'Whirlpool', 'Phoenix', 'Meteora', ...] } }); Copy struct ListProvidersRequest { /// Whether to include icon URLs for each provider. /// By default, icons are not included. includeIcons: Option, } Copy interface ListProvidersRequest { // Whether to include icon URLs for each provider. // By default, icons are not included. includeIcons?: boolean; } Copy struct ProviderInfo { /// Provider identifier. Valid value for the `providers` routing parameter. id: String, /// Human-readable display name. name: String, /// What kind of provider this is. kind: ProviderKind, /// URI for a 48x48 icon, if requested and available. iconUri48: Option, } enum ProviderKind { DexAggregator, RFQ, } Copy interface ProviderInfo { // Provider identifier. Valid for the `providers` routing parameter. id: string; // Human-readable display name. name: string; // What kind of provider this is. kind: ProviderKind; // URI for a 48x48 icon, if requested and available. iconUri48?: string; } type ProviderKind = "DexAggregator" | "RFQ"; Copy // Request all active providers await sendRequest(ws, requestId++, { ListProviders: { includeIcons: false }, }); ws.on('message', async (raw: Buffer) => { const msg = await decodeMessage(raw); if ('Response' in msg && 'ListProviders' in msg.Response.data) { const providers = msg.Response.data.ListProviders; providers.forEach((p: any) => { console.log(`${p.name} (${p.id}) — ${p.kind}`); // e.g. "Titan (Titan) — DexAggregator" }); } }); --- # Prime Mode and Custom Settings | Titan ### [](https://titan-exchange.gitbook.io/titan/getting-started/quickstart-1#extra-user-parameters) Extra User Parameters ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252F0hd7Ob5OLmSv0sYVwz7t%252FScreen%2520Shot%25202025-08-13%2520at%25201.48.38%2520PM.png%3Falt%3Dmedia%26token%3D5bc1db02-93a1-4721-8178-5b73cfba8340&width=768&dpr=3&quality=100&sign=3ed03fae&sv=2) In the settings button at the top right of the swap box, users can configure their transactions and routes in a variety of ways including: * Prime vs Manual Mode * Max Slippage * Transaction Fee Methods * AMM Exclusion ### [](https://titan-exchange.gitbook.io/titan/getting-started/quickstart-1#prime-mode) Prime Mode Titan's Prime Mode automatically optimizes your swap settings — including slippage and transaction landing — to deliver the best execution through Titan’s meta-aggregator. With automatic sandwich protection, Titan Prime charges zero fees as comparable to other services that will take up to a 10 basis point fee. Along with Titan's propietary algorithm, this means users can get an extra 20 basis points per trade when using Titan Prime. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252F0hd7Ob5OLmSv0sYVwz7t%252FScreen%2520Shot%25202025-08-13%2520at%25201.48.38%2520PM.png%3Falt%3Dmedia%26token%3D5bc1db02-93a1-4721-8178-5b73cfba8340&width=768&dpr=3&quality=100&sign=3ed03fae&sv=2) When the settings button is showing an animated Prime button, Titan Prime settings will be applied to the trade. For Titan quotes, the transaction is simulated to see what the user would get at that point in time when the swap button is pressed. If this would result in a revert due to slippage tolerances being exceeded, the attempted swap would result in an error message. ### [](https://titan-exchange.gitbook.io/titan/getting-started/quickstart-1#manual-mode) Manual Mode #### [](https://titan-exchange.gitbook.io/titan/getting-started/quickstart-1#max-slippage) Max Slippage ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FoB1ekMLegVFJAkVtkERJ%252FScreen%2520Shot%25202025-08-13%2520at%25201.50.28%2520PM.png%3Falt%3Dmedia%26token%3D183475be-9140-416b-94f2-baac73baf398&width=768&dpr=3&quality=100&sign=fe653ce7&sv=2) Slippage is the amount that your final trade differs by from your quoted price when executing a trade. This could be due to several reasons, but the most common is that someone has already traded ahead of you. This setting exists so that if the slippage exceeds your max tolerance, the trade is reverted even though the transaction fee is still taken by the blockchain. There are 2 slippage settings that the user can modify: * Base Tokens: Any token pair that is not a stablecoin to stablecoin pair or SOL/LST or LST/SOL pair. * Stable/LST: Any token pair that is a stablecoin to stablecoin pair or SOL/LST or LST/SOL pair These 2 different settings are used to reflect that some tokens are very closely related in value and therefore have far less slippage involved. #### [](https://titan-exchange.gitbook.io/titan/getting-started/quickstart-1#transaction-fee-methods) Transaction Fee Methods Titan currently supports two types of broadcast mode fees in order to process transactions with plans to add more soon. These currently are: * Priority Fees ([https://solana.com/developers/guides/advanced/how-to-use-priority-fees](https://solana.com/developers/guides/advanced/how-to-use-priority-fees) ) * MEV Protect, which is a combo of Jito ([https://docs.jito.wtf/](https://docs.jito.wtf/) ) and Nozomi ([https://use.temporal.xyz/](https://use.temporal.xyz/) ) along with anti sandwich protection ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FRB6h9bsFf12dxMxM8H67%252FScreen%2520Shot%25202025-08-13%2520at%25201.51.45%2520PM.png%3Falt%3Dmedia%26token%3Dc5c92be4-4095-438d-9aa5-194046cdbfb3&width=768&dpr=3&quality=100&sign=9d068d3&sv=2) All broadcast modes have the same options included. With Auto fee mode, Titan determines the appropriate fee level to be paid leveraging 3rd party services such as Helius, Triton, and Jito depending on how fast the user wishes to process the transaction. A max cap on the fee is also set here in case the suggested fee goes above what the user is comfortable paying. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FbofQTISqSCLUxkjo8VlU%252FScreen%2520Shot%25202025-08-13%2520at%25201.52.20%2520PM.png%3Falt%3Dmedia%26token%3D28811c28-3b18-4eb2-87f2-1141a95cddfb&width=768&dpr=3&quality=100&sign=385d316a&sv=2) With Custom fee mode, the user sets the exact fee they wish to pay. Some wallets may enforce a minimum priority fee to be paid per transaction. #### [](https://titan-exchange.gitbook.io/titan/getting-started/quickstart-1#amm-exclusion) AMM Exclusion Users also have the option to exclude various AMMs from the chosen routes for whatever reason. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FqM8pCmHESpY2PHYeLu20%252FScreen%2520Shot%25202025-08-13%2520at%25201.53.14%2520PM.png%3Falt%3Dmedia%26token%3De2f95c8c-3747-4714-87ed-ee91812f989e&width=768&dpr=3&quality=100&sign=bf06b829&sv=2) The selected AMMs will then be excluded from generated routes. AMMs have been normalized across DEX Aggregators so that the user does not need to know how each DEX Aggregator handles the naming and identification of various DEXes. [PreviousQuickstart](https://titan-exchange.gitbook.io/titan/getting-started/quickstart) [NextTitan Limit Orders](https://titan-exchange.gitbook.io/titan/getting-started/titan-limit-orders) Last updated 4 months ago * [Extra User Parameters](https://titan-exchange.gitbook.io/titan/getting-started/quickstart-1#extra-user-parameters) * [Prime Mode](https://titan-exchange.gitbook.io/titan/getting-started/quickstart-1#prime-mode) * [Manual Mode](https://titan-exchange.gitbook.io/titan/getting-started/quickstart-1#manual-mode) --- # GetSwapPrice | Developer Docs | Titan _Available since protocol version 1.2.0._ **Returns a price quote without instructions or transaction data.** Use it when you need to display prices in a UI without the overhead of building executable transactions — lighter weight than `NewSwapQuoteStream`. This is a one-shot request, not a stream. The server finds the best direct route and uses the simulated output to determine the price. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price#request) Request ----------------------------------------------------------------------------------------------------------------------- Rust TypeScript Copy struct SwapPriceRequest { /// Address of the input mint of the swap. inputMint: Pubkey, /// Address of the desired output token for the swap. outputMint: Pubkey, /// Raw number of tokens to swap, not scaled by decimals. amount: u64, /// If set, constrain quotes to the given set of DEXes. dexes: Option>, /// If set, exclude the following DEXes when determining routes. excludeDexes: Option>, } Copy interface SwapPriceRequest { // Address of the input mint. inputMint: Pubkey; // Address of the output mint. outputMint: Pubkey; // Raw number of tokens to swap. Use BigInt. amount: number | bigint; // If set, constrain to these DEXes. dexes?: string[]; // If set, exclude these DEXes. excludeDexes?: string[]; } [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price#response) Response ------------------------------------------------------------------------------------------------------------------------- Rust TypeScript **The response does not include** `**instructions**`**,** `**addressLookupTables**`**, or any transaction data.** To get executable swap data, use [NewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) or the Gateway [Quote Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap) endpoint. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price#example) Example ----------------------------------------------------------------------------------------------------------------------- See [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#sending-a-request) for `sendRequest` and `decodeMessage` setup. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price#related-pages) Related pages ----------------------------------------------------------------------------------------------------------------------------------- * [NewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) — full quote with executable instructions * [Gateway Quote Price](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price) — REST equivalent * [Configure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) — venue filtering with `dexes` and `excludeDexes` [PreviousGetVenues / ListProviders](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers) [NextTitan Gateway](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway) Last updated 2 months ago * [Request](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price#request) * [Response](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price#response) * [Example](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price#example) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-swap-price#related-pages) Copy struct SwapPrice { /// Identifier for this price quote. id: String, /// Address of the input mint. inputMint: Pubkey, /// Address of the output mint. outputMint: Pubkey, /// Amount that was used for the price. amountIn: u64, /// The amount out of the best simulated quote. amountOut: u64, } Copy interface SwapPrice { // Identifier for this price quote. id: string; // Address of the input mint. inputMint: Pubkey; // Address of the output mint. outputMint: Pubkey; // Amount used for pricing. amountIn: number | bigint; // Best simulated output amount. amountOut: number | bigint; } Copy import WebSocket from 'ws'; // highlight-next-line import { Encoder, Decoder } from '@msgpack/msgpack'; import { compressSync, decompressSync } from 'fflate'; // zstd-compatible deflate import bs58 from 'bs58'; // --- Encoder / Decoder with BigInt support for u64 fields --- // highlight-start const encoder = new Encoder({ useBigInt64: true }); const decoder = new Decoder({ useBigInt64: true }); // highlight-end // Connect with zstd sub-protocol for compressed frames const url = `${process.env.TITAN_ENDPOINT}?auth=${process.env.TITAN_API_KEY}`; // highlight-next-line const ws = new WebSocket(url, ['v1.api.titan.ag+zstd', 'v1.api.titan.ag']); let requestId = 0; // Pubkeys as 32-byte binary — MessagePack sends these as raw bytes const SOL = bs58.decode('So11111111111111111111111111111111111111112'); const USDC = bs58.decode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); /** Encode, optionally compress, and send a request frame. */ function sendRequest(ws: WebSocket, id: number, data: Record) { // highlight-next-line const payload = encoder.encode({ id, data }); // If the server negotiated the +zstd sub-protocol, compress before sending const frame = ws.protocol === 'v1.api.titan.ag+zstd' ? compressSync(new Uint8Array(payload)) : payload; ws.send(frame); } /** Decompress (if needed) and decode an incoming frame. */ function decodeMessage(raw: Buffer): any { const bytes = ws.protocol === 'v1.api.titan.ag+zstd' ? decompressSync(new Uint8Array(raw)) : raw; // highlight-next-line return decoder.decode(bytes); } ws.on('open', () => { // Request a price-only quote — no transaction data returned sendRequest(ws, requestId++, { GetSwapPrice: { inputMint: SOL, outputMint: USDC, amount: 1_000_000_000n, // 1 SOL in lamports }, }); }); ws.on('message', async (raw: Buffer) => { const msg = decodeMessage(raw); // highlight-start // Price response — use amountOut for display if ('Response' in msg && 'GetSwapPrice' in msg.Response.data) { const price = msg.Response.data.GetSwapPrice; console.log('Output amount:', price.amountOut); // BigInt ws.close(); } // highlight-end if ('Error' in msg) { console.error(`Error ${msg.Error.code}: ${msg.Error.message}`); ws.close(); } }); --- # Info / Venues / Providers | Developer Docs | Titan **Three lightweight endpoints for reading server configuration and discovering available venues and providers.** All are simple GET requests you can issue at any time. **All responses are MessagePack-encoded.** Set `Accept: application/vnd.msgpack` in your request headers. **Authentication** — `Authorization: Bearer ` header or `?auth=` query param. See [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#authentication) for JWT details. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#info) Info ---------------------------------------------------------------------------------------------------------------- Copy GET /api/v1/info **Returns server settings, protocol version, and configurable parameter bounds.** The REST equivalent of [GetInfo](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) . Call it to read the defaults and limits you'll need when configuring swap requests. For full `ServerInfo` type definitions (including `VersionInfo`, `ServerSettings`, `BoundedValueWithDefault`, and all sub-types), see the [GetInfo](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) reference page. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#example) Example Copy import { Decoder } from '@msgpack/msgpack'; // useBigInt64 required — 64-bit integer fields (amounts, timestamps) const decoder = new Decoder({ useBigInt64: true }); // Fetch server info from the Gateway REST endpoint const res = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/info`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', }, } ); // Decode the MessagePack response const info = decoder.decode(new Uint8Array(await res.arrayBuffer())) as any; // Protocol version — major changes are backwards-incompatible console.log('Protocol version:', info.protocolVersion); // Quote stream settings — use these bounds when configuring requests console.log('Default update interval:', info.settings.quoteUpdate.intervalMs.default, 'ms'); console.log('Concurrent streams allowed:', info.settings.connection.concurrentStreams); * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#venues) Venues -------------------------------------------------------------------------------------------------------------------- **Returns the list of on-chain venues available for routing.** Each label is a valid value for the `dexes` and `excludeDexes` query parameters on [Quote Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap) and [Quote Price](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price) . For full `VenueInfo` type definitions, see the [GetVenues / ListProviders](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers) reference page. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#query-parameters) Query parameters * `**includeProgramIds**` — `"true"` to include the Solana program ID for each venue. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#example-1) Example * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#providers) Providers -------------------------------------------------------------------------------------------------------------------------- **Returns the list of active quote providers.** Each `id` is a valid value for the `providers` query parameter on [Quote Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-swap) . Each provider independently competes to deliver the best-priced route. For full `ProviderInfo` and `ProviderKind` type definitions, see the [GetVenues / ListProviders](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers) reference page. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#query-parameters-1) Query parameters * `**includeIcons**` — `"true"` to include 48×48 icon URIs for each provider. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#example-2) Example * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#error-responses) Error responses -------------------------------------------------------------------------------------------------------------------------------------- * `**400**` — **Invalid parameters.** Malformed query parameter value. * `**401**` — **Missing or invalid authentication token.** Check your JWT and its claims. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#related-pages) Related pages ---------------------------------------------------------------------------------------------------------------------------------- * [GetInfo](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) — Direct (WebSocket) equivalent with full `ServerInfo` type definitions * [GetVenues / ListProviders](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/venues-providers) — Direct (WebSocket) equivalents with full `VenueInfo` and `ProviderInfo` type definitions * [Configure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) — Use venue and provider IDs to filter and customize quote routing * [Titan Direct vs Titan Gateway](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct-vs-gateway) — Choosing between WebSocket and REST [PreviousQuote Price](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-quote-price) [NextWire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) Last updated 2 months ago * [Info](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#info) * [Example](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#example) * [Venues](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#venues) * [Query parameters](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#query-parameters) * [Example](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#example-1) * [Providers](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#providers) * [Query parameters](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#query-parameters-1) * [Example](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#example-2) * [Error responses](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#error-responses) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info#related-pages) Copy GET /api/v1/venues Copy // Fetch all available venues with their on-chain program IDs const res = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/venues?includeProgramIds=true`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', }, } ); // Decode and inspect the venue list const venues = decoder.decode(new Uint8Array(await res.arrayBuffer())) as any; console.log('Available venues:', venues.labels); // e.g. ['Raydium', 'Whirlpool', 'Phoenix', 'Meteora', ...] Copy GET /api/v1/providers Copy // Fetch all active quote providers const res = await fetch( `${process.env.TITAN_ENDPOINT}/api/v1/providers`, { headers: { 'Authorization': `Bearer ${process.env.TITAN_API_KEY}`, 'Accept': 'application/vnd.msgpack', }, } ); // Decode and iterate over the provider list const providers = decoder.decode(new Uint8Array(await res.arrayBuffer())) as any[]; for (const p of providers) { console.log(`${p.name} (${p.id}) — ${p.kind}`); // e.g. "Titan (Titan) — DexAggregator" } --- # Community & Support | Developer Docs | Titan **Connect with the Titan team and community for support, feedback, and updates.** * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/community-and-support#discord) Discord -------------------------------------------------------------------------------------------------------------- Join the Titan Discord for real-time help, announcements, and discussion with other developers. **Discord is the fastest way to get support.** The team actively monitors developer channels. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/community-and-support#github) GitHub ------------------------------------------------------------------------------------------------------------ * **TypeScript SDK** — [github.com/Titan-Pathfinder/titan-sdk-ts](https://github.com/Titan-Pathfinder/titan-sdk-ts) * **Rust SDK crates** — [crates.io/search?q=titan-api-types](https://crates.io/search?q=titan-api-types) **Found a bug?** Open an issue on the relevant SDK repository with reproduction steps. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/community-and-support#getting-api-access) Getting API access ------------------------------------------------------------------------------------------------------------------------------------ See [Get API Access](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/api-access) for instructions on obtaining your API key. [PreviousSDK Reference](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk) [NextAI / LLM Integration](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration) Last updated 20 days ago * [Discord](https://titan-exchange.gitbook.io/titan/developer-doc/resources/community-and-support#discord) * [GitHub](https://titan-exchange.gitbook.io/titan/developer-doc/resources/community-and-support#github) * [Getting API access](https://titan-exchange.gitbook.io/titan/developer-doc/resources/community-and-support#getting-api-access) --- # Wire Protocol | Developer Docs | Titan This page covers how data is encoded on the wire — the serialization format, encoding conventions, and shared types used across all Titan API messages. **Both Titan Direct and Titan Gateway use MessagePack binary encoding. JSON is not supported.** [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#data-format) Data format ----------------------------------------------------------------------------------------------------------------------- The basic data format for serialization of all messages is **MessagePack**. * **Objects/structs are encoded as maps** — this allows additional fields to be added without breaking compatibility with previous versions. * **Field names are** `**camelCase**` unless otherwise specified. * **Integers are encoded using the smallest MessagePack int type** that fits the value. * **Use** `**BigInt**` **for** `**u64**` **values** (amounts, timestamps) — values above 2^53 lose precision as float64, which the server rejects. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#optional-data) Optional data --------------------------------------------------------------------------------------------------------------------------- If a value is optional, its type is `Option` in Rust and `T?` or `T | null` in TypeScript. **Optional fields in objects may be omitted entirely from the serialized map.** Otherwise, a missing optional value should be encoded as `nil` (`0xc0`) — decoded as `None` in Rust and `null` in TypeScript. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#simple-enumerations) Simple enumerations --------------------------------------------------------------------------------------------------------------------------------------- Simple enumerations (those without associated data) are **encoded as strings matching the variant name exactly**: Rust TypeScript Copy enum SwapMode { ExactIn, ExactOut, } // Encoded as: "ExactIn" or "ExactOut" Copy enum SwapMode { ExactIn = "ExactIn", ExactOut = "ExactOut", } [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#complex-enumerations) Complex enumerations ----------------------------------------------------------------------------------------------------------------------------------------- Complex enumerations (those with associated data) are **encoded as single-value maps**, mapping the variant name to the associated data. * Single associated item → the value is that data. * Multiple associated items → the value is an array. Rust TypeScript This pattern applies to both client requests (`RequestData`) and server messages (`ServerMessage`). **To determine the message type, check which key is present in the top-level map.** [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#binary-data) Binary data ----------------------------------------------------------------------------------------------------------------------- Binary data is encoded using MessagePack `bin` formats. Rust TypeScript TypeScript has no way to specify byte array size — refer to the Rust types for size constraints. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#common-types) Common types ------------------------------------------------------------------------------------------------------------------------- ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#pubkey) Pubkey **Solana public keys are 32-byte binary data.** Encoded using MessagePack `bin 8` format — all pubkeys start with `c4 20` followed by 32 bytes of key data. Example — the WSOL public key `So11111111111111111111111111111111111111112`: Rust TypeScript ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#accountmeta) AccountMeta Compact account descriptor used in instructions. **Uses single-letter field names to minimize message size.** Rust TypeScript ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#instruction) Instruction A single on-chain instruction. **Also uses single-letter field names for compactness.** Rust TypeScript `**AccountMeta**` **and** `**Instruction**` **use single-letter field names (**`**p**`**,** `**s**`**,** `**w**`**,** `**a**`**,** `**d**`**) to reduce payload size.** These are Titan's wire format, not abbreviations of the standard Solana SDK types. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#message-envelope-types) Message envelope types --------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#clientrequest) ClientRequest Every client request wraps an RPC method call with a monotonically increasing `id`. Rust TypeScript ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#servermessage) ServerMessage **The server sends one of four message types:** Rust TypeScript * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#compression) Compression ----------------------------------------------------------------------------------------------------------------------- Compression wraps the MessagePack payload. The order of operations: **Sending:** serialize to MessagePack → compress → send as binary WebSocket frame **Receiving:** receive binary frame → decompress → deserialize from MessagePack The compression scheme is negotiated once at connection time. See [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) for protocol strings and setup. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#gateway-differences) Gateway differences --------------------------------------------------------------------------------------------------------------------------------------- Titan Gateway uses the same MessagePack encoding but over HTTP REST: * **Requests** — query parameters (pubkeys as Base58 strings, not binary) * **Responses** — MessagePack body with `Content-Type: application/vnd.msgpack` * **Pubkeys in responses** are still binary `Uint8Array` in the MessagePack body * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#related-pages) Related pages --------------------------------------------------------------------------------------------------------------------------- * [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) — WebSocket setup, authentication, and compression negotiation * [GetInfo](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) — server settings and protocol version * [NewSwapQuoteStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream) — streaming swap quotes [PreviousInfo / Venues / Providers](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/gateway/gateway-info) [NextTypes Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) Last updated 2 months ago * [Data format](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#data-format) * [Optional data](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#optional-data) * [Simple enumerations](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#simple-enumerations) * [Complex enumerations](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#complex-enumerations) * [Binary data](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#binary-data) * [Common types](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#common-types) * [Pubkey](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#pubkey) * [AccountMeta](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#accountmeta) * [Instruction](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#instruction) * [Message envelope types](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#message-envelope-types) * [ClientRequest](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#clientrequest) * [ServerMessage](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#servermessage) * [Compression](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#compression) * [Gateway differences](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#gateway-differences) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol#related-pages) Copy struct Request2Data { id: u32, amount: u64, } enum Complex { Request1(String), Request2(Request2Data), Request3(u32, u32), } // Valid encodings (shown as JSON for readability): // { "Request1": "hello" } // { "Request2": {"id": 1, "amount": 34} } // { "Request3": [3, 4] } Copy interface Request2Data { id: number; amount: number; } type Complex = | { Request1: string } | { Request2: Request2Data } | { Request3: [number, number] }; Copy // Variable-sized byte array Vec // Fixed-size byte array (N bytes) [u8; N] Copy // Binary data in TypeScript Uint8Array // or ArrayBuffer Copy c4 20 069b8857feab8184fb687f634618c035dac439dc1aeb3b5598a0f00000000001 Copy // Type alias for public keys type Pubkey = [u8; 32]; Copy // Type alias for public keys to differentiate from other binary data type Pubkey = Uint8Array; // 32 bytes Copy struct AccountMeta { p: Pubkey, // public key s: bool, // is_signer w: bool, // is_writable } Copy interface AccountMeta { p: Pubkey; // public key s: boolean; // is_signer w: boolean; // is_writable } Copy struct Instruction { p: Pubkey, // program_id a: Vec, // accounts d: Vec, // data } Copy interface Instruction { p: Pubkey; // program_id a: AccountMeta[]; // accounts d: Uint8Array; // data } Copy struct ClientRequest { /// Request ID, echoed in the server's response. id: u32, /// One of the RPC method variants. data: RequestData, } enum RequestData { GetInfo(GetInfoRequest), NewSwapQuoteStream(SwapQuoteRequest), StopStream(StopStreamRequest), GetVenues(GetVenuesRequest), ListProviders(ListProvidersRequest), GetSwapPrice(SwapPriceRequest), } Copy interface ClientRequest { // Request ID, echoed in the server's response. id: number; // One of the RPC method variants. data: RequestData; } type RequestData = | { GetInfo: GetInfoRequest } | { NewSwapQuoteStream: SwapQuoteRequest } | { StopStream: StopStreamRequest } | { GetVenues: GetVenuesRequest } | { ListProviders: ListProvidersRequest } | { GetSwapPrice: SwapPriceRequest }; Copy /// A message sent by the server to the client. enum ServerMessage { /// Successful response to a request, may optionally start a stream. Response(ResponseSuccess), /// An error response to a request. Error(ResponseError), /// Data for a stream. StreamData(StreamData), /// Notification that a stream has ended. StreamEnd(StreamEnd), } /// A successful response. struct ResponseSuccess { /// Identifier of the request that triggered this response. requestId: u32, /// The response data. data: ResponseData, /// If this request starts a new stream, contains stream info. stream: Option, } /// An error response. struct ResponseError { /// Identifier of the request that triggered this response. requestId: u32, /// A numeric error code. code: u32, /// A message describing the error. message: String, } /// Data packet for a stream. struct StreamData { /// ID of the stream. id: u32, /// Sequence number of this data packet. seq: u32, /// Data payload. payload: StreamDataPayload, } /// Notification that a stream has closed. struct StreamEnd { /// ID of the stream that has ended. id: u32, /// Error code, if the stream ended abnormally. errorCode: Option, /// Error message, if the stream ended abnormally. errorMessage: Option, } /// Notification that a new stream has been started. struct StreamStart { /// Stream ID — present in all StreamData and StreamEnd for this stream. id: u32, /// Type of data that will be sent in this stream. dataType: StreamDataType, } enum StreamDataType { SwapQuotes, // May be expanded in the future. } enum StreamDataPayload { SwapQuotes(SwapQuotes), // May be expanded in the future. } enum ResponseData { GetInfo(ServerInfo), NewSwapQuoteStream(QuoteSwapStreamResponse), StreamStopped(StopStreamResponse), GetVenues(VenueInfo), ListProviders(Vec), GetSwapPrice(SwapPrice), } Copy type ServerMessage = | { Response: ResponseSuccess } | { Error: ResponseError } | { StreamData: StreamData } | { StreamEnd: StreamEnd }; interface ResponseSuccess { // Identifier of the request that triggered this response. requestId: number; // The response data. data: ResponseData; // If the request started a new stream, contains stream info. stream?: StreamStart; } interface ResponseError { // Identifier of the request that triggered this response. requestId: number; // A numeric error code. code: number; // A message describing the error. message: string; } interface StreamData { // ID of the stream. id: number; // Sequence number of this data packet. seq: number; // Data payload. payload: StreamDataPayload; } interface StreamEnd { // ID of the stream that has ended. id: number; // Error code, if the stream ended abnormally. errorCode?: number; // Error message, if the stream ended abnormally. errorMessage?: string; } interface StreamStart { // Stream ID. id: number; // Type of data that will be sent in this stream. dataType: StreamDataType; } enum StreamDataType { SwapQuotes = "SwapQuotes", } type StreamDataPayload = { SwapQuotes: SwapQuotes }; type ResponseData = | { GetInfo: ServerInfo } | { NewSwapQuoteStream: QuoteSwapStreamResponse } | { StreamStopped: StopStreamResponse } | { GetVenues: VenueInfo } | { ListProviders: ProviderInfo[] } | { GetSwapPrice: SwapPrice }; --- # Titan Limit Orders | Titan Titan Limit Orders are TRUE on-chain limit orders. These are not trigger orders that other platforms may provide; Titan limit orders execute consistently through volatility. Through our unique architecture, Titan is bringing CeFi-grade execution on-chain to Solana, fulfilled by professional market makers like Auros, one of the top market making firms worldwide. Titan Limit Orders are based off of specific token pairs that enable top notch execution quality. We will be adding more pairs as the service keeps on developing. The main issue with Trigger Orders today are that they fill extremely slowly and randomly. Titan Limit Orders fill efficiently and attempts to account for market volatility. The end result are filled orders that can be hundreds and thousands of blocks faster, which is critical for traders. Partial fills are also enabled. A 10 bps fee is charged for Limit Orders with a discount for Titan VIP users. This is lower than comparable products from competitors by up to 50%, while offering better execution quality. There is also a minimum $10 USD notional for this service. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252F23h2zRrGoEE1qnqWMpK3%252FScreen%2520Shot%25202026-01-14%2520at%25209.21.15%2520PM.png%3Falt%3Dmedia%26token%3D30f83553-16f3-460e-9e6b-67853e45cee2&width=768&dpr=3&quality=100&sign=18237b06&sv=2) Once an order expires or is filled, a crank will automatically return funds to the user's main wallet. A rent fee is also collected to open up the relevant account. The full amount is returned upon completion/cancellation of the order. Titan Limit Orders are open to be filled by anyone. Please find instructions here [https://titan-exchange.gitbook.io/titan/titan-developer-docs/apis/searchers-limit-orders](https://titan-exchange.gitbook.io/titan/titan-developer-docs/apis/searchers-limit-orders) and contact the team if there are any questions. ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-limit-orders#limit-order-guide) Limit Order Guide In order to navigate to Limit Order section, please click the Limit tab on the swap page. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FvF8TNpg9QrjleZywsLjU%252FScreen%2520Shot%25202026-01-14%2520at%25209.24.56%2520PM.png%3Falt%3Dmedia%26token%3Dc00a6581-a671-4463-9656-eb08ad65eef3&width=768&dpr=3&quality=100&sign=d63abbd4&sv=2) Once navigated, users will have chart visualization and order history loaded up as well. Please click on the dropdown to select the token pair you wish to trade. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FyBKkYfOyfbhBOMvdhsq9%252FScreen%2520Shot%25202026-01-14%2520at%25209.30.31%2520PM.png%3Falt%3Dmedia%26token%3D71484550-f813-4a15-88f7-ff1ba55e020c&width=768&dpr=3&quality=100&sign=ad41275b&sv=2) After the trading pair is selected, please choose the direction of the trade, the limit price, quantity, and expiry date. After these are chosen, please execute the order. As a reminder, users will not be able to set a limit price that is above the market price. A minimum $10 notional is also required. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FlgSZ5OnDoTdw3Gf2eeVf%252FScreen%2520Shot%25202026-01-14%2520at%25209.30.47%2520PM.png%3Falt%3Dmedia%26token%3Dc2d69b94-1889-4ff1-808d-f15d141a8ede&width=768&dpr=3&quality=100&sign=9e783a56&sv=2) ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-limit-orders#order-management) Order Management You can manage your orders directly from the swap page under open orders. The progress of the order, expiry, and limit price can be seen. In addition, there is also a link out to solscan as well as the ability to cancel an order if you click on the x. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FipINEENYWNsPa9blaZVc%252FScreen%2520Shot%25202026-01-14%2520at%25209.34.04%2520PM.png%3Falt%3Dmedia%26token%3Df7bdffd1-009c-482a-989a-f93d9a5de256&width=768&dpr=3&quality=100&sign=71bf0d5c&sv=2) You can also navigate to order history to check the progress. If you click on an order, you will be able to check the history for that particular order. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FtWbvJCMoqHnCE17WsGvE%252FScreen%2520Shot%25202026-01-14%2520at%25209.35.38%2520PM.png%3Falt%3Dmedia%26token%3D5e8db72b-7b2b-49de-b1d9-3018de1f3e2d&width=768&dpr=3&quality=100&sign=1ca2753f&sv=2) In addition, there is also a notification button that will notify you every time a limit order has an update. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FErTGwIPlPtBQL01wJzny%252FScreen%2520Shot%25202026-01-14%2520at%25209.36.39%2520PM.png%3Falt%3Dmedia%26token%3D86bf5844-54eb-480c-a40b-f1dfbff61f17&width=768&dpr=3&quality=100&sign=85e28a3b&sv=2) ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-limit-orders#analytics) Analytics Limit Orderes will have its own tracking in the summary page as well as the profile page. There will also be a dedicated limit order leaderboard. ![](https://titan-exchange.gitbook.io/titan/~gitbook/image?url=https%3A%2F%2F214878899-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FKEg3FeKkeNIHryTs7Kso%252Fuploads%252FHSQusodFBQcRBdUaS4vA%252FScreen%2520Shot%25202026-01-14%2520at%25209.37.15%2520PM.png%3Falt%3Dmedia%26token%3De0f7f40b-dbc2-4b71-b942-799149677cba&width=768&dpr=3&quality=100&sign=b9a2e9df&sv=2) ### [](https://titan-exchange.gitbook.io/titan/getting-started/titan-limit-orders#charting-data) Charting Data The chart data comes from a combination of Trading View and Binance. This may not be reflective of a market maker's inventory at certain times. Please be aware of this. [PreviousPrime Mode and Custom Settings](https://titan-exchange.gitbook.io/titan/getting-started/quickstart-1) [NextTitan Private Swaps](https://titan-exchange.gitbook.io/titan/getting-started/titan-private-swaps) Last updated 4 months ago * [Limit Order Guide](https://titan-exchange.gitbook.io/titan/getting-started/titan-limit-orders#limit-order-guide) * [Order Management](https://titan-exchange.gitbook.io/titan/getting-started/titan-limit-orders#order-management) * [Analytics](https://titan-exchange.gitbook.io/titan/getting-started/titan-limit-orders#analytics) * [Charting Data](https://titan-exchange.gitbook.io/titan/getting-started/titan-limit-orders#charting-data) --- # AI / LLM Integration | Developer Docs | Titan **Use Titan's swap infrastructure from AI agents, LLM tool-calling workflows, and autonomous trading systems.** * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#claude-code-skill) Claude Code Skill ------------------------------------------------------------------------------------------------------------------------------- **The fastest way to build Titan integrations with AI.** The `@titanexchange/titan-api-skill` package gives Claude Code protocol-aware code generation for the Titan API. * **Package:** [@titanexchange/titan-api-skill](https://www.npmjs.com/package/@titanexchange/titan-api-skill) * **Source:** [github.com/Titan-Pathfinder/titan-api-claude-skills](https://github.com/Titan-Pathfinder/titan-api-claude-skills) ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#what-it-provides) What it provides * **Protocol-aware code generation** — Generates TypeScript with correct MessagePack encoding, BigInt amounts, and bs58-decoded token mints matching the Titan WebSocket API spec. * **SDK and raw WebSocket support** — Covers both SDK-based and direct WebSocket integration depending on developer needs. * **Parameter structure enforcement** — Places fields like `slippageBps`, `intervalMs`, and `num_quotes` in their correct nested objects matching the expected request schema. * **Runnable examples included** — Ships with working TypeScript examples that can be executed directly. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#installation) Installation **npx (recommended):** Copy # For current project npx @titanexchange/titan-api-skill # For all projects (global) npx @titanexchange/titan-api-skill --global # Overwrite existing install npx @titanexchange/titan-api-skill --force Then type `/titan-swap-api` in Claude Code to use the skill. **Manual install (curl):** ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#quick-example) Quick example Ask Claude Code: > "Help me stream USDC to SOL quotes using Titan API" Claude will generate protocol-correct code: ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#runnable-examples) Runnable examples The `/examples` directory contains working TypeScript examples: ### [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#required-credentials) Required credentials * `**WS_URL**` — Titan WebSocket endpoint. * `**AUTH_TOKEN**` — API authentication token. See [Get API Access](https://titan-exchange.gitbook.io/titan/developer-doc/getting-started/api-access) . * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#llm-friendly-docs-llms.txt) LLM-friendly docs (llms.txt) --------------------------------------------------------------------------------------------------------------------------------------------------- **Titan's documentation is automatically available in LLM-optimized formats** via the [llms.txt](https://llmstxt.org/) standard. AI agents and LLMs can ingest the full docs without scraping HTML. * `**/llms.txt**` — Index of all doc sections with links to individual pages in Markdown format. * `**/llms-full.txt**` — The entire documentation as a single Markdown file — ideal for full-context ingestion. * **Every page as** `**.md**` — Append `.md` to any doc page URL to get the raw Markdown version. These endpoints are **generated automatically by GitBook** and stay up-to-date with every publish. No configuration needed. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#key-things-to-know) Key things to know --------------------------------------------------------------------------------------------------------------------------------- * **Protocol** — WebSocket + MessagePack (not JSON). * **Amounts** — Must be `BigInt`, not `number`. * **Token mints** — Must be `Uint8Array` via `bs58.decode()`. * **Parameters** — `slippageBps` goes in `swap`, `intervalMs` goes in `update`. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#related-pages) Related pages ----------------------------------------------------------------------------------------------------------------------- * [SDK Reference](https://titan-exchange.gitbook.io/titan/developer-doc/resources/sdk) — TypeScript and Rust SDK documentation * [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) — WebSocket setup and protocol details * [Quickstart](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/quickstart) — End-to-end integration example [PreviousCommunity & Support](https://titan-exchange.gitbook.io/titan/developer-doc/resources/community-and-support) Last updated 2 months ago * [Claude Code Skill](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#claude-code-skill) * [What it provides](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#what-it-provides) * [Installation](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#installation) * [Quick example](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#quick-example) * [Runnable examples](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#runnable-examples) * [Required credentials](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#required-credentials) * [LLM-friendly docs (llms.txt)](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#llm-friendly-docs-llms.txt) * [Key things to know](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#key-things-to-know) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/resources/ai-llm-integration#related-pages) Copy # Global mkdir -p ~/.claude/skills/titan-swap-api curl -o ~/.claude/skills/titan-swap-api/SKILL.md \ https://raw.githubusercontent.com/Titan-Pathfinder/titan-api-claude-skills/main/SKILL.md # Project-level mkdir -p .claude/skills/titan-swap-api curl -o .claude/skills/titan-swap-api/SKILL.md \ https://raw.githubusercontent.com/Titan-Pathfinder/titan-api-claude-skills/main/SKILL.md Copy import { V1Client } from "@titanexchange/sdk-ts"; import bs58 from "bs58"; const client = await V1Client.connect(`${WS_URL}?auth=${AUTH_TOKEN}`); const { stream } = await client.newSwapQuoteStream({ swap: { inputMint: bs58.decode("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), outputMint: bs58.decode("So11111111111111111111111111111111111111112"), amount: BigInt(100_000_000), // 100 USDC — must be BigInt! }, transaction: { userPublicKey: bs58.decode(USER_PUBLIC_KEY), }, }); for await (const quotes of stream) { console.log(quotes); } Copy cd examples npm install cp .env.example .env # Edit .env with your credentials npm run stream-sdk # SDK streaming npm run stream-raw # Raw WebSocket npm run proxy # Backend proxy --- # NewSwapQuoteStream | Developer Docs | Titan **Opens a stream of live swap quotes.** The server responds with a stream ID and begins pushing [`StreamData`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#message-envelope-types) messages at the configured interval until the stream is [stopped](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream) or the connection closes. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#request) Request ------------------------------------------------------------------------------------------------------------------------------ The request is a `SwapQuoteRequest` with three sub-objects: `swap` (what to quote), `transaction` (wallet context for building instructions), and `update` (optional stream tuning). Rust TypeScript Copy struct SwapQuoteRequest { /// Parameters for the swap. swap: SwapParams, /// Parameters for transaction generation. transaction: TransactionParams, /// Parameters for the stream of quote updates. update: Option, } struct SwapParams { /// Address of the input mint of the swap. inputMint: Pubkey, /// Address of the desired output token for the swap. outputMint: Pubkey, /// Raw number of tokens to swap, not scaled by decimals. amount: u64, /// Swap mode for how the amount should be interpreted. /// Either ExactIn or ExactOut, defaults to ExactIn. swapMode: Option, /// Allowed slippage in basis points. slippageBps: Option, /// If set, constrain quotes to the given set of DEXes. dexes: Option>, /// If set, exclude the following DEXes when determining routes. excludeDexes: Option>, /// If set to true, only direct routes between the input and output mint /// will be considered. onlyDirectRoutes: Option, /// If set to true, only quotes with transactions that fit within the size /// constraint are returned. addSizeConstraint: Option, /// The size constraint to use when `addSizeConstraint` is set. /// Default is set by the server, normally slightly less than 1232 /// to allow room for additional instructions. sizeConstraint: Option, /// If set, limit quotes to the given set of provider IDs. providers: Option>, /// If set, limit total number of accounts used by routes. /// If not set, up to 64 accounts are allowed. /// Available Since: v1.1 accountsLimitTotal: Option, /// If set, limit total number of writable accounts used by routes. /// If not set, up to 64 writable accounts are allowed. /// Available Since: v1.1 accountsLimitWritable: Option, /// A template of instructions and ALTs the router must leave room for in /// the transaction. Titan generates a swap that fits alongside them within /// Solana's size limits. See "Transaction Template" below. /// INCOMPATIBLE with `accountsLimitTotal`, `accountsLimitWritable`, and /// `sizeConstraint` — passing both returns an error. /// Available Since: v1.2 transactionTemplate: Option, } struct TransactionParams { /// Public key of the user requesting the swap. /// NOTE: Setting this to a read-only system account will result in /// simulations failing and no quotes being returned. userPublicKey: Pubkey, /// If true, close the input token account as part of the transaction. closeInputTokenAccount: Option, /// If true, an idempotent ATA will be added to the transactions. createOutputTokenAccount: Option, /// Token account for the output mint used to collect fees. /// Must already exist on-chain. feeAccount: Option, /// Fee amount to take, in basis points. /// If not specified, default fee for the requester is used. feeBps: Option, /// Whether the fee should be taken in terms of the input mint. /// Default is false (fee taken from output mint). feeFromInputMint: Option, /// Token account into which to place the output of the swap. /// If not specified, the user's ATA is used. outputAccount: Option, /// If true, leave the output as wrapped SOL (the wSOL SPL token) instead of /// unwrapping it to native SOL. Only has an effect when the output mint is /// wSOL; ignored otherwise. Default: false (output unwrapped to native SOL). /// Requires `titanSwapVersion: 3`. outputWsol: Option, /// Router version to use: `3` for V3, otherwise V2. See "Swap V3" below. titanSwapVersion: Option, /// Separate funder for SOL-denominated costs of the swap — network fees, /// rent for any ATA the router creates (wSOL wrap ATA, output ATA), and /// the destination for the rent refund when the wSOL ATA is closed. /// The payer must sign the transaction alongside the user for it to land. /// Requires `titanSwapVersion: 3`. payer: Option, /// Token account that receives any surplus when realized DEX output /// exceeds the quoted `outAmount`. The skim is capped at 10 bps of /// `outAmount` — any surplus beyond that stays with the user. /// MUST be a token account of the output mint — passing a wallet pubkey /// or wrong-mint token account fails the transaction at execution. /// Requires `titanSwapVersion: 3`. positiveSlippageFeeReceiver: Option, } struct QuoteUpdateParams { /// How often the server should send updates, in milliseconds. intervalMs: Option, /// Maximum number of quotes per update. /// If more are available, the worst are filtered out. numQuotes: Option, } [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#response) Response -------------------------------------------------------------------------------------------------------------------------------- A successful response includes a [`QuoteSwapStreamResponse`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) with the confirmed update interval, and a [`StreamStart`](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types#message-envelope-types) with the stream ID: * `**intervalMs**` (`u64`) — The actual interval the server will use for this stream. * `**stream.id**` (`u32`) — **Use this ID to** [**stop the stream**](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream) **later.** * `**stream.dataType**` — Always `"SwapQuotes"`. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#stream-updates) Stream updates -------------------------------------------------------------------------------------------------------------------------------------------- After the stream opens, the server pushes `StreamData` messages at the confirmed interval. Each contains a `SwapQuotes` payload — **a** `**quotes**` **map keyed by provider ID** where each value is a `SwapRoute` with quote details and executable instructions. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#metadata.expectedwinner) `metadata.ExpectedWinner` Each `SwapQuotes` update includes a `metadata` object with an `ExpectedWinner` field — **Titan's recommendation for the best slippage-adjusted route.** Rather than sorting by raw `outAmount`, use this to select the route that Titan expects to deliver the best actual execution after factoring in slippage, simulation results, and route reliability. Rust TypeScript `**quotes**` **is a map, not an array.** Not every provider appears in every update — iterate with `Object.entries`. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#transaction-template) Transaction Template -------------------------------------------------------------------------------------------------------------------------------------------------------- `transactionTemplate` lets you reserve room in the transaction for instructions and address lookup tables that you plan to prepend or append yourself — a custom fee transfer, an oracle update, an app-specific log, etc. Titan factors the template into route sizing so the final transaction still fits within Solana's limits. Rust TypeScript `**transactionTemplate**` **is incompatible with** `**accountsLimitTotal**`**,** `**accountsLimitWritable**`**, and** `**sizeConstraint**`**.** The template is the sizing constraint — passing both returns an error. **Wire format uses single-letter field names for space efficiency.** Each `Instruction` serializes as `{ p, a, d }` (programId / accounts / data), each `AccountMeta` as `{ p, s, w }` (pubkey / isSigner / isWritable), each `AddressLookupTableAccount` as `{ p, a }` (key / addresses). Pubkeys are raw 32-byte arrays, not Base58 strings. See the [Transaction Template guide](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/transaction-template) for a worked example. **Available Since:** v1.2 [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#swap-v3) Swap V3 ------------------------------------------------------------------------------------------------------------------------------ Swap V3 is the newer routing version of the Titan Exchange Router (`T1TANpTeScyeqVzzgNViGDNrkQ6qHz9KrSBS4aNXvGT`). Opt in by setting `titanSwapVersion: 3` in `TransactionParams` — this unlocks the `payer`, `positiveSlippageFeeReceiver`, and `outputWsol` fields. Titan returns V2 by default and will switch to V3 in a future release. Until then, every request that needs the V3-only fields must set `titanSwapVersion: 3` explicitly. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#example) Example ------------------------------------------------------------------------------------------------------------------------------ See [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection#sending-a-request) for `sendRequest` and `decodeMessage` setup. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#related-pages) Related pages ------------------------------------------------------------------------------------------------------------------------------------------ * [StopStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream) — stop an active stream by its ID * [Stream & Execute a Swap](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/stream-and-execute) — full guide with transaction building, signing, and error handling * [Configure Routing](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/configure-routing) — venue and provider filtering * [Fee Collection](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/fee-collection) — collect platform fees on swaps * [Types Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) — `SwapQuoteRequest`, `SwapRoute`, `SwapQuotes`, and all type definitions [PreviousGetInfo](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/get-info) [NextStopStream](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/stop-stream) Last updated 8 days ago * [Request](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#request) * [Response](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#response) * [Stream updates](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#stream-updates) * [metadata.ExpectedWinner](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#metadata.expectedwinner) * [Transaction Template](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#transaction-template) * [Swap V3](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#swap-v3) * [Example](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#example) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/new-swap-quote-stream#related-pages) Copy interface SwapQuoteRequest { // Parameters for the swap. swap: SwapParams; // Parameters for transaction generation. transaction: TransactionParams; // Parameters for the stream of quote updates. update?: QuoteUpdateParams; } interface SwapParams { // Address of input mint for the swap. inputMint: Pubkey; // Address of output mint of the swap. outputMint: Pubkey; // Raw number of tokens to swap, not scaled by decimals. amount: number; // Whether amount is in terms of inputMint or outputMint. // Defaults to ExactIn. swapMode?: SwapMode; // Maximum allowed slippage, in basis points. slippageBps?: number; // If set, constrain quotes to the given set of DEXes. dexes?: string[]; // If set, exclude the following DEXes when determining routes. excludeDexes?: string[]; // If true, only direct routes will be considered. onlyDirectRoutes?: boolean; // If true, only quotes that fit within the size constraint are returned. addSizeConstraint?: boolean; // The size constraint to use when `addSizeConstraint` is set. // Default is set by the server, normally slightly less than 1232. sizeConstraint?: number; // If set, limit quotes to the given set of provider IDs. providers?: string[]; // Max total accounts per route. Default: 64. // Available Since: v1.1 accountsLimitTotal?: number; // Max writable accounts per route. Default: 64. // Available Since: v1.1 accountsLimitWritable?: number; // A template of instructions and ALTs the router must leave room for in // the transaction. Titan generates a swap that fits alongside them within // Solana's size limits. See "Transaction Template" below. // INCOMPATIBLE with `accountsLimitTotal`, `accountsLimitWritable`, and // `sizeConstraint` — passing both returns an error. // Available Since: v1.2 transactionTemplate?: TransactionTemplate; } interface TransactionParams { // Public key of the user requesting the swap. // NOTE: Setting this to a read-only system account will result in // simulations failing and no quotes being returned. userPublicKey: Pubkey; // If true, close the input token account as part of the transaction. closeInputTokenAccount?: boolean; // If true, an idempotent ATA creation is added to the transaction. createOutputTokenAccount?: boolean; // Token account for collecting fees. Must already exist on-chain. feeAccount?: Pubkey; // Fee amount in basis points. If not specified, default fee is used. feeBps?: number; // If true, fee is taken from input mint. Default: false (output mint). feeFromInputMint?: boolean; // Custom output token account. Defaults to the user's ATA. outputAccount?: Pubkey; // If true, leave the output as wrapped SOL (the wSOL SPL token) instead of // unwrapping it to native SOL. Only has an effect when the output mint is // wSOL; ignored otherwise. Default: false (output unwrapped to native SOL). // Requires `titanSwapVersion: 3`. outputWsol?: boolean; // Router version to use: `3` for V3, otherwise V2. See "Swap V3" below. titanSwapVersion?: number; // Separate funder for SOL-denominated costs of the swap — network fees, // rent for any ATA the router creates (wSOL wrap ATA, output ATA), and // the destination for the rent refund when the wSOL ATA is closed. // The payer must sign the transaction alongside the user for it to land. // Requires `titanSwapVersion: 3`. payer?: Pubkey; // Token account that receives any surplus when realized DEX output // exceeds the quoted `outAmount`. The skim is capped at 10 bps of // `outAmount` — any surplus beyond that stays with the user. // MUST be a token account of the output mint — passing a wallet pubkey // or wrong-mint token account fails the transaction at execution. // Requires `titanSwapVersion: 3`. positiveSlippageFeeReceiver?: Pubkey; } interface QuoteUpdateParams { // How often the server should send updates, in milliseconds. intervalMs?: number; // Maximum number of quotes per update. numQuotes?: number; } Copy struct SwapQuotes { /// Unique identifier for the quote. id: String, /// Address of the input mint for this quote. inputMint: Pubkey, /// Address of the output mint for this quote. outputMint: Pubkey, /// What swap mode was used for the quotes. swapMode: SwapMode, /// Amount used for the quotes. amount: u64, /// A mapping of a provider identifier to their quoted route. quotes: HashMap, /// Metadata including the expected winning provider (when DART is enabled). metadata: Option, } struct SwapQuotesMetadata { /// The provider Titan expects to deliver the best slippage-adjusted execution. ExpectedWinner: Option, } struct SwapRoute { /// How many input tokens go through this route. inAmount: u64, /// How many output tokens are expected. outAmount: u64, /// Slippage incurred, in basis points. slippageBps: u16, /// Platform fee information, if a fee is charged. platformFee: Option, /// Steps that comprise this route. steps: Vec, /// Instructions needed to execute the route. /// May not be provided if a full transaction is provided instead. instructions: Vec, /// Address lookup tables necessary to load. addressLookupTables: Vec, /// Context slot for the route. contextSlot: Option, /// Time taken to generate the quote in nanoseconds. timeTakenNs: Option, /// If this route expires by time, millisecond UNIX timestamp. expiresAtMs: Option, /// If this route expires by slot, last valid slot. expiresAfterSlot: Option, /// Compute units this transaction is expected to consume. computeUnits: Option, /// Recommended compute unit budget. /// Higher than computeUnits to account for on-chain fluctuations. computeUnitsSafe: Option, /// Transaction for the user to sign, if instructions are not provided. transaction: Option>, /// Provider-specific reference ID for this quote. /// Mainly provided by RFQ-based providers. reference_id: Option, } struct RoutePlanStep { /// Which AMM is being executed on at this step. ammKey: Pubkey, /// Label for the protocol (e.g. "Raydium AMM", "Phoenix"). label: String, /// Input mint for this step. inputMint: Pubkey, /// Output mint for this step. outputMint: Pubkey, /// Input tokens expected to go through this step. inAmount: u64, /// Output tokens expected from this step. outAmount: u64, /// Proportion of order flow in parts per billion. allocPpb: u32, /// Mint of the fee token, if applicable. feeMint: Option, /// Fee amount charged by the venue. feeAmount: Option, /// Context slot for the pool data. contextSlot: Option, } struct PlatformFee { /// Amount of tokens taken as a fee. amount: u64, /// Fee percentage, in basis points. fee_bps: u8, } Copy interface SwapQuotes { // Unique Quote identifier. id: string; // Address of the input mint. inputMint: Uint8Array; // Address of the output mint. outputMint: Uint8Array; // What swap mode was used. swapMode: SwapMode; // Amount used for the quotes. amount: number; // A mapping of provider identifier to their quoted route. quotes: { [key: string]: SwapRoute }; } interface SwapRoute { // Input tokens going through this route. inAmount: number; // Expected output tokens. outAmount: number; // Slippage incurred, in basis points. slippageBps: number; // Platform fee information, if charged. platformFee?: PlatformFee; // Steps that comprise this route. steps: RoutePlanStep[]; // Instructions needed to execute the route. instructions: Instruction[]; // Address lookup tables necessary to load. addressLookupTables: Pubkey[]; // Context slot for the route. contextSlot?: number; // Time taken to generate the quote in nanoseconds. timeTaken?: number; // If this route expires by time, millisecond UNIX timestamp. expiresAtMs?: number; // If this route expires by slot, last valid slot. expiresAfterSlot?: number; // Compute units this transaction is expected to consume. computeUnits?: number; // Recommended compute unit budget. computeUnitsSafe?: number; // Transaction for the user to sign, if instructions not provided. transaction?: Uint8Array; // Provider-specific reference ID for this quote. referenceId?: string; } interface RoutePlanStep { // Which AMM is being executed on at this step. ammKey: Uint8Array; // Label for the protocol (e.g. "Raydium AMM", "Phoenix"). label: string; // Input mint for this step. inputMint: Uint8Array; // Output mint for this step. outputMint: Uint8Array; // Input tokens expected to go through this step. inAmount: number; // Output tokens expected from this step. outAmount: number; // Proportion of order flow in parts per billion. allocPpb: number; // Mint of the fee token, if applicable. feeMint?: Uint8Array; // Fee amount charged by the venue. feeAmount?: number; // Context slot for the pool data. contextSlot?: number; } interface PlatformFee { // Amount of tokens taken as a fee. amount: number; // Fee percentage, in basis points. fee_bps: number; } Copy struct TransactionTemplate { /// Instructions to reserve space for. It is assumed that you have /// included the input mint and output mint account creation/deletion /// instructions when necessary. i: Vec, /// Address lookup tables used in the instructions. Provide them in the /// same order you'll use when compiling the message — Solana uses ALTs /// greedily, so their effect depends on ordering. Titan extends this /// vector with any ALTs it uses for the swap. a: Vec, /// Additional account metas to include in sizing calculations. m: Vec, } Copy interface TransactionTemplate { // Instructions to reserve space for. It is assumed that you have // included the input mint and output mint account creation/deletion // instructions when necessary. i: Instruction[]; // Address lookup tables used in the instructions. Provide them in the // same order you'll use when compiling the message — Solana uses ALTs // greedily, so their effect depends on ordering. Titan extends this // array with any ALTs it uses for the swap. a: AddressLookupTableAccount[]; // Additional account metas to include in sizing calculations. m: AccountMeta[]; } Copy { "transaction": { "userPublicKey": "72neGwRAi6QWsFQjy3PkDuYBC5GNCRwC2aUMGcrkoJuP", "titanSwapVersion": 3, "payer": "Gb4WdRjp7orviHSRz88pa3y9UkArLHR4gWWSv5HP31ZW", "positiveSlippageFeeReceiver": "LzEWGGE7aGC3XVqmMhiTZsByJBhr16dJpJoNY5RuWQ5" } } Copy import bs58 from 'bs58'; // Pubkeys are 32-byte binary — decode from Base58 before sending const SOL = bs58.decode('So11111111111111111111111111111111111111112'); const USDC = bs58.decode('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); const userPublicKey = bs58.decode('YOUR_WALLET_PUBLIC_KEY'); // Open a swap quote stream — server will push updates at the configured interval await sendRequest(ws, requestId++, { NewSwapQuoteStream: { swap: { inputMint: SOL, outputMint: USDC, amount: 1_000_000_000n, // 1 SOL in lamports — must be BigInt slippageBps: 50, // 0.5% slippage tolerance }, transaction: { userPublicKey, // Needed for transaction/instruction generation }, }, }); // Track the stream ID so we can stop it later let streamId: number | undefined; ws.on('message', async (raw: Buffer) => { const msg = await decodeMessage(raw); // Stream opened — capture the stream ID and confirmed interval if ('Response' in msg && 'NewSwapQuoteStream' in msg.Response.data) { streamId = msg.Response.stream.id; console.log(`Stream ${streamId} open — interval: ${msg.Response.data.NewSwapQuoteStream.intervalMs}ms`); } // Quote update — quotes is a map keyed by provider ID, not an array if ('StreamData' in msg) { const quotes = msg.StreamData.payload.SwapQuotes; for (const [provider, route] of Object.entries(quotes.quotes as Record)) { if (route.instructions?.length) { console.log(`${provider}: ${route.outAmount} out`); } } } // RPC error — check code and message for details if ('Error' in msg) { console.error(`Error ${msg.Error.code}: ${msg.Error.message}`); } // Stream closed — check errorCode/errorMessage if present if ('StreamEnd' in msg) { console.log(`Stream ${msg.StreamEnd.id} ended`); ws.close(); } }); --- # Error Codes | Developer Docs | Titan When a request fails, the server returns a `ResponseError` with a numeric `code` and a human-readable `message`. On **Titan Direct**, errors arrive as an `Error` variant of `ServerMessage`. On **Titan Gateway**, errors are returned as HTTP status codes with a MessagePack body. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#error-response-format) Error response format ----------------------------------------------------------------------------------------------------------------------------------------- Titan Direct Titan Gateway Copy { Error: { requestId: number; // Matches the ID of the original request code: number; // Numeric error code for programmatic handling message: string; // Human-readable description for logging/debugging } } The `message` field contains a specific, actionable description of the error. **Use the** `**code**` **for programmatic handling** and the `message` for logging and debugging. Status Description `400` Invalid parameters — malformed pubkey, missing required field, or invalid value. `401` Missing or invalid authentication token. `404` No routes found for this swap pair. [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#stream-errors) Stream errors ------------------------------------------------------------------------------------------------------------------------- Streams can end with an error via the `StreamEnd` message: Copy { StreamEnd: { id: number; // The stream ID that has ended errorCode?: number; // Present only if the stream ended due to an error errorMessage?: string; // Human-readable reason for the error, if any } } A `StreamEnd` **without** `errorCode` indicates a clean shutdown (e.g. after `StopStream`). A `StreamEnd` **with** `errorCode` means something went wrong and you should inspect the message. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#websocket-close-codes) WebSocket close codes ----------------------------------------------------------------------------------------------------------------------------------------- The server may close the WebSocket connection with a specific close code: * `**3002**` — **Protocol error.** The client sent an invalid or unsupported protocol string during negotiation, or violated the wire protocol after connecting. Reconnect with a valid `Sec-WebSocket-Protocol` header. * `**1000**` — Normal closure. The server shut down gracefully. * `**1001**` — Going away. The server is restarting or shutting down for maintenance. * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#sdk-error-classes) SDK error classes --------------------------------------------------------------------------------------------------------------------------------- **If you're using the** [`**@titanexchange/sdk-ts**`](https://www.npmjs.com/package/@titanexchange/sdk-ts) **TypeScript SDK**, errors are thrown as typed classes you can catch and inspect: ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#connection-errors) Connection errors * `**ConnectionClosed**` — The WebSocket was closed unexpectedly. Properties: `code` (close code), `reason` (close reason string), `wasClean` (whether the close was clean). * `**ConnectionError**` — Failed to establish or maintain the WebSocket connection. Property: `cause` (underlying error). * `**InvalidProtocolError**` — The server selected an unsupported protocol string during negotiation. Property: the invalid protocol string. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#rpc-errors) RPC errors * `**ErrorResponse**` — The server returned an error for a specific request. Properties: `response.code` (numeric error code), `response.message` (human-readable description), `response.requestId`. * `**StreamError**` — A stream ended with an error. Properties: `streamId`, `errorCode`, `errorMessage`. * `**ProtocolError**` — A wire-level protocol violation. Properties: `reason`, `data`. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#codec-errors) Codec errors * `**DecodeError**` — Failed to decode a MessagePack message. Properties: `reason`, `value`. ### [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#recommended-pattern) Recommended pattern * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#handling-errors) Handling errors ----------------------------------------------------------------------------------------------------------------------------- * **Authentication errors** — Verify your token is valid, not expired, and includes the required JWT claims (`iss`, `sub`, `aud`, `exp`, `iat`). See [Connection & Negotiation](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/direct/connection) . * **Invalid parameters** — Check that pubkeys are valid base58, amounts are positive integers, and all required fields are present. * **No routes found** — The swap pair may have insufficient liquidity, or routing constraints (`dexes`, `excludeDexes`, `onlyDirectRoutes`) may be too restrictive. **Try relaxing your filters** before assuming the pair is unsupported. * **Stream errors** — When a stream ends unexpectedly, re-open it. **Stream IDs from a previous connection are not valid after reconnect.** For reconnection patterns, see [Error Handling & Reconnect](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling) . * * * [](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#related-pages) Related pages ------------------------------------------------------------------------------------------------------------------------- * [Error Handling & Reconnect](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/guides/error-handling) — retry strategies, backoff logic, and reconnect patterns * [Wire Protocol](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/wire-protocol) — message envelope format and framing details * [Types Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) — Types Reference — index of all type definitions [PreviousTypes Reference](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/types) [NextOverview](https://titan-exchange.gitbook.io/titan/developer-doc/dart-swap-api/overview) Last updated 2 months ago * [Error response format](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#error-response-format) * [Stream errors](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#stream-errors) * [WebSocket close codes](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#websocket-close-codes) * [SDK error classes](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#sdk-error-classes) * [Connection errors](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#connection-errors) * [RPC errors](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#rpc-errors) * [Codec errors](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#codec-errors) * [Recommended pattern](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#recommended-pattern) * [Handling errors](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#handling-errors) * [Related pages](https://titan-exchange.gitbook.io/titan/developer-doc/swap-api/reference/error-codes#related-pages) Copy import { ErrorResponse, StreamError, ConnectionClosed } from '@titanexchange/sdk-ts'; try { // ... SDK operations } catch (err) { if (err instanceof ErrorResponse) { // Server rejected the request — check code for programmatic handling console.error(`RPC error ${err.response.code}: ${err.response.message}`); } else if (err instanceof StreamError) { // Stream ended abnormally — re-open it console.error(`Stream ${err.streamId} error: ${err.errorMessage}`); } else if (err instanceof ConnectionClosed) { // WebSocket dropped — reconnect with backoff console.warn(`Connection closed: code=${err.code}, clean=${err.wasClean}`); } } --- # Titan Page not found -------------- The page you are looking for doesn't exist. [Go to homepage](https://titan-exchange.gitbook.io/titan/developer-doc) ---