From titan-swap-api
Titan Swap API and Solana DEX-aggregation integration guide. Use whenever the user mentions Titan, Argos, or DART, or asks about streaming swap quotes, REST swap quotes, MessagePack-encoded Solana swap APIs, route selection (`metadata.ExpectedWinner`), Swap V3 (`payer`, `positiveSlippageFeeReceiver`), or building Solana swap/aggregator functionality — even if they don't explicitly say "Titan." Also use for DART-specific routing (1 bps fee, BBO guarantee, on-chain re-optimization at execution time).
How this skill is triggered — by the user, by Claude, or both
Slash command
/titan-swap-api:titan-swap-apiThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
When this skill is invoked, hold off on code generation and run the short interview below first (`AskUserQuestion` if available, otherwise inline questions). The reason: Titan has three distinct surfaces (Direct WebSocket, Gateway REST, DART JSON) that require different SDKs, encodings, and even different field shapes. Generating code before knowing which surface the user wants almost always pr...
When this skill is invoked, hold off on code generation and run the short interview below first (AskUserQuestion if available, otherwise inline questions). The reason: Titan has three distinct surfaces (Direct WebSocket, Gateway REST, DART JSON) that require different SDKs, encodings, and even different field shapes. Generating code before knowing which surface the user wants almost always produces something they have to throw away. The interview takes 30 seconds and saves a rewrite.
Step 1 — Credentials check:
Ask the user:
Titan Swap API skill loaded.
Do you have your Titan API credentials ready? (
TITAN_ENDPOINT,TITAN_API_KEY)
If no — tell them to get credentials from the Titan team before proceeding, then continue with the questions below so the setup is ready once they have them.
Note on wallet pubkeys — don't ask the user for theirs as if it were a credential. The wallet pubkey is a runtime value the app already has access to in three standard ways:
@solana/wallet-adapter-react, Phantom, Solflare, etc.) in frontend appsKeypair loaded from a private key in scripts/CLIsWhen generating code, detect how the user's project handles wallets and use that pattern. Asking for the pubkey directly is a sign you haven't read their wallet setup yet — start there.
Step 2 — Ask which API they want:
Use the AskUserQuestion tool with these options:
Question: "Which Titan API do you want to use?"
@titanexchange/sdk-ts or raw WebSocket with MessagePack.Explain: Direct and Gateway both route through Argos and deliver the same quote quality. DART is a separate dedicated endpoint that uses only the DART provider — pick it when you specifically want DART's on-chain BBO guarantee, or for free testing without credentials.
If the user picks DART, surface this up front so they aren't surprised later:
The free public DART endpoint allows 1 request per second per IP. If you need more throughput on a DART-only path, please reach out to the Titan team for a partner DART API key — apply at https://tally.so/r/1AvYeL or contact the team directly. (Reminder: Gateway and Direct already include DART as one of their providers, and
metadata.ExpectedWinnerwill pickTitan-DARTautomatically when it's the best route — so a higher-tier general API key is often a simpler path than a DART-only key.)
Step 3 — Ask how they want to integrate:
Use the AskUserQuestion tool with these options:
If they chose Titan Direct:
@titanexchange/sdk-ts. Handles WebSocket connection, MessagePack encoding, and stream management for you. Best for TypeScript/Node.js projects.If they chose Titan Gateway:
If they chose DART Public API:
fetch calls. No SDK, no MessagePack. Minimal setup.Step 4 — Ask what they need from the API:
Use the AskUserQuestion tool with these options:
For Titan Direct:
For Titan Gateway:
For DART Public API:
POST /swap returns transaction-ready instructions (compute budget pre-prepended).GET /markets. Use this if the user's pair isn't in the canned list.GET /health. Use for uptime probes from a backend.Step 5 — If they chose "Into existing project":
Before writing any code:
Step 6 — Generate code:
Now generate code, tailored to what the user told you in steps 1–5. Match their:
The goal isn't to drop in a generic example — it's to produce code that fits the user's codebase well enough to keep. If you find yourself writing boilerplate that ignores their conventions, stop and re-read their files.
Titan is a meta-aggregator for Solana that collects swap quotes from multiple providers and routes through Argos, Titan's proprietary routing engine. It offers two APIs — Titan Direct (WebSocket) and Titan Gateway (REST) — with identical routing quality.
The bulk of this skill lives in five reference files under references/. SKILL.md keeps just the agent interview, cross-API concepts that apply to all three surfaces, and short pointer blocks. Load only what you need for the task at hand.
| If the user is working on… | Read |
|---|---|
| Titan Gateway (REST) — quotes, prices, discovery endpoints, Swap V3 with REST | references/gateway.md |
| Titan Direct (WebSocket) — SDK, raw WebSocket, multi-stream, Swap V3 with Direct | references/direct.md |
| DART Public API — free JSON endpoint, supported pairs, partner keys | references/dart.md |
| Routing constraints, fee collection, error handling, reconnection, browser proxy patterns | references/routing-errors-deployment.md |
MessagePack details, compact {p,a,d} instruction format, non-TS language ports | references/wire-protocol.md |
Rule of thumb: load a reference before generating any non-trivial code for that surface. The recap blocks below each # H1 are deliberately short — they cover gotchas a developer needs to avoid mistakes, not enough to write a full integration.
Both route through the same Argos engine and return the same quote types. The difference is interface, not routing quality.
| Titan Direct | Titan Gateway | |
|---|---|---|
| Interface | WebSocket | REST |
| Quote delivery | Streaming — continuous updates | Per-request — one response per call |
| Connection | Persistent | Stateless |
| Best for | Trading bots, market makers, algo traders | Wallets, dApps, backend services |
| SDK | @titanexchange/sdk-ts | fetch + @msgpack/msgpack |
Every Titan Direct RPC method has a corresponding Gateway REST endpoint:
| 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 |
GET /api/v1/quote/price | GetSwapPrice |
Token amounts: Always raw amounts (atoms) as BigInt:
BigInt(1_000_000) (6 decimals)BigInt(1_000_000_000) (9 decimals)BigInt(100_000) (5 decimals)CRITICAL: Amount must be passed as BigInt for Titan Direct, or as a string for Titan Gateway query params.
Tip: Consider validating amounts before encoding:
const UINT64_MAX = BigInt("18446744073709551615"); // 2^64 - 1
function validateAmount(input: number | bigint): bigint {
if (typeof input === "number" && !Number.isInteger(input)) {
throw new Error(`Amount must be a whole number (got ${input}). Token amounts are in raw atoms.`);
}
const amount = BigInt(input);
if (amount < 0n || amount > UINT64_MAX) {
throw new Error(`Amount out of uint64 range [0, ${UINT64_MAX}] (got ${amount}).`);
}
return amount;
}
Users need from the Titan team:
TITAN_ENDPOINT — API endpoint URL
wss://... (WebSocket)https://... (REST)TITAN_API_KEY — JWT authentication tokenAuthentication methods:
Authorization: Bearer <token>?auth=<token> (for WebSocket or browser clients)The user's wallet public key is NOT a Titan credential — it comes from their existing wallet setup:
wallet.publicKey from @solana/wallet-adapter-react or similarKeypair.fromSecretKey(...) then .publicKeyWhen generating code, use whichever wallet source the user's project already has. Only fall back to process.env.USER_PUBLIC_KEY for standalone scripts with no existing wallet setup.
Full reference:
references/gateway.md. Load it when the user picked Gateway in Step 2 or asks anything about the REST endpoints (/api/v1/quote/swap,/api/v1/quote/price,/api/v1/info,/api/v1/venues,/api/v1/providers), MessagePack-encoded REST responses, or Swap V3 with Gateway.
Quick recap so you don't have to load the reference for trivial questions:
${TITAN_ENDPOINT}/api/v1/...Authorization: Bearer ${TITAN_API_KEY} (or ?auth= query param)Accept: application/vnd.msgpack and decode with Decoder({ useBigInt64: true })data returned in MessagePack as raw bytesmetadata.ExpectedWinner, not by sorting outAmounttitanSwapVersion, payer, positiveSlippageFeeReceiver) — see referenceFull reference:
references/direct.md. Load it when the user picked Direct in Step 2 or asks anything about WebSocket streaming,@titanexchange/sdk-ts,NewSwapQuoteStream, multi-stream management, raw-WebSocket integration, reconnection, compression, or Swap V3 with the Direct SDK.
Quick recap so you don't have to load the reference for trivial questions:
wss://${TITAN_ENDPOINT}/api/v1/ws?auth=${TITAN_API_KEY}@titanexchange/sdk-ts, recommended) or raw WebSocket with manual MessagePackUint8Array in the SDK — decode with bs58.decode(...). Amounts are BigInt.slippageBps lives inside swap; intervalMs and num_quotes live inside update — wrong nesting silently failsStreamData carries quotes (a map keyed by provider, not an array) plus metadata.ExpectedWinnertransaction on NewSwapQuoteStream — see reference for payer / positiveSlippageFeeReceiver semanticsreferences/routing-errors-deployment.md)Full reference:
references/dart.md. Read it before generating code for the DART endpoint.
The DART Swap API is a free public JSON REST endpoint that exclusively uses Titan's DART on-chain routing engine. Plain JSON (not MessagePack), no WebSocket, no API key required for the free tier (1 req/sec per IP).
https://api.titan.exchange/dartGET /health, GET /markets, POST /swapTitan-DART (no metadata.ExpectedWinner — single-provider endpoint)For request/response shapes, the full transaction-build example, supported-pair list, and partner-key headers, load references/dart.md.
Full reference:
references/routing-errors-deployment.md. Load it when the user is configuring routing constraints (DEX include/exclude, direct-only routes), discovering venues/providers, collecting platform fees, debugging error responses (SDK error types, HTTP error codes, reconnection patterns), or deploying Titan in a browser frontend (which requires a backend proxy to keep API keys off the client).
Quick recap:
/api/v1/venues and /api/v1/providers (or SDK equivalents)dexes / excludeDexes / providers / onlyDirectRoutesfeeAccount (must exist on-chain) + feeBps + optional feeFromInputMintTITAN_API_KEY in the frontend — proxy through your backend| Issue | Cause | Solution |
|---|---|---|
| Empty quotes every time | Amount not BigInt (Direct) or wrong format (Gateway) | Direct: Use BigInt(amount). Gateway: Use string "1000000000" |
TypeScript error on slippageBps | Wrong parameter location | Put slippageBps inside swap, not at top level |
TypeScript error on intervalMs | Wrong parameter location | Put intervalMs inside update object |
quotes.quotes is empty | No routes found | Check amount format, then check length |
| Connection closes with 1002 | Protocol error | Ensure MessagePack encoding, not JSON |
| Token mint errors | Wrong format | Direct: use bs58.decode() for Uint8Array. Gateway: use base58 string |
| Wrong amounts | Forgot decimals | USDC: x10^6, SOL: x10^9 |
| Quote expired | Executed too late | Check expiresAtMs, execute within 5 seconds |
| Simulation fails | Various | Check slippage, token accounts, compute units |
| Gateway 404 | No routes | Try relaxing dexes, excludeDexes, onlyDirectRoutes constraints |
| Gateway response unreadable | Decoding as JSON | Response is MessagePack — use @msgpack/msgpack decoder |
slippageBps in swap, intervalMs in update (Direct only)quotes.quotes can be {}Uint8Array (bs58.decode), Gateway uses base58 stringsFull reference:
references/wire-protocol.md. Read it when debugging MessagePack decoding, mapping the compact{p, a, d}instruction format, or implementing Titan in a non-TypeScript language.
Quick recap:
application/vnd.msgpack), not JSON. Decode with @msgpack/msgpack and Decoder({ useBigInt64: true }).{p: programId, a: accounts, d: data} and accounts are {p: pubkey, s: isSigner, w: isWritable}. Pubkeys are 32 raw bytes.data is base64. See references/dart.md.Users can reach out in Telegram group for questions.
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Searches MemPalace before answering questions about past work, people, projects, or prior decisions. Returns verbatim stored content instead of guessing from model memory.
npx claudepluginhub titan-pathfinder/titan-api-claude-skills --plugin titan-swap-api