Skip to main content
SODAX swaps are intents, not bridges. Your user signs one transaction on Solana that locks the input and declares what they want on the destination network. Solvers fill it; the SODAX relayer carries proof between Solana, the hub (Sonic), and the destination. If nothing fills, the intent can be cancelled and funds recovered. From your side it is one SDK call. From your user’s side it is one Phantom prompt.

What this looks like on Solana

  • Source: the intent transaction is a normal Solana transaction signed by the user’s wallet. ChainKeys.SOLANA_MAINNET ('solana') identifies the chain everywhere in the SDK.
  • Reach: any solver-compatible asset on any SODAX network is a valid destination, 140 assets today. The on-Solana asset list only bounds what users hold on Solana itself, not what they can swap into.
  • No approvals: there is no ERC-20 style allowance on Solana. isAllowanceValid always returns true; you can go straight from quote to swap.
  • Settlement: output lands on the destination network at dstAddress. Swaps into Solana settle to the user’s address as SPL balances.
  • Raw mode: methods that support raw: true return a SolanaRawTransaction when the source is Solana, TypeScript-narrowed from srcChainKey, if you want to control signing and broadcast yourself.

Quoting

The solver API quotes both directions:
getQuote deducts any configured partner fee before quoting, so quoted_amount is the net output the user actually receives.

Fees

Using SODAX is free to integrate. Two fees can apply to a trade:
  • Base fee: a fixed 0.1% of the input, taken by the protocol. Not configurable; compute it ahead of time with getSolverFee(inputAmount).
  • Your fee: optional platform fee on top, set by you and paid to you. It is the only fee you control. Configure it at SDK setup and check it with getPartnerFee(inputAmount). See Monetize SDK.

Executing

Prefer swap(). It creates the intent on Solana, verifies it landed, submits it to the relay, waits for the packet on the hub, and notifies the solver:
Track progress with getStatus(request), and cancel unfilled intents with cancelIntent. Limit orders (intents without deadlines) work from Solana too, via createLimitOrder.

Orchestrating manually? One Solana-specific step

If you use createIntent + submitIntent instead of swap(), note that Solana (and Bitcoin) intents require relay extra data. createIntent already returns it as relayData — pass that as data in the relay submission:
Only rebuild the extra data if you no longer hold that return value: getIntentSubmitTxExtraData({ intent }) (or reconstructRelayData(intent)) derives it from the intent alone. The { txHash } overload looks the intent up on the hub, so it needs the hub transaction hash — which does not exist until the relay lands. swap() does this automatically; most integrations never touch it.

Error handling

Operations return Result<T> instead of throwing. The core methods (swap, createIntent, postExecution) return a typed SodaxError union you can switch on by error.code.
Full reference, including raw mode, limit orders, cancellation, and the complete error-code table: Swaps.