# Swap Examples

This guide covers how to integrate swaps using the ZO SDK. Swaps are supported on **ZLP**, **SLP**, and **USDZ** via `api.swap()`, `api.swapV2Ptb()`, and fee estimation via `dataAPI.calculateSwapFeeBreakdown()`.

### Overview

A swap flow typically involves:

1. **Estimate fees** – Get the expected fee breakdown for the swap.
2. **Set slippage protection** – Compute `minAmountOut` based on expected output and slippage tolerance.
3. **Build transaction** – Call `api.swap()` to construct the transaction.
4. **Sign and send** – Sign with the wallet and submit to the network.

### Amounts and units

* `fromAmount` is in **atomic units** (raw token units), e.g. `1_000_000` for 1 USDC (6 decimals).
* `minAmountOut` is in **atomic units** of the destination token.
* `calculateSwapFeeBreakdown(fromAmount)` expects atomic units for the source token.

```typescript
// Example: swap 100 USDC (6 decimals) for SUI
const fromAmount = BigInt(100 * 1e6)  // 100_000_000 atomic units
```

### Estimate swap fees

Before building the swap transaction, you can estimate the fee breakdown to display to the user or compute a safe `minAmountOut`.

```typescript
import { SDK, LPToken, Network } from '@zofai/zo-sdk'
import { SuiClient } from '@mysten/sui/client'

const provider = new SuiClient({ url: 'https://fullnode.mainnet.sui.io' })
const network = Network.MAINNET
const apiEndpoint = 'https://api.zofinance.io'
const connectionURL = 'https://hermes.pyth.network'

const slpDataAPI = SDK.createSLPDataAPI(network, provider, apiEndpoint, connectionURL)

// fromAmount in atomic units (e.g. 100 USDC = 100 * 1e6)
const fromToken = 'usdc'
const toToken = 'sui'
const fromAmount = 100 * 1e6

const feeBreakdown = await slpDataAPI.calculateSwapFeeBreakdown(fromToken, toToken, fromAmount)

// feeBreakdown contains:
// - swapValue: notional in USD
// - totalVaultsValue: total vault value in USD
// - rebaseFeeInRate, rebaseFeeOutRate: rates for swap-in and swap-out
// - rebaseFeeInValue, rebaseFeeOutValue: rebase fee amounts in USD
// - swapImpactFeeValue: swap impact fee in USD
// - emaVolatilityFeeValue: EMA volatility fee in USD
// - totalFeeValue: sum of all fee components
// - totalFeeRate: totalFeeValue / swapValue

console.log(`Total fee: ${feeBreakdown.totalFeeValue.toFixed(4)} USD`)
console.log(`Fee rate: ${(feeBreakdown.totalFeeRate * 100).toFixed(2)}%`)
```

### Build and submit swap transaction

Use the **API** instance to build the swap transaction. You need:

* `fromToken`, `toToken` – token identifiers (e.g. `'usdc'`, `'sui'`).
* `fromAmount` – amount in atomic units (bigint).
* `fromCoinObjects` – owned coin object IDs for the source token.
* `minAmountOut` – optional; minimum output amount in atomic units (slippage protection).

```typescript
const slpAPI = SDK.createSLPAPI(network, provider, apiEndpoint, connectionURL)

const fromAmount = BigInt(100 * 1e6)  // 100 USDC
const fromCoinObjects = ['0x...']     // user's USDC coin IDs

// Optional: set minAmountOut to protect against slippage
// e.g. 1% slippage: minAmountOut = expectedOut * 0.99
const minAmountOut = 0  // or compute from oracle + slippage

const tx = await slpAPI.swap(
  'usdc',
  'sui',
  fromAmount,
  fromCoinObjects,
  minAmountOut
)

// Sign with wallet and execute
// const signed = await signAndExecuteTransaction({ transaction: tx })
```

### Swap and return coin to user (swapV2Ptb)

Use `swapV2Ptb()` when you need the output coin returned as a `TransactionObjectArgument`—for example, to pass into another move call or to transfer it within the same transaction. Unlike `swap()`, which consumes the output internally, `swapV2Ptb()` returns the output coin so you can compose it into larger transactions.

Pass an optional `tx` to compose into an existing transaction; otherwise a new transaction is created (you must sign and execute it via your wallet).

```typescript
const slpAPI = SDK.createSLPAPI(network, provider, apiEndpoint, connectionURL)

// Option 1: Standalone swap (tx created internally)
const tx = new Transaction()
const outputCoin = await slpAPI.swapV2Ptb(
  'usdc',
  'sui',
  BigInt(100 * 1e6),
  fromCoinObjects,
  minAmountOut,
  tx
)
// tx is modified in place; sign and execute tx

// Option 2: Compose with other move calls
const composedTx = new Transaction()
const swapCoin = await slpAPI.swapV2Ptb('usdc', 'sui', BigInt(100 * 1e6), fromCoinObjects, minAmountOut, composedTx)
composedTx.transferObjects([swapCoin], composedTx.pure.address(recipientAddress))
```

### Complete integration example

```typescript
import { SDK, LPToken, Network } from '@zofai/zo-sdk'
import { SuiClient } from '@mysten/sui/client'

async function swapWithFeeEstimate(
  fromToken: string,
  toToken: string,
  fromAmountAtomic: number,
  fromCoinObjects: string[],
  slippageBps: number = 50,  // 0.5%
) {
  const provider = new SuiClient({ url: 'https://fullnode.mainnet.sui.io' })
  const api = SDK.createSLPAPI(
    Network.MAINNET,
    provider,
    'https://api.zofinance.io',
    'https://hermes.zofinance.io'
  )

  // 1. Estimate fees
  const feeBreakdown = await api.dataAPI.calculateSwapFeeBreakdown(
    fromToken,
    toToken,
    fromAmountAtomic
  )

  // 2. Compute minAmountOut from fee breakdown (net value after fees) and slippage
  const toPrice = (await api.getOraclePrice(toToken)).getPriceUnchecked().getPriceAsNumberUnchecked()
  const toDecimals = 9  // use deployment consts or lookup
  const netValueUsd = feeBreakdown.swapValue - feeBreakdown.totalFeeValue
  const expectedOutAtomic = (netValueUsd * (10 ** toDecimals)) / toPrice
  const minAmountOut = Math.floor(expectedOutAtomic * (1 - slippageBps / 10000))

  // 3. Build transaction
  const tx = await api.swap(
    fromToken,
    toToken,
    BigInt(fromAmountAtomic),
    fromCoinObjects,
    minAmountOut
  )

  return {
    transaction: tx,
    feeBreakdown,
  }
}
```

### Fee components

| Component              | Description                                                               |
| ---------------------- | ------------------------------------------------------------------------- |
| **Rebase fee (in)**    | Fee on the source token when swapping in; depends on vault utilization.   |
| **Rebase fee (out)**   | Fee on the destination token when swapping out.                           |
| **Swap impact fee**    | Fee from `SwapImpactConfig`; scales with `swapValue / totalVaultsValue`.  |
| **EMA volatility fee** | Fee from `EmaVolatilityFeeConfig`; scales with price divergence from EMA. |

Use `calculateSwapFeeBreakdown` to get the USD value of each component and the total fee before executing the swap.

### Token identifiers

Tokens are identified by their symbol in the deployment config, e.g. `'sui'`, `'usdc'`, `'usdt'`, `'eth'`, `'btc'`. Ensure the `fromToken` and `toToken` values match those in the LP’s supported tokens.
