Python SDK for Kuru's Central Limit Orderbook (CLOB)
This project has been archived.
The maintainers of this project have marked this project as archived. No new releases are expected.
Project description
Kuru Python SDK
A Python SDK for interacting with Kuru's Central Limit Orderbook (CLOB).
Features
- Margin Account Management
- Deposit and withdraw tokens
- Order Management
- Place limit and market orders
- Cancel orders
- Real-time order tracking via WebSocket
- Batch orders
Installation
pip install kuru-sdk
Environment Variables
The SDK uses the following environment variables:
RPC_URL=your_ethereum_rpc_url
PK=your_private_key
Quick Start
Here's an example for depositing to the margin account. User needs margin account balance for limit orders.
Note: The deposit amount is in wei
import asyncio
import sys
from pathlib import Path
# Add project root to Python path
project_root = str(Path(__file__).parent.parent)
sys.path.append(project_root)
from web3 import Web3
from kuru_sdk.margin import MarginAccount
import os
import json
import argparse
from dotenv import load_dotenv
load_dotenv()
from kuru_sdk.client import KuruClient
# Network and contract configuration
NETWORK_RPC = os.getenv("RPC_URL") # Replace with your network RPC
ADDRESSES = {
'mon/usdc': '0x3a4cc34d6cc8b5e8aeb5083575aaa27f2a0a184a',
'margin_account': '0x33fa695D1B81b88638eEB0a1d69547Ca805b8949',
'usdc': '0x9A29e9Bab1f0B599d1c6C39b60a79596b3875f56',
'mon': '0x0000000000000000000000000000000000000000'
}
async def main():
web3 = Web3(Web3.HTTPProvider(NETWORK_RPC))
margin_account = MarginAccount(
web3=web3,
contract_address=ADDRESSES['margin_account'],
private_key=os.getenv('PK')
)
wallet_address = web3.eth.account.from_key(os.getenv('PK')).address
# deposit 10 mon
await margin_account.deposit(
token=ADDRESSES['mon'],
amount=10000000000000000000
)
balance = await margin_account.get_balance(
user_address=wallet_address,
token=ADDRESSES['mon']
)
print(f"Balance: {balance}")
if __name__ == "__main__":
asyncio.run(main())
Here's a complete example showing how to place orders with different transaction options:
Placing single order
async def main():
client = ClientOrderExecutor(
web3=Web3(Web3.HTTPProvider(NETWORK_RPC)),
contract_address=ADDRESSES['orderbook'],
private_key=os.getenv("PK"),
websocket_url="wss://ws.testnet.kuru.io"
)
# Limit buy
order = OrderRequest(
cloid = "mm_1"
market_address=ADDRESSES['mon/usdc'],
order_type='limit',
side='buy',
price=price,
size=size,
post_only=post_only
)
# Limit sell
order = OrderRequest(
cloid = "mm_2"
market_address=ADDRESSES['mon/usdc'],
order_type='limit',
side='sell',
price=price,
size=size,
post_only=post_only
)
# Market buy
order = OrderRequest(
cloid = "mm_3"
market_address=ADDRESSES['mon/usdc'],
order_type='market',
side='buy',
size=size,
min_amount_out=min_amount,
fill_or_kill=False
)
# Market sell
order = OrderRequest(
cloid = "mm_4"
market_address=ADDRESSES['mon/usdc'],
order_type='market',
side='sell',
size=size,
min_amount_out=min_amount,
fill_or_kill=False
)
try:
tx_hash = await client.place_order(order)
print(f"Transaction hash: {tx_hash}")
return tx_hash
except Exception as e:
print(f"Error placing order: {str(e)}")
return None
if __name__ == "__main__":
asyncio.run(main())
Placing batch orders
async def main():
# Limit buy
order1 = OrderRequest(
cloid = "mm_5"
market_address=ADDRESSES['mon/usdc'],
order_type='limit',
side='buy',
price=price,
size=size,
post_only=post_only
)
# Limit sell
order2 = OrderRequest(
cloid = "mm_6"
market_address=ADDRESSES['mon/usdc'],
order_type='limit',
side='sell',
price=price,
size=size,
post_only=post_only
)
# Cancel order
order3 = OrderRequest(
market_address=ADDRESSES['mon/usdc'],
order_type='cancel',
cancel_cloids=["mm_1", "mm_2"]
)
orders = [order1, order2, order3]
try:
tx_hash = await client.batch_orders(order)
print(f"Transaction hash: {tx_hash}")
return tx_hash
except Exception as e:
print(f"Error placing batch order: {str(e)}")
return None
if __name__ == "__main__":
asyncio.run(main())
Cancelling order
async def main():
try:
tx_hash = await client.cancel_order("mm_1")
print(f"Transaction hash: {tx_hash}")
return tx_hash
except Exception as e:
print(f"Error cancelling order: {str(e)}")
return None
if __name__ == "__main__":
asyncio.run(main())
Components
Transaction Options
You can customize transaction parameters using TxOptions:
# Basic gas settings
tx_options = TxOptions(
gas_limit=140000,
gas_price=1000000000, # 1 gwei
max_priority_fee_per_gas=0
)
# With custom nonce
tx_options = TxOptions(
gas_limit=140000,
gas_price=1000000000,
max_priority_fee_per_gas=0,
nonce=web3.eth.get_transaction_count(address)
)
By using TxOptions tou can save 1-2 seconds in runtime.
WebSocket Connection Management
The SDK handles WebSocket connections automatically, but you need to properly connect and disconnect: The client automatically connects to ws. But it has to be manually disabled once done.
Event Handling
The SDK provides real-time order updates through WebSocket events:
async def on_order_created(event):
print(f"Order created - ID: {event.orderId}")
print(f"Size: {event.size}, Price: {event.price}")
print(f"Transaction: {event.transactionHash}")
async def on_trade(event):
print(f"Trade executed for order {event.orderId}")
print(f"Filled size: {event.filledSize} @ {event.price}")
print(f"Maker: {event.makerAddress}")
print(f"Taker: {event.takerAddress}")
async def on_order_cancelled(event):
print(f"Order {event.orderId} cancelled")
Orderbook Reconciliation
The SDK provides a method to reconcile the local orderbook with the on-chain orderbook using events from the websocket. This requires you to write custom callback functions and pass it to the KuruClient.
class OrderbookState:
def __init__(self):
self.l2_book = None
async def main():
web3 = Web3(Web3.HTTPProvider(os.getenv("RPC_URL")))
market_address = ADDRESSES['mon/usdc']
orderbook = Orderbook(
web3=web3,
contract_address=market_address,
private_key=os.getenv("PK")
)
client = ClientOrderExecutor(
web3=web3,
contract_address=market_address,
private_key=os.getenv("PK"),
websocket_url="wss://ws.testnet.kuru.io"
)
# Create a container class to hold the l2_book state
state = OrderbookState()
state.l2_book = await orderbook.fetch_orderbook()
print(state.l2_book)
# on order created callback that reconciles the orderbook and updates l2_book
def on_order_created(payload):
try:
print(f"Received order created event: {payload}")
state.l2_book = orderbook.reconcile_orderbook(state.l2_book, "OrderCreated", payload)
print("Updated L2Book:", state.l2_book)
except Exception as e:
print(f"Error reconciling order created: {e}")
print(f"Payload: {payload}")
# print(f"Current L2Book: {state.l2_book}")
# on order cancelled callback that reconciles the orderbook and updates l2_book
def on_order_cancelled(payload):
print(f"Received order cancelled event: {payload}")
try:
state.l2_book = orderbook.reconcile_orderbook(state.l2_book, "OrderCancelled", payload)
print("Updated L2Book:", state.l2_book)
except Exception as e:
print(f"Error reconciling order cancelled: {e}")
print(f"Payload: {payload}")
# print(f"Current L2Book: {state.l2_book}")
# on trade callback that reconciles the orderbook and updates l2_book
def on_trade(payload):
print(f"Received trade event: {payload}")
try:
state.l2_book = orderbook.reconcile_orderbook(state.l2_book, "Trade", payload)
print("Updated L2Book:", state.l2_book)
except Exception as e:
print(f"Error reconciling trade: {e}")
print(f"Payload: {payload}")
# print(f"Current L2Book: {state.l2_book}")
Always disconnect when done
await client.disconnect()
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kuru_sdk-0.2.1.tar.gz.
File metadata
- Download URL: kuru_sdk-0.2.1.tar.gz
- Upload date:
- Size: 27.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e610dec58f3c6b7e40299ab74e7a361785434035b891dc5b93d2f039510a5ef
|
|
| MD5 |
025ed10912ad985604b4dbf805e570b7
|
|
| BLAKE2b-256 |
7a179d594675348a156c9f0d8497bb413b2eb6bc030909ac5084639447792012
|
File details
Details for the file kuru_sdk-0.2.1-py3-none-any.whl.
File metadata
- Download URL: kuru_sdk-0.2.1-py3-none-any.whl
- Upload date:
- Size: 30.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d80f43ee5a08fb00fbee5fa0f37b1bdabea91f02035f35c6ba123191ab772f3
|
|
| MD5 |
be56ca4c9eac3c0634ec999acbb9c31a
|
|
| BLAKE2b-256 |
07f4aca989cc6ff7ed6793558658567c520d9b94e396926a97f8a766d0b3536a
|