> For the complete documentation index, see [llms.txt](https://docs.sodax.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sodax.com/solana/swaps.md).

# Swaps on Solana

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 compete to 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, 137 assets as of July 2026. The [on-Solana asset list](/solana/networks-and-assets.md) 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:

```typescript
const quoteResult = await sodax.swaps.getQuote({
  token_src: sol.address,             // token on Solana
  token_dst: usdc.address,            // token on the destination network
  token_src_blockchain_id: ChainKeys.SOLANA_MAINNET,
  token_dst_blockchain_id: ChainKeys.ARBITRUM_MAINNET,
  amount: 100_000_000n,
  quote_type: 'exact_input',          // or 'exact_output'
});
```

`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](https://docs.sodax.com/developers/how-to/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:

```typescript
const result = await sodax.swaps.swap({
  params: {
    inputToken: sol.address,
    outputToken: usdc.address,
    inputAmount: 100_000_000n,
    minOutputAmount: minOut,
    deadline: 300n,
    allowPartialFill: false,
    srcChainKey: ChainKeys.SOLANA_MAINNET,
    dstChainKey: ChainKeys.ARBITRUM_MAINNET,
    srcAddress: await walletProvider.getWalletAddress(),
    dstAddress: recipient,
    solver: '0x0000000000000000000000000000000000000000',
    data: '0x',
  },
  walletProvider, // ISolanaWalletProvider, narrowed by srcChainKey
});
```

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**. Fetch it with `getIntentSubmitTxExtraData` and pass it as `data` in the relay submission:

```typescript
const extraData = await sodax.swaps.getIntentSubmitTxExtraData({ txHash: hubTxHash });

await sodax.swaps.submitIntent({
  action: 'submit',
  params: {
    chain_id: 'solana',
    tx_hash: spokeTxHash,
    data: extraData.value, // required for Solana sources
  },
});
```

`swap()` does this automatically; most integrations never touch it.

## Error handling

Every method returns `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 (Solver)](https://docs.sodax.com/developers/packages/foundation/sdk/functional-modules/swaps).
