Getting started
Quickstart
Swap 1 HYPE for USDC on Elysium testnet in three steps. The same flow works for any pair.
1. Get a quote and a transaction
API=https://api.lane.markets/v1
USDC=0x7D29d8047B905000459c0E80c34a26CeedcB47b2
ME=0xYourAddress
curl "$API/quote?in=HYPE&out=$USDC&amount=1000000000000000000&recipient=$ME&slippageBps=50"Response (trimmed):
{
"amountIn": "1000000000000000000",
"amountOut": "24784177",
"minOut": "24660256",
"feeBps": 5,
"priceImpactBps": 3,
"splits": [
{ "amountIn": "700000000000000000", "route": [{ "protocol": "v3", "pool": "0xD6c7…", "tokenIn": "0xCD57…", "tokenOut": "0x7D29…", "fee": 3000 }] },
{ "amountIn": "300000000000000000", "route": [{ "protocol": "v2", "pool": "0x51A2…", "tokenIn": "0xCD57…", "tokenOut": "0x7D29…", "fee": 3000 }] }
],
"tx": { "from": "0xYou…", "to": "0xExecutor…", "data": "0x…", "value": "1000000000000000000", "chainId": 99801 },
"approval": null,
"simulation": { "ok": true, "gas": "203535" }
}The fields you need:
| Field | Meaning |
|---|---|
amountOut | What you should receive, after the router fee and measured token taxes |
minOut | The least you'll accept. Below it, the transaction reverts |
approval | null, or an approve transaction to send first (ERC20 input only) |
tx | The swap transaction to sign and send |
simulation.ok | true = the exact tx succeeded in simulation from your address. If false, don't send: read simulation.error |
2. Approve (ERC20 inputs only)
If approval is not null, send it ({ to, data }, value 0), wait for it to be mined, then ask for a new quote. The first quote's simulation could not pass without the allowance.
To skip a separate approve per token, use Permit2: a one-time approval, then a signature per swap.
3. Sign and send
Send tx as-is (to, data, value). Don't change data: it contains minOut and a 5-minute deadline. If the quote is older than a few blocks, quote again.
Full TypeScript example (viem)
import { createPublicClient, createWalletClient, http, defineChain, type Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const API = "https://api.lane.markets/v1";
const elysiumTestnet = defineChain({
id: 99801,
name: "Elysium Testnet",
nativeCurrency: { name: "HYPE", symbol: "HYPE", decimals: 18 },
rpcUrls: { default: { http: ["https://testnet-rpc.elysium.kinetiq.xyz"] } },
});
const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex); // never hard-code a key
const wallet = createWalletClient({ account, chain: elysiumTestnet, transport: http() });
const pub = createPublicClient({ chain: elysiumTestnet, transport: http() });
async function quote(params: Record<string, string>) {
const res = await fetch(`${API}/quote?${new URLSearchParams(params)}`);
const body = await res.json();
if (!res.ok) throw new Error(`${res.status} ${body.error} (request ${body.requestId})`);
return body;
}
export async function swap(tokenIn: string, tokenOut: string, amount: bigint, slippageBps = 50) {
const params = { in: tokenIn, out: tokenOut, amount: String(amount), recipient: account.address, slippageBps: String(slippageBps) };
let q = await quote(params);
if (q.approval) {
const hash = await wallet.sendTransaction({ to: q.approval.to, data: q.approval.data });
await pub.waitForTransactionReceipt({ hash });
q = await quote(params); // re-quote: the first simulation could not pass without the allowance
}
if (!q.simulation.ok) throw new Error(`not sending: ${q.simulation.error}`);
const hash = await wallet.sendTransaction({ to: q.tx.to, data: q.tx.data, value: BigInt(q.tx.value) });
const receipt = await pub.waitForTransactionReceipt({ hash });
if (receipt.status !== "success") throw new Error(`reverted: ${hash}`);
return { hash, expected: q.amountOut, min: q.minOut };
}
// 1 HYPE -> USDC
await swap("HYPE", "0x7D29d8047B905000459c0E80c34a26CeedcB47b2", 10n ** 18n);With the SDK
sdk/ wraps all of the above: executeSwap(router, walletClient, publicClient, { in, out, amount }) quotes, approves if needed, re-quotes, checks the simulation and sends.
In a browser wallet
A front does exactly this with window.ethereum: read GET /v1/config to add or switch the chain, call /quote every 15 s, send approval (or sign the Permit2 message) and then tx.
Before production
- Always check
simulation.okandwarnings(impersonator tokens, taxes). See Token safety. - Handle
404 no route,422 honeypotand503 indexer still backfilling. See Errors and limits. - Bots: get a partner key (Access) and use live prices instead of polling
/price.
Next: Build and execute