Add titan meta aggregation swap#439
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 98798a1. Configure here.
| ? "Titan Gateway is temporarily unavailable. Try again shortly." | ||
| : raw; | ||
| setQuoteInfo({ ...emptyQuote(false, mode), error: friendly }); | ||
| } |
There was a problem hiding this comment.
Stale quotes overwrite state
High Severity
Debounced quote requests are not cancelled when inputs change. An older in-flight getTitanSwap or getTitanPrice response can finish after a newer one and call setQuoteInfo, showing wrong output, rate, and winnerRoute for the current amount or pair.
Reviewed by Cursor Bugbot for commit 98798a1. Configure here.
| const isWinner = q.provider === winnerId; | ||
| // basis points behind the best output | ||
| const bpsBehind = | ||
| best > 0 ? ((best - parseInt(q.outAmount)) / best) * 10000 : 0; |
There was a problem hiding this comment.
Race bars use wrong baseline
Medium Severity
Provider comparison treats quotes[0].outAmount as the best output, but the server sorts ExpectedWinner to index zero before sorting by amount. When another provider quotes higher output, bars can exceed 100% and “bps behind” values go negative while the UI still labels the expected winner as “Best.”
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 98798a1. Configure here.
| }: TokenInputProps) { | ||
| const handleMaxClick = () => { | ||
| if (balance !== undefined && balance > 0) onAmountChange(balance.toString()); | ||
| }; |
There was a problem hiding this comment.
MAX uses full SOL balance
Medium Severity
The MAX control sets the input to the full displayed wallet balance. For native SOL, the swap transaction still needs lamports for fees (and often rent), so a “max” swap that passes the UI balance check can fail on-chain even though the app reported sufficient funds.
Reviewed by Cursor Bugbot for commit 98798a1. Configure here.


Note
Medium Risk
New mainnet swap path with real funds at stake; RPC proxy forwards arbitrary JSON-RPC if deployed without access controls, though Gateway/RPC tokens stay server-side.
Overview
Introduces
solana/titan-swap, a greenfield Next.js 16 demo that swaps on Solana via Titan Gateway and QuickNode, with QuickNode dark styling and wallet support (Phantom/Solflare).Server proxies keep secrets off the client:
/api/titan/*decodes MessagePack, normalizes pubkeys/instructions to JSON, and exposes info, providers, venues,/quote/price, and/quote/swap(includingsimulateand multi-providernumQuotes);/api/rpcforwards JSON-RPC for balances, ALTs, send, and HTTP polling confirmation (no WebSocket).The UI debounces quotes—indicative price when disconnected, full swap race when connected—shows competing providers (bps behind leader, latency), hop/venue route splits, slippage and Accurate/Fast routing, then runs build → sign → send → confirm from Titan’s instructions and ALTs. Setup is documented via
.env.local.example, README, and standard Next/Tailwind tooling.Reviewed by Cursor Bugbot for commit 98798a1. Configure here.