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";
type Hop = { fromTokenAddress: string; toTokenAddress: string; feeTier?: number };
type Quote = {
fromTokenAddress: string;
toTokenAddress: string;
chainId: number;
amountOut: string; // RAW input
minAmountIn: string; // RAW min out
routerType: string; // e.g. "aerodrome-slipstream"
multihop: Hop[]; // non-empty for multi-hop
path: string[]; // 3+ tokens
};
type BuildTx = {
success: boolean;
chainId: number;
routerAddress: string;
abiFunctionSignature: string; // swapExactInputPathVia(...)
abiParameters: any[];
routerType: string;
adapterAddress: string;
adapterData: string;
};
// 1) Get a multi-hop quote (EURC -> USDC -> BRZ)
async function getMultiHopQuote() {
const { data } = await axios.post<Quote>(
`${BASE_URL}/public/emigroswap/quote`,
{
fromTokenAddress: "0x60a3e35cc302bfa44cb288bc5a4f316fdb1adb42", // EURC
toTokenAddress: "0xE9185Ee218cae427aF7B9764A011bb89FeA761B4", // BRZ
amount: "100.00",
chainId: CHAIN_ID,
slippage: 0.5,
},
{ headers: { "x-api-key": API_KEY, "Content-Type": "application/json" } }
);
if (!Array.isArray(data.multihop) || data.path.length < 3) {
throw new Error("Expected multi-hop; quote returned single-hop.");
}
return data;
}
// 2) Build calldata (multi-hop)
async function buildMultiHopCalldata(q: Quote) {
const body = {
fromTokenAddress: q.fromTokenAddress,
toTokenAddress: q.toTokenAddress,
chainId: q.chainId,
userWallet: USER_WALLET,
amountOut: q.amountOut,
minAmountIn: q.minAmountIn,
routerType: q.routerType,
path: q.path, // EXACTLY from quote
multihop: q.multihop, // EXACTLY from quote
};
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 };
}
(async () => {
const quote = await getMultiHopQuote();
const build = await buildMultiHopCalldata(quote);
console.log("build:", build);
const tx = await encodeCall(build);
console.log("tx payload:", tx);
})();