Build single-hop calldata

Once you have the quote, build calldata ready for on-chain execution.

Endpoint: POST /public/emigroswap/buildTransaction

Use this when your quote has multihop: null and a 2-token path.

Endpoint POST /public/emigroswap/buildTransaction

Request

  • Required: fromTokenAddress, toTokenAddress, chainId, userWallet, amountOut (from quote), minAmountIn (from quote), routerType (from quote)

  • Optional (router-specific): feeTier for Uniswap V3-style routes.

Sample request (single-hop, Uniswap V3-style)

{
  "fromTokenAddress": "0x833589fCD6EdB6E08F4c7C32D4f71B54bDa02913",
  "toTokenAddress":   "0x0b3e328455c4059EEb9e3f84b5543F74E24e7E1b",
  "chainId": 8453,
  "userWallet": "0x000000000000000000000000000000000000dEaD",
  "amountOut": "100000000",
  "minAmountIn": "64813995948785878300",
  "routerType": "uniswapv3",
  "feeTier": 500
}
import axios from "axios";
import { ethers } from "ethers";

// ---- Config ----
const API_KEY = "esk_live.***";
const BASE_URL = "https://api.emigro.co";
const CHAIN_ID = 8453;
const USER_WALLET = "0x000000000000000000000000000000000000dEaD"; // recipient

type Quote = {
  fromTokenAddress: string;
  toTokenAddress: string;
  chainId: number;
  amountOut: string;   // RAW input (from quote)
  minAmountIn: string; // RAW min out (from quote)
  routerType: string;  // e.g. "uniswapv3" or "aerodrome-slipstream"
  feeTier?: number;    // may be present for v3
  multihop: null;      // single-hop
  path: [string, string];
};

type BuildTx = {
  success: boolean;
  chainId: number;
  routerAddress: string;
  abiFunctionSignature: string;
  abiParameters: any[];
  routerType: string;
  adapterAddress: string;
  adapterData: string;
};

// 1) Get a single-hop quote
async function getSingleHopQuote() {
  const { data } = await axios.post<Quote>(
    `${BASE_URL}/public/emigroswap/quote`,
    {
      fromTokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
      toTokenAddress:   "0xE9185Ee218cae427aF7B9764A011bb89FeA761B4", // BRZ
      amount: "100.00", // HUMAN
      chainId: CHAIN_ID,
      slippage: 0.5,
    },
    { headers: { "x-api-key": API_KEY, "Content-Type": "application/json" } }
  );
  if (Array.isArray((data as any).multihop)) {
    throw new Error("Expected single-hop; quote returned multihop.");
  }
  return data;
}

// 2) Build calldata (single-hop)
async function buildSingleHopCalldata(q: Quote) {
  const body: any = {
    fromTokenAddress: q.fromTokenAddress,
    toTokenAddress: q.toTokenAddress,
    chainId: q.chainId,
    userWallet: USER_WALLET,
    amountOut: q.amountOut,
    minAmountIn: q.minAmountIn,
    routerType: q.routerType,
  };
  if (q.routerType.toLowerCase().includes("uniswapv3") && typeof q.feeTier === "number") {
    body.feeTier = q.feeTier;
  }

  const { data } = await axios.post<BuildTx>(
    `${BASE_URL}/public/emigroswap/buildTransaction`,
    body,
    { headers: { "x-api-key": API_KEY, "Content-Type": "application/json" } }
  );
  return data;
}

// 3) (Optional) Encode & send using ethers v6
async function encodeCall(build: BuildTx) {
  const iface = new ethers.Interface([`function ${build.abiFunctionSignature}`]);
  const data = iface.encodeFunctionData(
    build.abiFunctionSignature.split("(")[0],
    build.abiParameters
  );
  return { to: build.routerAddress, data };
  // To broadcast on your infra:
  // const provider = new ethers.JsonRpcProvider(process.env.BASE_RPC_URL);
  // const signer = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
  // const tx = await signer.sendTransaction({ to: build.routerAddress, data });
  // await tx.wait();
}

(async () => {
  const quote = await getSingleHopQuote();
  const build = await buildSingleHopCalldata(quote);
  console.log("build:", build);
  const tx = await encodeCall(build);
  console.log("tx payload:", tx);
})();

Response (shape)

Send the transaction exactly with the returned routerAddress, abiFunctionSignature, and abiParameters.

Last updated