Skip to content

GuidesQuickstart

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:

FieldMeaning
amountOutWhat you should receive, after the router fee and measured token taxes
minOutThe least you'll accept. Below it, the transaction reverts
approvalnull, or an approve transaction to send first (ERC20 input only)
txThe swap transaction to sign and send
simulation.oktrue = 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.ok and warnings (impersonator tokens, taxes). See Token safety.
  • Handle 404 no route, 422 honeypot and 503 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

lane.markets · Make the most of every move.