Installation
First, we installkuru-sdk
Copy
Ask AI
npm i @kuru-labs/kuru-sdk
Configure environment
Export yourPRIVATE_KEY to use the examples
Copy
Ask AI
export PRIVATE_KEY=<your_private_key>
Update config.json
config.json
Copy
Ask AI
{
"rpcUrl": "monad_rpc_url",
"marginAccountAddress": "0xdDDaBd30785bA8b45e434a1f134BDf304d6125d9", // testnet
"routerAddress": "0x1f5A250c4A506DA4cE584173c6ed1890B1bf7187", // testnet
}
Deposit into margin account
Copy
Ask AI
// Example: deposit tokens into a margin account via Kuru SDK
// Fill placeholders (rpcUrl, marginAccountAddress, tokenAddress, amount, decimals)
// and export PRIVATE_KEY before running.
import { ethers } from "ethers";
import * as KuruSdk from "@kuru-labs/kuru-sdk";
import * as KuruConfig from "../config.json";
const {rpcUrl, marginAccountAddress} = KuruConfig;
const tokenAddress = ""; // TODO: ERC-20 token to deposit (use 0x000...000 for native if supported)
const amount = ""; // TODO: human amount as string (e.g., "1000")
const decimals = 18; // TODO: token decimals (e.g., 18 for ABC, 6 for USDC)
async function main() {
const provider = new ethers.providers.JsonRpcProvider(rpcUrl);
const privateKey = process.env.PRIVATE_KEY; // must be set in env
if (!privateKey) throw new Error("PRIVATE_KEY environment variable not set");
const signer = new ethers.Wallet(privateKey, provider);
try {
// Deposits on behalf of the signer address. Set a different receiver if desired
const receipt = await KuruSdk.MarginDeposit.deposit(
signer,
marginAccountAddress,
await signer.getAddress(),
tokenAddress,
amount,
decimals,
true // set to true to auto-approve ERC-20 if not already approved
);
console.log("Transaction hash:", receipt.transactionHash);
} catch (error) {
console.error("Error depositing:", error);
}
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Place a limit buy
Placing a limit order. This consumes funds in your margin account.import parseEvents for tracking orders created.
parseEvents
Copy
Ask AI
import { ethers, BigNumber } from 'ethers';
interface TradeInfo {
orderId: BigNumber;
filledSize: BigNumber;
price: BigNumber;
isBuy: boolean;
}
export async function parseEvents(receipt: ethers.ContractReceipt): Promise<{
newOrderIds: BigNumber[];
trades: TradeInfo[];
}> {
const newOrderIds: BigNumber[] = [];
const trades: TradeInfo[] = [];
receipt.logs.forEach((log) => {
if (log.topics[0] === ethers.utils.id("OrderCreated(uint40,address,uint96,uint32,bool)")) {
try {
const decodedLog = ethers.utils.defaultAbiCoder.decode(
['uint40', 'address', 'uint96', 'uint32', 'bool'],
log.data
);
const orderId = BigNumber.from(decodedLog[0]);
newOrderIds.push(orderId);
} catch (error) {
console.error("Error decoding OrderCreated event:", error);
}
} else if (log.topics[0] === ethers.utils.id("Trade(uint40,address,bool,uint256,uint96,address,address,uint96)")) {
try {
const decodedLog = ethers.utils.defaultAbiCoder.decode(
['uint40', 'address', 'bool', 'uint256', 'uint96', 'address', 'address', 'uint96'],
log.data
);
trades.push({
orderId: BigNumber.from(decodedLog[0]),
price: BigNumber.from(decodedLog[3]),
filledSize: BigNumber.from(decodedLog[7]),
isBuy: decodedLog[2]
});
} catch (error) {
console.error("Error decoding trade event:", error);
}
}
});
return { newOrderIds, trades };
}
Copy
Ask AI
// Example: place a limit buy order using the Kuru SDK
// Fill the placeholders (rpcUrl, marketAddress) and export PRIVATE_KEY before running.
import { ethers } from "ethers";
import * as KuruSdk from "@kuru-labs/kuru-sdk";
import { parseEvents } from "./";
import * as KuruConfig from "../config.json";
const {rpcUrl, marginAccountAddress} = KuruConfig;
// Order parameters (strings OK; SDK handles parsing/decimals):
// price → quoted in quote per base (e.g., USDC per ABC); must respect tick size
// size → amount of base to buy; must be ≥ min size
const price = ""; // TODO: e.g., "5" for 5 USDC per ABC
const size = ""; // TODO: e.g., "10" for 10 ABC
async function main() {
const provider = new ethers.providers.JsonRpcProvider(rpcUrl);
// PRIVATE_KEY should be exported in your shell before running
const privateKey = process.env.PRIVATE_KEY; // must be set in env
if (!privateKey) throw new Error("PRIVATE_KEY environment variable not set");
const signer = new ethers.Wallet(privateKey, provider);
// Fetch market parameters (precisions, tick size, fees)
const marketParams = await KuruSdk.ParamFetcher.getMarketParams(
provider,
marketAddress
);
try {
// Place a Good-Till-Cancel limit buy
const receipt = await KuruSdk.GTC.placeLimit(
signer,
marketAddress,
marketParams,
{
price,
size,
isBuy: true,
postOnly: true
}
);
console.log("Transaction hash:", receipt.transactionHash);
// Extract created order ids from events
const { newOrderIds } = await parseEvents(receipt)
console.log("OrderIds:", newOrderIds)
} catch (error) {
console.error("Error placing limit buy order:", error);
}
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});