> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dzap.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Batch Swap (Multi-Token)

> Swap multiple token pairs in one trade request

You can request quotes for multiple pairs and execute them in a single `trade()` call by building a `data` array from the quote response.

## Flow

1. Call `getTradeQuotes` with multiple entries in `data`.
2. For each pair key in the response, get `recommendedSource ?? bestReturnSource` and the corresponding quote from `quoteRates[source]`.
3. Build `TradeBuildTxnRequestData[]` with `amount`, `srcToken`, `destToken`, `toChain`, `protocol`, `recipient`, `slippage` (and optionally `srcDecimals`, `destDecimals`) from each quote.
4. Check allowances and approve only non-native tokens (skip `0x0000000000000000000000000000000000000000`).
5. Call `trade({ request: { sender, refundee, fromChain, gasless: false, data: buildData }, signer })`.
6. On failure with `action === "TRY_ANOTHER_ROUTE"`, rebuild `data` using `bestReturnSource` and retry.

## Example

```typescript theme={null}
import { DZapClient, Services, TxnStatus, ApprovalModes } from "@dzapio/sdk";
import type { TradeQuotesRequestData, TradeBuildTxnRequest, TradeBuildTxnRequestData } from "@dzapio/sdk";

const NATIVE = "0x0000000000000000000000000000000000000000";

async function batchSwap(
  signer: any,
  userAddress: `0x${string}`,
  chainId: number,
  swaps: Array<{
    srcToken: string;
    srcDecimals: number;
    destToken: string;
    destDecimals: number;
    amount: string;
  }>
) {
  const dZap = DZapClient.getInstance();

  const quoteReq: TradeQuotesRequestData[] = swaps.map((s) => ({
    amount: s.amount,
    srcToken: s.srcToken,
    srcDecimals: s.srcDecimals,
    destToken: s.destToken,
    destDecimals: s.destDecimals,
    toChain: chainId,
    slippage: 0.5,
  }));

  const quotes = await dZap.getTradeQuotes({
    fromChain: chainId,
    data: quoteReq,
    account: userAddress,
  });

  const buildData: TradeBuildTxnRequestData[] = [];
  for (const [pairKey, pairQuotes] of Object.entries(quotes)) {
    const source = pairQuotes.recommendedSource ?? pairQuotes.bestReturnSource;
    if (!source || !pairQuotes.quoteRates?.[source]) continue;
    const q = pairQuotes.quoteRates[source];
    buildData.push({
      amount: q.srcAmount,
      srcToken: q.srcToken.address,
      srcDecimals: q.srcToken.decimals,
      destToken: q.destToken.address,
      destDecimals: q.destToken.decimals,
      toChain: chainId,
      protocol: source,
      recipient: userAddress,
      slippage: 0.5,
    });
  }

  const tokensForApproval = buildData
    .filter((d) => d.srcToken.toLowerCase() !== NATIVE.toLowerCase())
    .map((d) => ({ address: d.srcToken as `0x${string}`, amount: d.amount }));

  if (tokensForApproval.length > 0) {
    const allowanceRes = await dZap.getAllowance({
      chainId,
      sender: userAddress,
      tokens: tokensForApproval,
      service: Services.trade,
      mode: ApprovalModes.Default,
    });

    const allowanceMap = allowanceRes.data ?? {};
    const needsApproval = tokensForApproval.filter((t) => {
      const entry = allowanceMap[t.address];
      return entry && entry.type !== "eip2612" && entry.allowance < BigInt(t.amount);
    });

    if (needsApproval.length > 0) {
      const approveRes = await dZap.approve({
        chainId,
        signer,
        sender: userAddress,
        tokens: needsApproval,
        service: Services.trade,
        mode: ApprovalModes.Default,
      });
      if (approveRes.status !== TxnStatus.success) throw new Error("Approval failed");
    }
  }

  const tradeReq: TradeBuildTxnRequest = {
    sender: userAddress,
    refundee: userAddress,
    fromChain: chainId,
    gasless: false,
    data: buildData,
  };

  let tradeRes = await dZap.trade({ request: tradeReq, signer });

  if (tradeRes.status !== TxnStatus.success && tradeRes.action === "TRY_ANOTHER_ROUTE") {
    const pairKeys = Object.keys(quotes);
    const fallbackData = buildData.map((d, i) => {
      const fallbackSource = quotes[pairKeys[i]]?.bestReturnSource;
      return fallbackSource ? { ...d, protocol: fallbackSource } : d;
    });
    tradeRes = await dZap.trade({
      request: { ...tradeReq, data: fallbackData },
      signer,
    });
  }

  if (tradeRes.status !== TxnStatus.success) {
    throw new Error(tradeRes.errorMsg ?? "Trade failed");
  }
  return tradeRes.txnHash ?? null;
}
```

## Next steps

* [Execute trade](/sdk/trade/execute-trade) - Single-pair flow and TRY\_ANOTHER\_ROUTE
* [Request quotes](/sdk/trade/request-quotes) - Quote request and response shape
* [Approval mechanisms](/sdk/approval-mechanisms) - Native token and approval modes
