> For the complete documentation index, see [llms.txt](https://hinkal-team.gitbook.io/hinkal/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hinkal-team.gitbook.io/hinkal/hinkal-mobile-sdk/ios/guides/swaps.md).

# Swaps

A private swap trades one token for another entirely inside the private balance, with no public trace of the trade. It runs server-side through a Hinkal relayer.

SDK calls take an `NSError` out-parameter, wrapped here with the `call` helper from Getting Started.

### Quote first

Get a quote before swapping. Use `getEvmSwapPrices` on EVM chains, `getSolanaSwapPrices` on Solana:

```swift
let quoteJSON = try call { hinkal.getEvmSwapPrices(chainId, inAmount: inWei, inTokenAddr: inToken, outTokenAddr: outToken, error: &$0) }
```

The quote returns the swap data you pass into `swap`.

### Basic Swap

```swift
let txHash = try call {
    hinkal.swap(
        chainId,
        tokenAddrsJSON: "[\"\(inToken)\", \"\(outToken)\"]",
        amountsWeiJSON: "[\"\(inWei)\"]",
        actionID: actionID,
        swapData: swapData,
        feeToken: inToken,
        feeStructureJSON: "",
        error: &$0
    )
}
print("Swap tx:", txHash)
```

On Solana use `swapSolana(...)`, which omits `actionID`:

```swift
let txHash = try call {
    hinkal.swapSolana(
        chainId,
        tokenAddrsJSON: "[\"\(inToken)\", \"\(outToken)\"]",
        amountsWeiJSON: "[\"\(inWei)\"]",
        swapData: swapData,
        feeToken: outToken,
        feeStructureJSON: "",
        error: &$0
    )
}
```

### Parameters

<table data-search="false"><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>chainID</code></td><td><code>Int64</code></td><td>Target chain id.</td></tr><tr><td><code>tokenAddrsJSON</code></td><td><code>String</code></td><td>JSON array: input token, then output token.</td></tr><tr><td><code>amountsWeiJSON</code></td><td><code>String</code></td><td>JSON array with the input amount in wei.</td></tr><tr><td><code>actionID</code></td><td><code>String</code></td><td>DEX action id from the quote (EVM only).</td></tr><tr><td><code>swapData</code></td><td><code>String</code></td><td>Encoded swap data from the quote.</td></tr><tr><td><code>feeToken</code></td><td><code>String</code></td><td>Token the fee is paid in.</td></tr><tr><td><code>feeStructureJSON</code></td><td><code>String</code></td><td>Fee quote, or empty for defaults.</td></tr></tbody></table>

### Error Handling

```swift
do {
    let txHash = try call {
        hinkal.swap(chainId, tokenAddrsJSON: "[\"\(inToken)\", \"\(outToken)\"]", amountsWeiJSON: "[\"\(inWei)\"]",
                    actionID: actionID, swapData: swapData, feeToken: inToken, feeStructureJSON: "", error: &$0)
    }
} catch {
    print("Swap failed:", error.localizedDescription)
}
```

### Best Practices

#### 1. Always quote immediately before swapping

Quotes move. Fetch a fresh quote with `getEvmSwapPrices` / `getSolanaSwapPrices` right before calling `swap`, and pass its `swapData` unchanged.

```swift
let quote = try call { hinkal.getEvmSwapPrices(chainId, inAmount: inWei, inTokenAddr: inToken, outTokenAddr: outToken, error: &$0) }
```

#### 2. Use the right method per chain

Use `swap` on EVM/Tron (it takes `actionID`) and `swapSolana` on Solana (no `actionID`). Branch on `MobileIsSolanaChain(chainId)`.

#### 3. Refresh the balance afterward

```swift
 = try call { hinkal.getTotalBalance(chainId, userKeysSignature: signature,
    ethAddress: address, resetCache: true, useBlockedUtxos: false, error: &$0) }
```
