About ten minutes on Polyester devnet: public reads, a live stream, then a place-and-cancel with an API key.
Prerequisites
Install the SDK. Create an API key in the Polyester
app (API in the sidebar). Copy the key id and private key when shown, the private key is
only displayed once. Open the key's Permissions, enable Spot trading, choose the allowed
markets, and set a maximum order size that covers this test. Copy your Account ID from Profile.
The API-key SDK can use an assigned policy but cannot create or assign one.
Create a client
use polyester::{Client, Config};
let client = Client::new(Config {
api_key_id: Some("ak_...".into()),
api_private_key: Some("...".into()), // 64-char hex from key creation
default_account_id: Some("...".into()), // Profile โ Account ID
..Default::default()
})?;Wait for catalogs
Decimal order inputs need spot config scales. Wait before first write:
client.wait_for_catalogs().await?;See Catalog & precision.
Read public market data
use polyester::services::ListMarketOverviewOptions;
let overview = client.market_overview.list(ListMarketOverviewOptions {
limit: Some(5),
..Default::default()
}).await?;
for market in overview.markets {
println!("{} {:?}", market.symbol, market.last_price.as_ref().map(|p| p.as_ticks()));
}Stream public trades
let mut sub = client.market_data.subscribe_trades("BTC-USDT").await?;
if let Some(trade) = sub.recv_result().await? {
println!("{trade:?}");
}Subscription queues are bounded. If your consumer falls behind, the SDK raises a realtime overflow error and faults the subscription, it does not silently drop updates. See Streaming.
Place and cancel a limit order
Your API key policy must allow Spot trading for BTC-USDT, and its maximum order size must cover
the order below. Spot orders spend trading balance. Manage the policy from the key's Permissions page in the Polyester app.
use std::time::{SystemTime, UNIX_EPOCH};
use polyester::models::{CreateOrderParams, CreateOrderType, CreateSide, CreateTimeInForce};
use polyester::{Price, Quantity};
let quantity_scale = client
.catalogs
.base_quantity_scale_for_symbol("BTC-USDT")
.ok_or_else(|| polyester::Error::validation("BTC-USDT quantity scale is unavailable"))?;
let client_order_id = format!(
"quickstart-{}",
SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("system clock before Unix epoch")
.as_nanos()
);
let result = client.orders.create(CreateOrderParams {
symbol: "BTC-USDT".into(),
side: CreateSide::Buy,
order_type: CreateOrderType::Limit,
quantity: Some(Quantity::from_decimal_str(
"0.001",
quantity_scale,
Some("BTC-USDT".into()),
None,
)?),
max_quote_debit_scaled: None,
price: Some(Price::from_decimal_str("50000", Some("BTC-USDT".into()))?),
time_in_force: Some(CreateTimeInForce::Gtc),
client_order_id: Some(client_order_id.clone()),
subaccount_id: None,
post_only: Some(true),
market_client_ref_price: None,
fee_asset: None,
self_trade_prevention: None,
market_max_slippage: None,
attached_risk: None,
}).await?;
println!("{} {}", result.status, result.order_id); // status == "accepted" (admission ack)
client
.orders
.cancel_by_client_order_id(&client_order_id, Some("BTC-USDT"), None)
.await?;Next: Authentication and Trading.