Skip to main content
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

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) => allowanceMap[t.address]?.approvalNeeded
    );

    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