Posted By : Krishan
In this guide, we will walk through the process of placing a limit order on Kyberswap using their API. Kyberswap is a decentralized exchange (DEX) aggregator that provides the best token prices by aggregating liquidity from various DEXs. By leveraging Kyberswap's API, we can automate the process of placing limit orders for token trades, giving you full control over your trade price. This tutorial will guide you through setting up the necessary environment, writing the code to interact with the Kyberswap API, and successfully placing a limit order using Node.js and the appropriate dependencies. For more about DEX, visit crypto exchange development services.
A limit order is an instruction to buy or sell your token at a specific price or better. It gives control over the trade price to be executed.
For example:
A buy limit order will only execute at the limit price. And a sell limit order will only execute at the limit price or higher.
A dex aggregator & liquidity protocol that provides the best token price by aggregating liquidity from various DEXs. It also provides liquidity providers with opportunities to earn rewards by depositing their tokens.
Before everything, you must have Node.js and VS Code installed.
Let's set up this:
Open your terminal and type this command:
1. mkdir KyberswapApi
2. cd KyberswapApi
3. code .
It will open your project KyberswapApi in VS Code, then open the terminal in VS Code and type this command: npm init
It will initialize a project and create the package.json file. npm install viem ethers axios
It will install all dependencies in your package.json file.
Create a file index.js and paste this Program
Run this command in your terminal : node index.js (this will create the limit order successfully).
Also, Read | A Dev Guide to Placing Orders using Hyperliquid API
To create a new order, we need to make a post request on this URL: https://limit-order.kyberswap.com/write/api/v1/orders
For this, we need params which include the signed EIP712 message and returned data from this post request(https://limit-order.kyberswap.com/write/api/v1/orders/sign-message).
Program :
import {
createWalletClient,
erc20Abi,
parseEther,
getContract,
createPublicClient,
http,
encodeFunctionData
} from 'viem';
import { ethers } from 'ethers';
import axios from 'axios';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
const kyberApiUrl = 'https://limit-order.kyberswap.com';
const privateKey =
'000000X4PRivateKey';
const rpcUrl = 'https://mainnet.base.org';
async function mainApprove(makerAsset, limitOrderContract, maker, makingAmount) {
const client = createPublicClient({
chain: {
id: 8453, // Base chain ID
name: 'Base',
rpcUrls: {
default: { http: ['https://mainnet.base.org'] },
},
},
transport: http('https://mainnet.base.org')
});
console.log('Client created for Base chain:', client);
const tokenContract = getContract({
abi: erc20Abi,
address: makerAsset,
client: client,
});
console.log('here is the tokenContract',tokenContract.address);
const currentAllowance = await tokenContract.read.allowance([
maker,
limitOrderContract,
]);
console.log('Current Allowance:', currentAllowance.toString());
const encodedCalls = [];
if (BigInt(currentAllowance) < BigInt('100000000')) {
console.log('here it comes ');
const approvalData =await getTokenApprovalCalldata(
makerAsset,
limitOrderContract,
makingAmount,
);
console.log(' Approval Data:', approvalData);
encodedCalls.push({
to: makerAsset ,
data: approvalData,
// gas: '0.007547422'
//approvalGas.toString(),
});
console.log('Encoded Calls:', encodedCalls);
const swaptx = encodedCalls;
const str = '000000X4PRivateKey';
const account = privateKeyToAccount(`0x${str}`);
const walletClient = createWalletClient({
account,
chain: base,
transport: http('https://mainnet.base.org'),
});
console.log('Wallet Client created:');
const tx1=[];
for (const call of swaptx) {
const tx = {
to: call.to,
data: call.data,
value: call.value ? BigInt(call.value) : 0n,
};
const hash = await walletClient.sendTransaction(tx);
tx1.push(hash);
console.log(' Transaction sent, hash:', hash);
}
return tx1;
}
return '';
}
async function postCreateOrderUnsigned(
chainId,
makerAsset,
takerAsset,
maker, //Maker address
makingAmount, // '10000'
takingAmount // '20000000000000000'
) {
let targetPath = `/write/api/v1/orders/sign-message`;
// Structure the request to be sent in POST body
const requestBody = {
chainId: chainId.toString(),
makerAsset: makerAsset, // USDC
takerAsset: takerAsset, // KNC
maker: maker,
allowedSenders: [maker], // Included so that only our account can fill this order
makingAmount: makingAmount,
takingAmount: takingAmount,
expiredAt: Math.floor(Date.now() / 1000) + 60 * 60, // 60mins
};
console.debug(requestBody);
try {
const { data } = await axios.post(kyberApiUrl + targetPath, requestBody);
// Return the request used and the EIP712 unsigned data
console.log('the data we have',data);
return {
routerContract: data.data.domain.verifyingContract,
requestBody: requestBody,
returnedData: data.data,
};
} catch (error) {
throw error;
}
}
//Get Maker Active Making Amount
async function getMakerActiveAmount(chainId, makerAsset, makerAddress) {
const targetPath = `/read-ks/api/v1/orders/active-making-amount`;
const targetPathConfig = {
params: {
chainId: chainId,
makerAsset: makerAsset,
maker: makerAddress,
},
};
try {
const { data } = await axios.get(
kyberApiUrl + targetPath,
targetPathConfig
);
return data.data.activeMakingAmount;
} catch (error) {
throw error;
}
}
async function getContracts(chainId) {
const targetPath = `/read-ks/api/v1/configs/contract-address`;
// Specify the chainId to query
const targetPathConfig = {
params: {
chainId: chainId.toString(),
},
};
try {
console.log(`\nGetting the LO contracts...`);
const { data } = await axios.get(
kyberApiUrl + targetPath,
targetPathConfig
);
return data.data;
} catch (error) {
throw error;
}
}
// Request approval with calldata sending to the user server (client-side)
async function getTokenApprovalCalldata(
tokenContractAddress,
spenderAddress,
amount
) {
const data = encodeFunctionData({
abi: erc20Abi,
functionName: 'approve',
args: [spenderAddress, parseEther(amount.toString())],
});
//TODO: Send the calldata to the user server here
return data;
}
async function signOrderData(domain, types, message) {
const provider = new ethers.JsonRpcProvider(rpcUrl);
const signer = new ethers.Wallet(privateKey, provider);
return await signer.signTypedData(domain, types, message);
}
// Create New Order on Kyberswap
async function postCreateOrder(
chainId,
makerAsset,
takerAsset,
maker,
makingAmount,
takingAmount
) {
const targetPath = `/write/api/v1/orders`;
const unsignedOrder = await postCreateOrderUnsigned(
chainId,
makerAsset,
takerAsset,
maker,
makingAmount,
takingAmount
);
// Get the request body and the EIP712 order creation data
const unsignedOrderReqBody = unsignedOrder.requestBody;
const unsignedOrderReturnData = unsignedOrder.returnedData;
const routerContract = unsignedOrder.routerContract;
// Get the Maker current making amount to ensure contract has sufficient allowance across all orders
const currentMakingAmount = await getMakerActiveAmount(
chainId,
makerAsset,
maker
);
const newMakingAmount =
Number(currentMakingAmount) + Number(unsignedOrderReqBody.makingAmount);
// Get the LO contract address to interact with on-chain
const limitOrderContract = (await getContracts(chainId)).latest;
// Check if LO contract has sufficient allowance to spend makerAsset
await getTokenApprovalCalldata(
makerAsset,
limitOrderContract,
newMakingAmount
);
const swaptx= await mainApprove(
makerAsset,
limitOrderContract,
maker,
newMakingAmount
)
console.log('the swaptx is: ',swaptx);
// Sign the EIP712 order creation with the user server (client-side)
const signature = await signOrderData(
unsignedOrderReturnData.domain,
{ Order: unsignedOrderReturnData.types.Order },
unsignedOrderReturnData.message
);
// Structure the request to be sent in POST body
const requestBody = {
...unsignedOrderReqBody,
salt: unsignedOrderReturnData.message.salt,
signature: signature,
};
console.log('the request body is: ', requestBody);
try {
console.log(`\nPosting the create order...`);
const { data } = await axios.post(kyberApiUrl + targetPath, requestBody);
console.log(`KyberSwap server response:`);
console.log(data);
} catch (error) {
throw error;
}
}
Call the post createOrder function with its parameters, and your order will be created.
For example :
postCreateOrder(
'8453', // chainId
'0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', // maker asset
'0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', // taker asset
'0x1AC9b76006BaF4f06563E491d4182C82792D2A2C', // maker address
'5000000', // making amount
'5000000' // taking amount
);
You may also like | Building a Portfolio Tracker Dashboard Using Hyperliquid API
In conclusion, this guide demonstrates how to place a limit order on Kyberswap using the API, allowing you to efficiently manage trades with full control over your order price. By following the steps to set up your environment, configure your wallet, and interact with the Kyberswap API, you can easily integrate limit orders into your trading strategies. With the right parameters and authentication, you can securely create orders on Kyberswap and take advantage of the liquidity available. This process enables developers to enhance their algorithmic trading systems and automate transactions effectively on the platform. For more information, refer to the Kyberswap API documentation.
In case you are planning to build a DEX aggregator like Kyberswap, connect with our skilled blockchain developers to get started.
July 9, 2025 at 12:17 pm
Your comment is awaiting moderation.