Orderbook API
The Orderbook API provides decentralized trading functionality with support for limit orders, market orders, liquidity provision, and multi-hop swaps.
Endpoints
Market Management
Orderbook Data
Order Operations
Trade History
Streaming
Get Markets Info
Get information about all available markets.
Method: GetMarketsInfo
Parameters: None
Response:
| Field | Type | Description |
|---|---|---|
markets | MarketInfo[] | Array of market information |
MarketInfo Object:
| Field | Type | Description |
|---|---|---|
base | CurrencyInfo | Base currency info |
quote | CurrencyInfo | Quote currency info |
taker_base_fee | DecimalString | Taker fee in base currency |
taker_quote_fee | DecimalString | Taker fee in quote currency |
maker_base_fee | DecimalString | Maker fee in base currency |
maker_quote_fee | DecimalString | Maker fee in quote currency |
base_precision | uint32 | Decimal precision for base |
quote_precision | uint32 | Decimal precision for quote |
min_base_amount | DecimalString | Minimum base amount |
min_quote_amount | DecimalString | Minimum quote amount |
Example Request:
TypeScript
import { OrderbookServiceClient } from './proto/OrderbookServiceClientPb'
import { GetMarketsInfoRequest } from './proto/orderbook_pb'
const client = new OrderbookServiceClient('http://localhost:5001')
const request = new GetMarketsInfoRequest()
const response = await client.getMarketsInfo(request, {})
const markets = response.getMarketsList()
Go
import (
"context"
pb "your-package/proto"
)
client := pb.NewOrderbookServiceClient(conn)
request := &pb.GetMarketsInfoRequest{}
response, err := client.GetMarketsInfo(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
markets := response.GetMarkets()
Rust
use tonic::Request;
use your_package::orderbook_service_client::OrderbookServiceClient;
use your_package::GetMarketsInfoRequest;
let mut client = OrderbookServiceClient::connect("http://localhost:5001").await?;
let request = Request::new(GetMarketsInfoRequest {});
let response = client.get_markets_info(request).await?.into_inner();
let markets = response.markets;
Example Response:
{
"markets": [
{
"base": {
"protocol": 0,
"network_id": "0",
"asset_id": "BTC",
"decimals": 8
},
"quote": {
"protocol": 1,
"network_id": "1",
"asset_id": "0x0000000000000000000000000000000000000000",
"decimals": 18
},
"taker_base_fee": "0.001",
"taker_quote_fee": "0.001",
"maker_base_fee": "0.0005",
"maker_quote_fee": "0.0005",
"base_precision": 8,
"quote_precision": 18,
"min_base_amount": "10000",
"min_quote_amount": "1000000000000000"
}
]
}
Get Market Info
Get information about a specific market.
Method: GetMarketInfo
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
first_currency | OrderbookCurrency | YES | First currency of the pair |
other_currency | OrderbookCurrency | YES | Other currency of the pair |
Response:
| Field | Type | Description |
|---|---|---|
market_info | MarketInfo | Market information (optional - null if market doesn't exist) |
Example Request:
TypeScript
const request = new GetMarketInfoRequest()
request.setFirstCurrency({
network: { protocol: 0, chainId: '0', name: 'Bitcoin' },
assetId: 'BTC'
})
request.setOtherCurrency({
network: { protocol: 1, chainId: '1', name: 'Ethereum' },
assetId: '0x0000000000000000000000000000000000000000'
})
const response = await client.getMarketInfo(request, {})
const marketInfo = response.getMarketInfo()
Go
request := &pb.GetMarketInfoRequest{
FirstCurrency: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 0, ChainId: "0", Name: "Bitcoin"},
AssetId: "BTC",
},
OtherCurrency: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 1, ChainId: "1", Name: "Ethereum"},
AssetId: "0x0000000000000000000000000000000000000000",
},
}
response, err := client.GetMarketInfo(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
marketInfo := response.GetMarketInfo()
Rust
let request = Request::new(GetMarketInfoRequest {
first_currency: Some(OrderbookCurrency {
network: Some(Network {
protocol: 0,
chain_id: "0".to_string(),
name: "Bitcoin".to_string(),
}),
asset_id: "BTC".to_string(),
}),
other_currency: Some(OrderbookCurrency {
network: Some(Network {
protocol: 1,
chain_id: "1".to_string(),
name: "Ethereum".to_string(),
}),
asset_id: "0x0000000000000000000000000000000000000000".to_string(),
}),
});
let response = client.get_market_info(request).await?.into_inner();
let market_info = response.market_info;
Initialize Market
Initialize a new market for a currency pair.
Method: InitMarket
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
first_currency | OrderbookCurrency | YES | First currency |
other_currency | OrderbookCurrency | YES | Other currency |
Response:
| Field | Type | Description |
|---|---|---|
market_info | MarketInfo | Market info (null if pair is invalid) |
Example Request:
TypeScript
const request = new InitMarketRequest()
request.setFirstCurrency({
network: { protocol: 0, chainId: '0', name: 'Bitcoin' },
assetId: 'BTC'
})
request.setOtherCurrency({
network: { protocol: 1, chainId: '1', name: 'Ethereum' },
assetId: '0x0000000000000000000000000000000000000000'
})
const response = await client.initMarket(request, {})
Go
request := &pb.InitMarketRequest{
FirstCurrency: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 0, ChainId: "0", Name: "Bitcoin"},
AssetId: "BTC",
},
OtherCurrency: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 1, ChainId: "1", Name: "Ethereum"},
AssetId: "0x0000000000000000000000000000000000000000",
},
}
response, err := client.InitMarket(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
Rust
let request = Request::new(InitMarketRequest {
first_currency: Some(OrderbookCurrency {
network: Some(Network {
protocol: 0,
chain_id: "0".to_string(),
name: "Bitcoin".to_string(),
}),
asset_id: "BTC".to_string(),
}),
other_currency: Some(OrderbookCurrency {
network: Some(Network {
protocol: 1,
chain_id: "1".to_string(),
name: "Ethereum".to_string(),
}),
asset_id: "0x0000000000000000000000000000000000000000".to_string(),
}),
});
let response = client.init_market(request).await?.into_inner();
Get Initialized Markets
Get all initialized markets.
Method: GetInitializedMarkets
Parameters: None
Response:
| Field | Type | Description |
|---|---|---|
markets | CurrencyInfoPair[] | Array of currency pairs |
Example Request:
TypeScript
const request = new GetInitializedMarketsRequest()
const response = await client.getInitializedMarkets(request, {})
const markets = response.getMarketsList()
Go
request := &pb.GetInitializedMarketsRequest{}
response, err := client.GetInitializedMarkets(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
markets := response.GetMarkets()
Rust
let request = Request::new(GetInitializedMarketsRequest {});
let response = client.get_initialized_markets(request).await?.into_inner();
let markets = response.markets;
Get Orderbook
Get the current orderbook state for a market.
Method: GetOrderbook
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
base | OrderbookCurrency | YES | Base currency |
quote | OrderbookCurrency | YES | Quote currency |
Response:
| Field | Type | Description |
|---|---|---|
orderbook | Orderbook | Orderbook data (optional) |
Orderbook Object:
| Field | Type | Description |
|---|---|---|
info | MarketInfo | Market information |
orders | map<string, LiquidityPosition> | Active liquidity orders (order_id → position) |
LiquidityPosition Object:
| Field | Type | Description |
|---|---|---|
client_pubkey | bytes | Order owner's public key |
min_buy_price | DecimalString | Minimum buy price |
max_buy_price | DecimalString | Maximum buy price |
min_sell_price | DecimalString | Minimum sell price |
max_sell_price | DecimalString | Maximum sell price |
quote_amount | DecimalString | Active quote amount |
base_amount | DecimalString | Active base amount |
inactive_quote_amount | DecimalString | Inactive quote amount |
inactive_base_amount | DecimalString | Inactive base amount |
highest_buy_price | DecimalString | Highest buy price |
lowest_sell_price | DecimalString | Lowest sell price |
remove_on_fill | bool | Remove order after any fill |
Example Request:
TypeScript
const request = new GetOrderbookRequest()
request.setBase({
network: { protocol: 0, chainId: '0', name: 'Bitcoin' },
assetId: 'BTC'
})
request.setQuote({
network: { protocol: 1, chainId: '1', name: 'Ethereum' },
assetId: '0x0000000000000000000000000000000000000000'
})
const response = await client.getOrderbook(request, {})
const orderbook = response.getOrderbook()
Go
request := &pb.GetOrderbookRequest{
Base: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 0, ChainId: "0", Name: "Bitcoin"},
AssetId: "BTC",
},
Quote: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 1, ChainId: "1", Name: "Ethereum"},
AssetId: "0x0000000000000000000000000000000000000000",
},
}
response, err := client.GetOrderbook(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
orderbook := response.GetOrderbook()
Rust
let request = Request::new(GetOrderbookRequest {
base: Some(OrderbookCurrency {
network: Some(Network {
protocol: 0,
chain_id: "0".to_string(),
name: "Bitcoin".to_string(),
}),
asset_id: "BTC".to_string(),
}),
quote: Some(OrderbookCurrency {
network: Some(Network {
protocol: 1,
chain_id: "1".to_string(),
name: "Ethereum".to_string(),
}),
asset_id: "0x0000000000000000000000000000000000000000".to_string(),
}),
});
let response = client.get_orderbook(request).await?.into_inner();
let orderbook = response.orderbook;
Example Response:
{
"orderbook": {
"info": { ... },
"orders": {
"order_abc123": {
"client_pubkey": "02abc...",
"min_buy_price": "27.5",
"max_buy_price": "28.0",
"min_sell_price": "28.5",
"max_sell_price": "29.0",
"quote_amount": "50000000000000000000",
"base_amount": "100000000",
"inactive_quote_amount": "0",
"inactive_base_amount": "0",
"highest_buy_price": "28.0",
"lowest_sell_price": "28.5",
"remove_on_fill": false
}
}
}
}
Get Orderbook Balances
Get your orderbook balances across all currencies.
Method: GetOrderbookBalances
Parameters: None
Response:
| Field | Type | Description |
|---|---|---|
balances | OrderbookBalance[] | Array of balances by currency |
OrderbookBalance Object:
| Field | Type | Description |
|---|---|---|
currency | OrderbookCurrency | Currency identifier |
balance | CurrencyBalance | Balance breakdown |
CurrencyBalance Object:
| Field | Type | Description |
|---|---|---|
sending | DecimalString | Available to send |
receiving | DecimalString | Available to receive |
pending_sending | DecimalString | Pending sends |
pending_receiving | DecimalString | Pending receives |
unavailable_sending | DecimalString | Unavailable for sending |
unavailable_receiving | DecimalString | Unavailable for receiving |
in_use_sending | DecimalString | Locked in active orders (sending) |
in_use_receiving | DecimalString | Locked in active orders (receiving) |
Example Request:
TypeScript
const request = new GetOrderbookBalancesRequest()
const response = await client.getOrderbookBalances(request, {})
const balances = response.getBalancesList()
Go
request := &pb.GetOrderbookBalancesRequest{}
response, err := client.GetOrderbookBalances(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
balances := response.GetBalances()
Rust
let request = Request::new(GetOrderbookBalancesRequest {});
let response = client.get_orderbook_balances(request).await?.into_inner();
let balances = response.balances;
Estimate Order
Estimate order execution before placing it.
Method: EstimateOrder
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
order_variant | OrderVariant | YES | Order details (one of: AddLiquidity, MarketOrder, SwapOrder) |
OrderVariant Types:
AddLiquidity
| Field | Type | Description |
|---|---|---|
base | OrderbookCurrency | Base currency |
quote | OrderbookCurrency | Quote currency |
min_buy_price | DecimalString | Minimum buy price |
mid_price | DecimalString | Middle price |
max_sell_price | DecimalString | Maximum sell price |
amount | OrderAmount | Amount (base or quote) |
remove_on_fill | bool | Remove on any fill |
MarketOrder
| Field | Type | Description |
|---|---|---|
base | OrderbookCurrency | Base currency |
quote | OrderbookCurrency | Quote currency |
amount | OrderAmount | Amount (base or quote) |
side | OrderSide | BUY (0) or SELL (1) |
SwapOrder
| Field | Type | Description |
|---|---|---|
from_currency | OrderbookCurrency | Starting currency |
currency_path | OrderbookCurrency[] | Intermediate currencies |
to_currency | OrderbookCurrency | Destination currency |
amount | SwapAmount | Amount (sending or receiving) |
Response:
| Field | Type | Description |
|---|---|---|
order_match | OrderMatch | Estimated execution (optional) |
Example Request (Market Order):
TypeScript
const request = new EstimateOrderRequest()
request.setOrderVariant({
marketOrder: {
base: {
network: { protocol: 0, chainId: '0', name: 'Bitcoin' },
assetId: 'BTC'
},
quote: {
network: { protocol: 1, chainId: '1', name: 'Ethereum' },
assetId: '0x0000000000000000000000000000000000000000'
},
amount: { base: { amount: '1000000' } }, // 0.01 BTC
side: OrderSide.BUY
}
})
const response = await client.estimateOrder(request, {})
const match = response.getOrderMatch()
Go
request := &pb.EstimateOrderRequest{
OrderVariant: &pb.OrderVariant{
Variant: &pb.OrderVariant_MarketOrder{
MarketOrder: &pb.MarketOrder{
Base: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 0, ChainId: "0", Name: "Bitcoin"},
AssetId: "BTC",
},
Quote: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 1, ChainId: "1", Name: "Ethereum"},
AssetId: "0x0000000000000000000000000000000000000000",
},
Amount: &pb.OrderAmount{
Amount: &pb.OrderAmount_Base{
Base: &pb.BaseAmount{Amount: "1000000"},
},
},
Side: pb.OrderSide_BUY,
},
},
},
}
response, err := client.EstimateOrder(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
match := response.GetOrderMatch()
Rust
use your_package::order_variant::Variant;
let request = Request::new(EstimateOrderRequest {
order_variant: Some(OrderVariant {
variant: Some(Variant::MarketOrder(MarketOrder {
base: Some(OrderbookCurrency {
network: Some(Network {
protocol: 0,
chain_id: "0".to_string(),
name: "Bitcoin".to_string(),
}),
asset_id: "BTC".to_string(),
}),
quote: Some(OrderbookCurrency {
network: Some(Network {
protocol: 1,
chain_id: "1".to_string(),
name: "Ethereum".to_string(),
}),
asset_id: "0x0000000000000000000000000000000000000000".to_string(),
}),
amount: Some(order_amount::Amount::Base(BaseAmount {
amount: "1000000".to_string(),
})),
side: OrderSide::Buy as i32,
})),
}),
});
let response = client.estimate_order(request).await?.into_inner();
let match_result = response.order_match;
Example Request (Add Liquidity):
TypeScript
const request = new EstimateOrderRequest()
request.setOrderVariant({
addLiquidity: {
base: { ... },
quote: { ... },
minBuyPrice: '27.5',
midPrice: '28.0',
maxSellPrice: '28.5',
amount: { quote: { amount: '50000000000000000000' } }, // 50 ETH
removeOnFill: false
}
})
const response = await client.estimateOrder(request, {})
Go
request := &pb.EstimateOrderRequest{
OrderVariant: &pb.OrderVariant{
Variant: &pb.OrderVariant_AddLiquidity{
AddLiquidity: &pb.AddLiquidity{
Base: &pb.OrderbookCurrency{...},
Quote: &pb.OrderbookCurrency{...},
MinBuyPrice: "27.5",
MidPrice: "28.0",
MaxSellPrice: "28.5",
Amount: &pb.OrderAmount{
Amount: &pb.OrderAmount_Quote{
Quote: &pb.QuoteAmount{Amount: "50000000000000000000"},
},
},
RemoveOnFill: false,
},
},
},
}
response, err := client.EstimateOrder(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
Rust
let request = Request::new(EstimateOrderRequest {
order_variant: Some(OrderVariant {
variant: Some(Variant::AddLiquidity(AddLiquidity {
base: Some(OrderbookCurrency {...}),
quote: Some(OrderbookCurrency {...}),
min_buy_price: "27.5".to_string(),
mid_price: "28.0".to_string(),
max_sell_price: "28.5".to_string(),
amount: Some(order_amount::Amount::Quote(QuoteAmount {
amount: "50000000000000000000".to_string(),
})),
remove_on_fill: false,
})),
}),
});
let response = client.estimate_order(request).await?.into_inner();
Create Order
Place a new order in the orderbook.
Method: CreateOrder
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
order_variant | OrderVariant | YES | Order details |
Response:
| Field | Type | Description |
|---|---|---|
order_id | string | Unique order identifier |
Example Request:
TypeScript
const request = new CreateOrderRequest()
request.setOrderVariant({
marketOrder: {
base: {
network: { protocol: 0, chainId: '0', name: 'Bitcoin' },
assetId: 'BTC'
},
quote: {
network: { protocol: 1, chainId: '1', name: 'Ethereum' },
assetId: '0x0000000000000000000000000000000000000000'
},
amount: { base: { amount: '1000000' } },
side: OrderSide.SELL
}
})
const response = await client.createOrder(request, {})
const orderId = response.getOrderId()
console.log('Order created:', orderId)
Go
request := &pb.CreateOrderRequest{
OrderVariant: &pb.OrderVariant{
Variant: &pb.OrderVariant_MarketOrder{
MarketOrder: &pb.MarketOrder{
Base: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 0, ChainId: "0", Name: "Bitcoin"},
AssetId: "BTC",
},
Quote: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 1, ChainId: "1", Name: "Ethereum"},
AssetId: "0x0000000000000000000000000000000000000000",
},
Amount: &pb.OrderAmount{
Amount: &pb.OrderAmount_Base{
Base: &pb.BaseAmount{Amount: "1000000"},
},
},
Side: pb.OrderSide_SELL,
},
},
},
}
response, err := client.CreateOrder(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
orderId := response.GetOrderId()
fmt.Printf("Order created: %s\n", orderId)
Rust
let request = Request::new(CreateOrderRequest {
order_variant: Some(OrderVariant {
variant: Some(Variant::MarketOrder(MarketOrder {
base: Some(OrderbookCurrency {
network: Some(Network {
protocol: 0,
chain_id: "0".to_string(),
name: "Bitcoin".to_string(),
}),
asset_id: "BTC".to_string(),
}),
quote: Some(OrderbookCurrency {
network: Some(Network {
protocol: 1,
chain_id: "1".to_string(),
name: "Ethereum".to_string(),
}),
asset_id: "0x0000000000000000000000000000000000000000".to_string(),
}),
amount: Some(order_amount::Amount::Base(BaseAmount {
amount: "1000000".to_string(),
})),
side: OrderSide::Sell as i32,
})),
}),
});
let response = client.create_order(request).await?.into_inner();
let order_id = response.order_id;
println!("Order created: {}", order_id);
Cancel Order
Cancel an existing order.
Method: CancelOrder
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
order_id | string | YES | Order ID to cancel |
Response:
| Field | Type | Description |
|---|---|---|
removed | bool | Whether order was removed |
Example Request:
TypeScript
const request = new CancelOrderRequest()
request.setOrderId('order_abc123')
const response = await client.cancelOrder(request, {})
if (response.getRemoved()) {
console.log('Order cancelled successfully')
}
Go
request := &pb.CancelOrderRequest{
OrderId: "order_abc123",
}
response, err := client.CancelOrder(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
if response.GetRemoved() {
fmt.Println("Order cancelled successfully")
}
Rust
let request = Request::new(CancelOrderRequest {
order_id: "order_abc123".to_string(),
});
let response = client.cancel_order(request).await?.into_inner();
if response.removed {
println!("Order cancelled successfully");
}
Cancel All Orders
Cancel all your active orders.
Method: CancelAllOrders
Parameters: None
Response: Empty (success confirmation)
Example Request:
TypeScript
const request = new CancelAllOrdersRequest()
await client.cancelAllOrders(request, {})
console.log('All orders cancelled')
Go
request := &pb.CancelAllOrdersRequest{}
_, err := client.CancelAllOrders(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
fmt.Println("All orders cancelled")
Rust
let request = Request::new(CancelAllOrdersRequest {});
client.cancel_all_orders(request).await?;
println!("All orders cancelled");
Get Order
Get details of a specific order.
Method: GetOrder
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
order_id | string | YES | Order ID |
Response:
| Field | Type | Description |
|---|---|---|
order | Order | Order details |
Order Object (one of):
PairOrder (LiquidityOrder or MarketOrder)
LiquidityOrder:
| Field | Type | Description |
|---|---|---|
base | OrderbookCurrency | Base currency |
quote | OrderbookCurrency | Quote currency |
created_at | Timestamp | Creation time |
min_buy_price | DecimalString | Min buy price |
max_buy_price | DecimalString | Max buy price |
min_sell_price | DecimalString | Min sell price |
max_sell_price | DecimalString | Max sell price |
remaining_base_amount | DecimalString | Remaining base |
remaining_quote_amount | DecimalString | Remaining quote |
paid_base_fee | DecimalString | Fees paid in base |
paid_quote_fee | DecimalString | Fees paid in quote |
filled | Filled | Fill details (optional) |
MarketOrder:
| Field | Type | Description |
|---|---|---|
base | OrderbookCurrency | Base currency |
quote | OrderbookCurrency | Quote currency |
created_at | Timestamp | Creation time |
remaining_amount | OrderAmount | Remaining amount |
unmatched_amount | OrderAmount | Unmatched amount |
buy or sell | Buy or Sell | Execution details |
SwapOrder
| Field | Type | Description |
|---|---|---|
from_currency | OrderbookCurrency | Source currency |
currency_path | OrderbookCurrency[] | Route |
to_currency | OrderbookCurrency | Destination currency |
created_at | Timestamp | Creation time |
remaining_amount | SwapAmount | Remaining |
unmatched_amount | SwapAmount | Unmatched |
sold_from_currency_amount | DecimalString | Sold amount |
bought_to_currency_amount | DecimalString | Bought amount |
paid_to_currency_fee | DecimalString | Fee paid |
Example Request:
TypeScript
const request = new GetOrderRequest()
request.setOrderId('order_abc123')
const response = await client.getOrder(request, {})
const order = response.getOrder()
Go
request := &pb.GetOrderRequest{
OrderId: "order_abc123",
}
response, err := client.GetOrder(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
order := response.GetOrder()
Rust
let request = Request::new(GetOrderRequest {
order_id: "order_abc123".to_string(),
});
let response = client.get_order(request).await?.into_inner();
let order = response.order;
Get Own Orders
Get your orders for a specific market.
Method: GetOwnOrders
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
base | OrderbookCurrency | YES | Base currency |
quote | OrderbookCurrency | YES | Quote currency |
Response:
| Field | Type | Description |
|---|---|---|
orders | map<string, Order> | Map of order_id → Order |
Example Request:
TypeScript
const request = new GetOwnOrdersRequest()
request.setBase({
network: { protocol: 0, chainId: '0', name: 'Bitcoin' },
assetId: 'BTC'
})
request.setQuote({
network: { protocol: 1, chainId: '1', name: 'Ethereum' },
assetId: '0x0000000000000000000000000000000000000000'
})
const response = await client.getOwnOrders(request, {})
const orders = response.getOrdersMap()
Go
request := &pb.GetOwnOrdersRequest{
Base: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 0, ChainId: "0", Name: "Bitcoin"},
AssetId: "BTC",
},
Quote: &pb.OrderbookCurrency{
Network: &pb.Network{Protocol: 1, ChainId: "1", Name: "Ethereum"},
AssetId: "0x0000000000000000000000000000000000000000",
},
}
response, err := client.GetOwnOrders(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
orders := response.GetOrders()
Rust
let request = Request::new(GetOwnOrdersRequest {
base: Some(OrderbookCurrency {
network: Some(Network {
protocol: 0,
chain_id: "0".to_string(),
name: "Bitcoin".to_string(),
}),
asset_id: "BTC".to_string(),
}),
quote: Some(OrderbookCurrency {
network: Some(Network {
protocol: 1,
chain_id: "1".to_string(),
name: "Ethereum".to_string(),
}),
asset_id: "0x0000000000000000000000000000000000000000".to_string(),
}),
});
let response = client.get_own_orders(request).await?.into_inner();
let orders = response.orders;
Get All Own Orders
Get all your orders across all markets.
Method: GetAllOwnOrders
Parameters: None
Response:
| Field | Type | Description |
|---|---|---|
orders | map<string, Order> | Map of order_id → Order |
Example Request:
TypeScript
const request = new GetAllOwnOrdersRequest()
const response = await client.getAllOwnOrders(request, {})
const allOrders = response.getOrdersMap()
Go
request := &pb.GetAllOwnOrdersRequest{}
response, err := client.GetAllOwnOrders(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
allOrders := response.GetOrders()
Rust
let request = Request::new(GetAllOwnOrdersRequest {});
let response = client.get_all_own_orders(request).await?.into_inner();
let all_orders = response.orders;
Get Trade History
Get public trade history for a market.
Method: GetTradeHistory
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
base | OrderbookCurrency | YES | Base currency |
quote | OrderbookCurrency | YES | Quote currency |
Response:
| Field | Type | Description |
|---|---|---|
trade_history | Trade[] | Trades (sorted newest first) |
Trade Object:
| Field | Type | Description |
|---|---|---|
taker_order_id | string | Taker's order ID |
base_amount | DecimalString | Base amount traded |
quote_amount | DecimalString | Quote amount traded |
price | DecimalString | Execution price |
final_price | DecimalString | Final price after fees |
timestamp | Timestamp | Trade time |
maker_order_side | OrderSide | Maker side (BUY/SELL) |
Example Request:
TypeScript
const request = new GetTradeHistoryRequest()
request.setBase({ ... })
request.setQuote({ ... })
const response = await client.getTradeHistory(request, {})
const trades = response.getTradeHistoryList()
Go
request := &pb.GetTradeHistoryRequest{
Base: &pb.OrderbookCurrency{...},
Quote: &pb.OrderbookCurrency{...},
}
response, err := client.GetTradeHistory(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
trades := response.GetTradeHistory()
Rust
let request = Request::new(GetTradeHistoryRequest {
base: Some(OrderbookCurrency {...}),
quote: Some(OrderbookCurrency {...}),
});
let response = client.get_trade_history(request).await?.into_inner();
let trades = response.trade_history;
Get Pair Market Trades
Get your market trades for a specific pair.
Method: GetPairMarketTrades
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
base | OrderbookCurrency | YES | Base currency |
quote | OrderbookCurrency | YES | Quote currency |
Response:
| Field | Type | Description |
|---|---|---|
trades | ClientMarketTrade[] | Your trades (newest first) |
ClientMarketTrade Object:
| Field | Type | Description |
|---|---|---|
swap_id | string | Swap identifier |
order_id | string | Order identifier |
base_amount | DecimalString | Base amount |
quote_amount | DecimalString | Quote amount |
base_fee | DecimalString | Fee in base |
quote_fee | DecimalString | Fee in quote |
price | DecimalString | Price |
final_price | DecimalString | Final price |
timestamp | Timestamp | Trade time |
order_side | OrderSide | BUY/SELL |
order_type | OrderType | LIMIT/MARKET/LIQUIDITY/SWAP |
Example Request:
TypeScript
const request = new GetPairMarketTradesRequest()
request.setBase({ ... })
request.setQuote({ ... })
const response = await client.getPairMarketTrades(request, {})
const trades = response.getTradesList()
Go
request := &pb.GetPairMarketTradesRequest{
Base: &pb.OrderbookCurrency{...},
Quote: &pb.OrderbookCurrency{...},
}
response, err := client.GetPairMarketTrades(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
trades := response.GetTrades()
Rust
let request = Request::new(GetPairMarketTradesRequest {
base: Some(OrderbookCurrency {...}),
quote: Some(OrderbookCurrency {...}),
});
let response = client.get_pair_market_trades(request).await?.into_inner();
let trades = response.trades;
Get All Market Trades
Get all your market trades across all pairs.
Method: GetAllMarketTrades
Parameters: None
Response:
| Field | Type | Description |
|---|---|---|
pair_market_trades | PairMarketTrades[] | Trades grouped by pair |
Example Request:
TypeScript
const request = new GetAllMarketTradesRequest()
const response = await client.getAllMarketTrades(request, {})
const trades = response.getPairMarketTradesList()
Go
request := &pb.GetAllMarketTradesRequest{}
response, err := client.GetAllMarketTrades(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
trades := response.GetPairMarketTrades()
Rust
let request = Request::new(GetAllMarketTradesRequest {});
let response = client.get_all_market_trades(request).await?.into_inner();
let trades = response.pair_market_trades;
Get Pair Swap Trades
Get your swap trades for a specific currency pair.
Method: GetPairSwapTrades
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
from_currency | OrderbookCurrency | YES | Source currency |
to_currency | OrderbookCurrency | YES | Destination currency |
Response:
| Field | Type | Description |
|---|---|---|
trades | ClientSwapTrade[] | Swap trades (newest first) |
ClientSwapTrade Object:
| Field | Type | Description |
|---|---|---|
swap_id | string | Swap identifier |
order_id | string | Order identifier |
from_currency_amount | DecimalString | Amount sent |
to_currency_amount | DecimalString | Amount received |
to_currency_fee | DecimalString | Fee paid |
timestamp | Timestamp | Trade time |
Example Request:
TypeScript
const request = new GetPairSwapTradesRequest()
request.setFromCurrency({ ... })
request.setToCurrency({ ... })
const response = await client.getPairSwapTrades(request, {})
const swapTrades = response.getTradesList()
Go
request := &pb.GetPairSwapTradesRequest{
FromCurrency: &pb.OrderbookCurrency{...},
ToCurrency: &pb.OrderbookCurrency{...},
}
response, err := client.GetPairSwapTrades(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
swapTrades := response.GetTrades()
Rust
let request = Request::new(GetPairSwapTradesRequest {
from_currency: Some(OrderbookCurrency {...}),
to_currency: Some(OrderbookCurrency {...}),
});
let response = client.get_pair_swap_trades(request).await?.into_inner();
let swap_trades = response.trades;
Get All Swap Trades
Get all your swap trades.
Method: GetAllSwapTrades
Parameters: None
Response:
| Field | Type | Description |
|---|---|---|
pair_swap_trades | PairSwapTrades[] | Swaps grouped by currency pair |
Example Request:
TypeScript
const request = new GetAllSwapTradesRequest()
const response = await client.getAllSwapTrades(request, {})
const allSwaps = response.getPairSwapTradesList()
Go
request := &pb.GetAllSwapTradesRequest{}
response, err := client.GetAllSwapTrades(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
allSwaps := response.GetPairSwapTrades()
Rust
let request = Request::new(GetAllSwapTradesRequest {});
let response = client.get_all_swap_trades(request).await?.into_inner();
let all_swaps = response.pair_swap_trades;
Subscribe Market Events
Stream real-time market updates.
Method: SubscribeMarketEvents
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
base | OrderbookCurrency | YES | Base currency |
quote | OrderbookCurrency | YES | Quote currency |
Response: Stream of MarketEvent
MarketEvent Types:
| Event | Description |
|---|---|
is_synced | Initial sync complete |
orderbook_update | Orderbook changed |
trade_update | Trade executed |
daily_stats_update | 24h stats updated |
candlestick_update | New candlestick data |
Example:
TypeScript
const request = new SubscribeMarketEventsRequest()
request.setBase({ ... })
request.setQuote({ ... })
const stream = client.subscribeMarketEvents(request, {})
stream.on('data', (event) => {
if (event.hasIsSynced()) {
console.log('Market synced')
}
if (event.hasOrderbookUpdate()) {
const update = event.getOrderbookUpdate()
console.log('Orderbook updated:', update)
}
if (event.hasTradeUpdate()) {
const trade = event.getTradeUpdate()
console.log('Trade:', trade.getBaseAmount(), '@', trade.getPrice())
}
if (event.hasDailyStatsUpdate()) {
const stats = event.getDailyStatsUpdate()
console.log('24h volume:', stats.getVolatility()?.getBaseVolume())
}
if (event.hasCandlestickUpdate()) {
const candle = event.getCandlestickUpdate()
console.log('Candle:', candle.getInterval(), candle.getCandlestick())
}
})
stream.on('error', (err) => console.error('Stream error:', err))
stream.on('end', () => console.log('Stream ended'))
Go
request := &pb.SubscribeMarketEventsRequest{
Base: &pb.OrderbookCurrency{...},
Quote: &pb.OrderbookCurrency{...},
}
stream, err := client.SubscribeMarketEvents(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
for {
event, err := stream.Recv()
if err != nil {
log.Printf("Stream error: %v", err)
break
}
if event.GetIsSynced() {
fmt.Println("Market synced")
}
if update := event.GetOrderbookUpdate(); update != nil {
fmt.Printf("Orderbook updated: %v\n", update)
}
if trade := event.GetTradeUpdate(); trade != nil {
fmt.Printf("Trade: %s @ %s\n", trade.GetBaseAmount(), trade.GetPrice())
}
if stats := event.GetDailyStatsUpdate(); stats != nil {
fmt.Printf("24h volume: %s\n", stats.GetVolatility().GetBaseVolume())
}
if candle := event.GetCandlestickUpdate(); candle != nil {
fmt.Printf("Candle: %v %v\n", candle.GetInterval(), candle.GetCandlestick())
}
}
Rust
use tokio_stream::StreamExt;
let request = Request::new(SubscribeMarketEventsRequest {
base: Some(OrderbookCurrency {...}),
quote: Some(OrderbookCurrency {...}),
});
let mut stream = client.subscribe_market_events(request).await?.into_inner();
while let Some(event) = stream.next().await {
let event = event?;
if event.is_synced {
println!("Market synced");
}
if let Some(update) = event.orderbook_update {
println!("Orderbook updated: {:?}", update);
}
if let Some(trade) = event.trade_update {
println!("Trade: {} @ {}", trade.base_amount, trade.price);
}
if let Some(stats) = event.daily_stats_update {
if let Some(vol) = stats.volatility {
println!("24h volume: {}", vol.base_volume);
}
}
if let Some(candle) = event.candlestick_update {
println!("Candle: {:?} {:?}", candle.interval, candle.candlestick);
}
}
Subscribe DEX Events
Stream all your DEX activity (orders, balances, swaps).
Method: SubscribeDexEvents
Parameters: None
Response: Stream of DexEvent
DexEvent Types:
| Event | Description |
|---|---|
is_synced | Initial sync complete |
balance_update | Balance changed |
order_update | Order created/updated/completed/cancelled |
order_matched | Your order matched |
swap_update | Swap progress update |
market_trade_update | Market trade completed |
swap_trade_update | Swap trade completed |
Example:
TypeScript
const request = new SubscribeDexEventsRequest()
const stream = client.subscribeDexEvents(request, {})
stream.on('data', (event) => {
const timestamp = event.getTimestamp()
if (event.hasBalanceUpdate()) {
const balance = event.getBalanceUpdate()
console.log('Balance updated:', balance.getCurrency(), balance.getBalance())
}
if (event.hasOrderUpdate()) {
const update = event.getOrderUpdate()
if (update.hasOrderCreated()) {
console.log('Order created:', update.getOrderCreated().getOrderId())
}
if (update.hasOrderCompleted()) {
console.log('Order completed:', update.getOrderCompleted().getOrderId())
}
}
if (event.hasOrderMatched()) {
const matched = event.getOrderMatched()
console.log('Order matched:', matched.getOwnOrderId())
console.log('Is taker:', matched.getIsTaker())
}
if (event.hasSwapUpdate()) {
const swap = event.getSwapUpdate()
const progress = swap.getProgress()
console.log('Swap status:', progress.getStatus())
if (progress.hasError()) {
console.error('Swap error:', progress.getError())
}
}
})
Go
request := &pb.SubscribeDexEventsRequest{}
stream, err := client.SubscribeDexEvents(context.Background(), request)
if err != nil {
log.Fatalf("Error: %v", err)
}
for {
event, err := stream.Recv()
if err != nil {
log.Printf("Stream error: %v", err)
break
}
timestamp := event.GetTimestamp()
if balance := event.GetBalanceUpdate(); balance != nil {
fmt.Printf("Balance updated: %v %v\n",
balance.GetCurrency(), balance.GetBalance())
}
if update := event.GetOrderUpdate(); update != nil {
if created := update.GetOrderCreated(); created != nil {
fmt.Printf("Order created: %s\n", created.GetOrderId())
}
if completed := update.GetOrderCompleted(); completed != nil {
fmt.Printf("Order completed: %s\n", completed.GetOrderId())
}
}
if matched := event.GetOrderMatched(); matched != nil {
fmt.Printf("Order matched: %s\n", matched.GetOwnOrderId())
fmt.Printf("Is taker: %v\n", matched.GetIsTaker())
}
if swap := event.GetSwapUpdate(); swap != nil {
progress := swap.GetProgress()
fmt.Printf("Swap status: %v\n", progress.GetStatus())
if errMsg := progress.GetError(); errMsg != "" {
fmt.Printf("Swap error: %s\n", errMsg)
}
}
}
Rust
use tokio_stream::StreamExt;
let request = Request::new(SubscribeDexEventsRequest {});
let mut stream = client.subscribe_dex_events(request).await?.into_inner();
while let Some(event) = stream.next().await {
let event = event?;
let timestamp = event.timestamp;
if let Some(balance) = event.balance_update {
println!("Balance updated: {:?} {:?}",
balance.currency, balance.balance);
}
if let Some(update) = event.order_update {
if let Some(created) = update.order_created {
println!("Order created: {}", created.order_id);
}
if let Some(completed) = update.order_completed {
println!("Order completed: {}", completed.order_id);
}
}
if let Some(matched) = event.order_matched {
println!("Order matched: {}", matched.own_order_id);
println!("Is taker: {}", matched.is_taker);
}
if let Some(swap) = event.swap_update {
if let Some(progress) = swap.progress {
println!("Swap status: {:?}", progress.status);
if let Some(error) = progress.error {
eprintln!("Swap error: {}", error);
}
}
}
}
Enums Reference
OrderSide
| Value | Description |
|---|---|
BUY (0) | Buy base with quote |
SELL (1) | Sell base for quote |
OrderType
| Value | Description |
|---|---|
LIMIT (0) | Limit order |
LIQUIDITY (1) | Liquidity provision order |
MARKET (2) | Market order |
SWAP (3) | Multi-hop swap order |
SwapStatus
| Value | Description |
|---|---|
ORDER_MATCHED (0) | Order matched with counterparty |
RECEIVING_INVOICE_CREATED (1) | Invoice created for receiving |
PAYING_INVOICE_RECEIVED (2) | Payment invoice received |
PAYMENT_SENT (3) | Payment sent |
PAYMENT_RECEIVED (4) | Payment received |
PAYMENT_CLAIMED (5) | Payment claimed by you |
PAYMENT_CLAIMED_BY_COUNTERPARTY (6) | Counterparty claimed |
SWAP_COMPLETED (7) | Swap successful |
SWAP_FAILED (8) | Swap failed |
CandlestickInterval
| Value | Description |
|---|---|
ONE_MINUTE (0) | 1m candles |
THREE_MINUTES (1) | 3m candles |
FIVE_MINUTES (2) | 5m candles |
FIFTEEN_MINUTES (3) | 15m candles |
THIRTY_MINUTES (4) | 30m candles |
ONE_HOUR (5) | 1h candles |
TWO_HOURS (6) | 2h candles |
FOUR_HOURS (7) | 4h candles |
SIX_HOURS (8) | 6h candles |
EIGHT_HOURS (9) | 8h candles |
TWELVE_HOURS (10) | 12h candles |
ONE_DAY (11) | 1d candles |
THREE_DAYS (12) | 3d candles |
ONE_WEEK (13) | 1w candles |
ONE_MONTH (14) | 1M candles |
Common Workflows
Place a limit order (liquidity provision)
TypeScript
async function placeLimitOrder(
client: OrderbookServiceClient,
base: OrderbookCurrency,
quote: OrderbookCurrency,
midPrice: string,
spreadPercent: number,
quoteAmount: string
) {
const spread = parseFloat(midPrice) * (spreadPercent / 100)
const minBuyPrice = (parseFloat(midPrice) - spread).toString()
const maxSellPrice = (parseFloat(midPrice) + spread).toString()
// Estimate first
const estimateReq = new EstimateOrderRequest()
estimateReq.setOrderVariant({
addLiquidity: {
base,
quote,
minBuyPrice,
midPrice,
maxSellPrice,
amount: { quote: { amount: quoteAmount } },
removeOnFill: false
}
})
const estimate = await client.estimateOrder(estimateReq, {})
console.log('Estimated match:', estimate.getOrderMatch())
// Create order
const createReq = new CreateOrderRequest()
createReq.setOrderVariant({
addLiquidity: {
base,
quote,
minBuyPrice,
midPrice,
maxSellPrice,
amount: { quote: { amount: quoteAmount } },
removeOnFill: false
}
})
const response = await client.createOrder(createReq, {})
return response.getOrderId()
}
// Example: Provide liquidity at 28 ETH/BTC with 1% spread
const orderId = await placeLimitOrder(
client,
btcCurrency,
ethCurrency,
'28.0', // mid price
1.0, // 1% spread
'50000000000000000000' // 50 ETH
)
Go
func placeLimitOrder(
client pb.OrderbookServiceClient,
base *pb.OrderbookCurrency,
quote *pb.OrderbookCurrency,
midPrice string,
spreadPercent float64,
quoteAmount string,
) (string, error) {
midPriceFloat, _ := strconv.ParseFloat(midPrice, 64)
spread := midPriceFloat * (spreadPercent / 100)
minBuyPrice := fmt.Sprintf("%f", midPriceFloat-spread)
maxSellPrice := fmt.Sprintf("%f", midPriceFloat+spread)
// Estimate first
estimateReq := &pb.EstimateOrderRequest{
OrderVariant: &pb.OrderVariant{
Variant: &pb.OrderVariant_AddLiquidity{
AddLiquidity: &pb.AddLiquidity{
Base: base,
Quote: quote,
MinBuyPrice: minBuyPrice,
MidPrice: midPrice,
MaxSellPrice: maxSellPrice,
Amount: &pb.OrderAmount{
Amount: &pb.OrderAmount_Quote{
Quote: &pb.QuoteAmount{Amount: quoteAmount},
},
},
RemoveOnFill: false,
},
},
},
}
estimate, err := client.EstimateOrder(context.Background(), estimateReq)
if err != nil {
return "", err
}
fmt.Printf("Estimated match: %v\n", estimate.GetOrderMatch())
// Create order
createReq := &pb.CreateOrderRequest{
OrderVariant: estimateReq.OrderVariant,
}
response, err := client.CreateOrder(context.Background(), createReq)
if err != nil {
return "", err
}
return response.GetOrderId(), nil
}
// Example: Provide liquidity at 28 ETH/BTC with 1% spread
orderId, err := placeLimitOrder(
client,
btcCurrency,
ethCurrency,
"28.0", // mid price
1.0, // 1% spread
"50000000000000000000", // 50 ETH
)
Rust
async fn place_limit_order(
client: &mut OrderbookServiceClient<Channel>,
base: OrderbookCurrency,
quote: OrderbookCurrency,
mid_price: &str,
spread_percent: f64,
quote_amount: &str,
) -> Result<String, Box<dyn std::error::Error>> {
let mid_price_float: f64 = mid_price.parse()?;
let spread = mid_price_float * (spread_percent / 100.0);
let min_buy_price = (mid_price_float - spread).to_string();
let max_sell_price = (mid_price_float + spread).to_string();
// Estimate first
let estimate_req = Request::new(EstimateOrderRequest {
order_variant: Some(OrderVariant {
variant: Some(Variant::AddLiquidity(AddLiquidity {
base: Some(base.clone()),
quote: Some(quote.clone()),
min_buy_price: min_buy_price.clone(),
mid_price: mid_price.to_string(),
max_sell_price: max_sell_price.clone(),
amount: Some(order_amount::Amount::Quote(QuoteAmount {
amount: quote_amount.to_string(),
})),
remove_on_fill: false,
})),
}),
});
let estimate = client.estimate_order(estimate_req).await?.into_inner();
println!("Estimated match: {:?}", estimate.order_match);
// Create order
let create_req = Request::new(CreateOrderRequest {
order_variant: Some(OrderVariant {
variant: Some(Variant::AddLiquidity(AddLiquidity {
base: Some(base),
quote: Some(quote),
min_buy_price,
mid_price: mid_price.to_string(),
max_sell_price,
amount: Some(order_amount::Amount::Quote(QuoteAmount {
amount: quote_amount.to_string(),
})),
remove_on_fill: false,
})),
}),
});
let response = client.create_order(create_req).await?.into_inner();
Ok(response.order_id)
}
// Example: Provide liquidity at 28 ETH/BTC with 1% spread
let order_id = place_limit_order(
&mut client,
btc_currency,
eth_currency,
"28.0", // mid price
1.0, // 1% spread
"50000000000000000000", // 50 ETH
).await?;
Execute market order
TypeScript
async function buyMarket(
client: OrderbookServiceClient,
base: OrderbookCurrency,
quote: OrderbookCurrency,
baseAmount: string
) {
const request = new CreateOrderRequest()
request.setOrderVariant({
marketOrder: {
base,
quote,
amount: { base: { amount: baseAmount } },
side: OrderSide.BUY
}
})
const response = await client.createOrder(request, {})
return response.getOrderId()
}
Go
func buyMarket(
client pb.OrderbookServiceClient,
base *pb.OrderbookCurrency,
quote *pb.OrderbookCurrency,
baseAmount string,
) (string, error) {
request := &pb.CreateOrderRequest{
OrderVariant: &pb.OrderVariant{
Variant: &pb.OrderVariant_MarketOrder{
MarketOrder: &pb.MarketOrder{
Base: base,
Quote: quote,
Amount: &pb.OrderAmount{
Amount: &pb.OrderAmount_Base{
Base: &pb.BaseAmount{Amount: baseAmount},
},
},
Side: pb.OrderSide_BUY,
},
},
},
}
response, err := client.CreateOrder(context.Background(), request)
if err != nil {
return "", err
}
return response.GetOrderId(), nil
}
Rust
async fn buy_market(
client: &mut OrderbookServiceClient<Channel>,
base: OrderbookCurrency,
quote: OrderbookCurrency,
base_amount: &str,
) -> Result<String, Box<dyn std::error::Error>> {
let request = Request::new(CreateOrderRequest {
order_variant: Some(OrderVariant {
variant: Some(Variant::MarketOrder(MarketOrder {
base: Some(base),
quote: Some(quote),
amount: Some(order_amount::Amount::Base(BaseAmount {
amount: base_amount.to_string(),
})),
side: OrderSide::Buy as i32,
})),
}),
});
let response = client.create_order(request).await?.into_inner();
Ok(response.order_id)
}
Multi-hop swap
TypeScript
async function swapBTCtoUSDT(
client: OrderbookServiceClient,
amount: string
) {
// BTC → ETH → USDT
const request = new CreateOrderRequest()
request.setOrderVariant({
swapOrder: {
fromCurrency: btcCurrency,
currencyPath: [ethCurrency],
toCurrency: usdtCurrency,
amount: { sending: { value: amount } }
}
})
const response = await client.createOrder(request, {})
return response.getOrderId()
}
Go
func swapBTCtoUSDT(
client pb.OrderbookServiceClient,
amount string,
) (string, error) {
// BTC → ETH → USDT
request := &pb.CreateOrderRequest{
OrderVariant: &pb.OrderVariant{
Variant: &pb.OrderVariant_SwapOrder{
SwapOrder: &pb.SwapOrder{
FromCurrency: btcCurrency,
CurrencyPath: []*pb.OrderbookCurrency{ethCurrency},
ToCurrency: usdtCurrency,
Amount: &pb.SwapAmount{
Amount: &pb.SwapAmount_Sending{
Sending: &pb.SendingAmount{Value: amount},
},
},
},
},
},
}
response, err := client.CreateOrder(context.Background(), request)
if err != nil {
return "", err
}
return response.GetOrderId(), nil
}
Rust
async fn swap_btc_to_usdt(
client: &mut OrderbookServiceClient<Channel>,
amount: &str,
) -> Result<String, Box<dyn std::error::Error>> {
// BTC → ETH → USDT
let request = Request::new(CreateOrderRequest {
order_variant: Some(OrderVariant {
variant: Some(Variant::SwapOrder(SwapOrder {
from_currency: Some(btc_currency),
currency_path: vec![eth_currency],
to_currency: Some(usdt_currency),
amount: Some(swap_amount::Amount::Sending(SendingAmount {
value: amount.to_string(),
})),
})),
}),
});
let response = client.create_order(request).await?.into_inner();
Ok(response.order_id)
}
Best Practices
- Always estimate before creating - Use
EstimateOrderto verify liquidity - Subscribe to DEX events - Monitor your orders in real-time
- Check orderbook balances - Ensure sufficient balance before placing orders
- Use liquidity orders for market making - Better fees than market orders
- Handle swap failures - Monitor
SwapStatusfor errors - Cancel stale orders - Remove unfilled orders to free up balance
- Use appropriate precision - Respect
base_precisionandquote_precision