KyberSwap Plugin
[!IMPORTANT]
Complete the short Base MCP onboarding flow defined in SKILL.md before calling any KyberSwap endpoint. The user’s wallet address is fetched lazily when needed.
Overview
KyberSwap is a DEX aggregator that routes trades across 50+ liquidity sources (Uniswap V2/V3/V4, Curve, Balancer, and others) to find the best execution price across 7 chains. The plugin calls the KyberSwap Aggregator HTTP API to fetch a route quote and build unsigned calldata, then submits the result to Base MCP’ssend_calls. Use KyberSwap when the user wants the best rate across all available liquidity — not just a single protocol’s pools.
Surface Routing
On chat-only surfaces where the allowlist is not configured: inform the user that the swap cannot proceed and direct them to the KyberSwap web UI at
kyberswap.com. Do not improvise a workaround. For the full decision tree, see ../references/custom-plugins.md.
Endpoints
Base URL:https://aggregator-api.kyberswap.com/{chain}
Chain slugs: base · ethereum · arbitrum · optimism · polygon · bsc · avalanche
GET /api/v1/routes
Fetches the best route and returns arouteSummary required verbatim in the build step.
Response shape:
routeSummary object exactly as returned — it is required verbatim in the build step.
POST /api/v1/route/build
Builds encoded swap calldata from a previously fetched route.routeSummary. Routes expire in ~30 seconds — if this step fails with “return amount is not enough”, re-fetch the route and retry.
Response shape:
transactionValue is a decimal wei string (e.g. "0" for ERC-20 input, "10000000000000000" for 0.01 ETH). Hex-encode it before passing as value in send_calls: "0x" + BigInt(transactionValue).toString(16). Non-zero only for native token input.
GET /api/v1/public/tokens (token resolution)
Resolve a token symbol to its contract address when not in the known-addresses table in## Notes.
symbol match and highest marketCap. If no whitelisted match, retry without isWhitelisted.
Chain IDs: base=8453, ethereum=1, arbitrum=42161, optimism=10, polygon=137, bsc=56, avalanche=43114
Orchestration
Swap
get_wallets→walletAddress.- Resolve token symbols to addresses — use the
## Notestable first, then the token-api endpoint. - Compute
amountInin base units: multiply human amount by10^decimals(ETH=18, USDC=6, WBTC=8). - Determine slippage: default
50bps for common pairs,100bps for long-tail tokens. Apply thresholds in## Risks & Warningsbefore proceeding. GET /api/v1/routes→routeSummary,amountOut,amountOutUsd,gasUsd. Show the quoted output and gas cost to the user; confirm before proceeding.POST /api/v1/route/build→data(swap calldata),transactionValue,routerAddress. VerifyrouterAddressequals0x6131B5fae19EA4f9D964eAc0408E4408b66337b5— abort and warn the user if it differs.- Build calls array:
- Native tokenIn →
[swap_call] - ERC-20 tokenIn →
[approval_call, swap_call]— always include approval, no allowance check needed. - USDT on Ethereum — if existing allowance is non-zero, prepend a zero-approval call before the real approval.
- Native tokenIn →
send_calls(chain, calls)→approvalUrl,requestId.- Present
approvalUrlto the user. Do not auto-approve. Callget_request_status(requestId)only after the user acts.
Submission
Target tool:send_calls
Map POST /route/build output into send_calls as follows:
ERC-20 tokenIn — approval + swap batch:
hex(transactionValue): "0x" + BigInt(transactionValue).toString(16) — transactionValue is a decimal wei string from the API.
ERC-20 approval calldata encoding:
base, ethereum, arbitrum, optimism, polygon, bsc, avalanche) — not numeric chain IDs. After send_calls returns an approval URL, follow the flow in ../references/approval-mode.md.
Example Prompts
“Swap 100 USDC to ETH on Base”get_wallets→ address.GET /api/v1/routesonbase— tokenIn=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913(USDC, 6 dec), tokenOut=0xEeee...eEEE, amountIn=100000000.- Show quoted output and gas to user; confirm.
POST /api/v1/route/build→data(swap calldata),transactionValue="0"→ hex-encode to"0x0".- Encode approve calldata: router spends
100000000USDC. send_calls("base", [approval_call, swap_call]).
get_wallets→ address.GET /api/v1/routesonarbitrum— tokenIn=0xEeee...eEEE, tokenOut=0xaf88d065e77c8cC2239327C5EDb3A432268e5831(USDC), amountIn=100000000000000000.- Show quoted output and gas to user; confirm.
POST /api/v1/route/build→data(swap calldata),transactionValue="10000000000000000"→ hex-encode to"0xde0b6b3a7640000"(non-zero, native input).- No approval needed — native ETH.
send_calls("arbitrum", [swap_call])with value=transactionValue.
get_wallets→ address.GET /api/v1/routesonpolygon— tokenIn=0xEeee...eEEE, tokenOut=0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359(USDC), amountIn=500000000000000000000.- Return
amountOutUsdandgasUsdto the user — no transaction submitted.
Risks & Warnings
-
Slippage — Swaps can fill materially worse than the quoted price if market conditions shift between quote and execution. Apply the following thresholds:
If the user does not specify slippage, default to
50bps for common pairs (ETH/USDC, WBTC/ETH) and100bps for long-tail or volatile tokens. Always pass an explicit value — the API defaults to 0 bps ifslippageToleranceis omitted, causing most trades to fail.
Notes
Router address (same on all supported chains):0x6131B5fae19EA4f9D964eAc0408E4408b66337b5
Native token sentinel (ETH/BNB/MATIC/AVAX/etc.): 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Common token addresses:
KyberSwap splits trades across multiple pools when beneficial —
routeSummary may describe a multi-hop or split route. Pass it as-is; do not modify it.
USDT on Ethereum: if existing allowance is non-zero, the approve call will revert — send a zero-approval first (amount = 0x0...0), then the real approval.