LayerHopdocs

Guides

Same-chain swaps

Swap tokens on one chain — Jupiter on Solana, 0x/Relay/LI.FI on EVM — and confirm them on chain.

Open in ClaudeOpen in ChatGPT

Same-chain swaps use the same three calls as bridging: quote, build, sign. Only tracking differs.

Solana (Jupiter, LI.FI)#

TypeScript
const { best } = await lh.quote({
  srcChain: "solana", srcToken: "USDC", amount: "25000000",   // 25 USDC
  dstChain: "solana", dstToken: "SOL",
  sender: solanaAddress, recipient: solanaAddress,
});
const tx = await lh.buildTx(best.quoteId); // Jupiter → { vm: "svm", serializedTx, submitViaApi: true }

Jupiter transactions are always submitViaApi: true: sign, then lh.submit(quoteId, signedBase64). See the submitViaApi flow.

Note

Jupiter's referral fee has a 50 bps minimum. With the default api channel fee (20 bps) LayerHop takes no fee on Jupiter routes, and the quote shows ourFeeBps: 0.

EVM (0x, Relay, LI.FI)#

TypeScript
const { best } = await lh.quote({
  srcChain: "arbitrum", srcToken: "ETH", amount: "500000000000000000", // 0.5 ETH
  dstChain: "arbitrum", dstToken: "USDC",
  sender: evmAddress, recipient: evmAddress,
});
const tx = await lh.buildTx(best.quoteId); // { vm: "evm", ..., value: "500000000000000000" }

Selling ETH puts the amount in value and needs no approval. Selling an ERC-20 returns an approval. 0x quotes need the operator's ZEROX_API_KEY.

Confirming#

Same-chain providers settle inside the transaction, so GET /v1/orders/jupiter/{id} and GET /v1/orders/zerox/{id} always return state: "unknown". Confirm on chain instead:

TypeScript
// EVM
const receipt = await pub.waitForTransactionReceipt({ hash });
const ok = receipt.status === "success";

// Solana
const { value } = await connection.confirmTransaction(signature, "confirmed");
const ok = value.err === null;

Relay and LI.FI same-chain swaps can be tracked through the orders endpoint like cross-chain ones.

Same token, same chain#

Quoting the same token in and out on one chain fails with NO_ROUTE: there is nothing to swap.