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.
isAllowanceValidalways returnstrue; 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: truereturn aSolanaRawTransactionwhen the source is Solana, TypeScript-narrowed fromsrcChainKey, 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
Preferswap(). 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:
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 usecreateIntent + 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:
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 returnResult<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.