Smart Contracts
This page lists the official LiquidMesh Router contracts and explains how to interact with them on each chain.
LiquidMesh keeps one router per chain. For EVM chains, the router address is the same across networks.
Router Addresses
EVM chains share the same router address:
0x3d90f66B534Dd8482b181e24655A9e8265316BE9
Always verify the address from this page before integrating in production.
Integration Overview
There are two ways to obtain the transaction data for interacting with the router:
-
Quote API (two-step):
- Get quote and route with
GET /v1/{networkId}/quote - Build executable
callMsgwithPOST /v1/{networkId}/swap
- Get quote and route with
-
Flash API (one-step):
- Get an executable order (with call data) in one request via
POST /v1/{networkId}/order
- Get an executable order (with call data) in one request via
The
callMsgincludes standard EVM fields such asto,data,value, andfrom(where applicable). On Solana, the API returns a serialized transaction you can sign and send.
EVM — Executing the Swap
Prerequisites
- Ensure the user has approved the router to spend the ERC‑20 input token (unless the swap is native token in / out).
- Respect
slippageBpswhen constructing the swap (already encoded incallMsgby our API). - Use the router address for the target chain (same EVM address across chains).
ethers.js (v6) example
import { ethers } from "ethers";
// 1) Obtain callMsg from LiquidMesh API (Quote API or Flash API)
const callMsg = {
from: "0x...user",
to: "0x3d90f66B534Dd8482b181e24655A9e8265316BE9",
data: "0x...",
value: "0x0"
};
// 2) Send the transaction
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
const tx = await wallet.sendTransaction({
to: callMsg.to,
data: callMsg.data,
value: callMsg.value,
});
const receipt = await tx.wait();
console.log("Swap tx hash:", receipt?.hash);web3.py example
from web3 import Web3
w3 = Web3(Web3.HTTPProvider(os.environ["RPC_URL"]))
acct = w3.eth.account.from_key(os.environ["PRIVATE_KEY"])
# callMsg from LiquidMesh API
callMsg = {
"to": "0x3d90f66B534Dd8482b181e24655A9e8265316BE9",
"data": "0x...",
"value": 0
}
tx = {
"to": callMsg["to"],
"data": callMsg["data"],
"value": callMsg["value"],
"nonce": w3.eth.get_transaction_count(acct.address),
"gasPrice": w3.eth.gas_price,
"chainId": w3.eth.chain_id,
}
# optionally set tx["gas"] using API's estimatedGas or w3.eth.estimate_gas
signed = acct.sign_transaction(tx)
tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction)
print("Swap tx hash:", tx_hash.hex())Solana — Executing the Swap
Prerequisites
swapTransactionreturned by LiquidMesh API is a serialized transaction (base64).- You need to deserialize, sign, and send using the user’s wallet.
@solana/web3.js example
import { Connection, VersionedTransaction, sendAndConfirmTransaction } from "@solana/web3.js";
// 1) Parse API response
const swapTxBase64 = "<swapTransaction-from-API>"; // base64-encoded
const raw = Buffer.from(swapTxBase64, "base64");
const tx = VersionedTransaction.deserialize(raw);
// 2) Sign with the user's wallet (pseudocode)
await wallet.signTransaction(tx);
// 3) Send
const conn = new Connection(process.env.SOLANA_RPC!, "confirmed");
const sig = await conn.sendRawTransaction(tx.serialize());
console.log("Swap signature:", sig);On Solana, ensure the user has sufficient SOL to cover fees and account creation (if any).
Best Practices
- Always trust but verify: keep the router address in a constant and verify here when deploying.
- Token approvals: for ERC‑20, prompt the user to approve the exact router address.
- Native tokens: when swapping native assets (e.g., ETH/BNB),
valuemust be set accordingly in the transaction. - Slippage & deadlines: respect slippage and timeouts embedded in the
callMsg. - Gas & simulation: use
estimatedGasas a reference; you may simulate again on your infra. - Security: never expose private keys; use secure key management (HSM, Vault, KMS).
- Monitoring: track confirmations and handle re-orgs where applicable.
Updated 3 months ago