About ten minutes on Polyester testnet: public reads, a live stream, then a place-and-cancel with an API key.
Create a client
use polyester::{Client, Config};
let client = Client::new(Config {
environment: Some(polyester::POLYESTER_TESTNET_ENVIRONMENT.clone()),
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. CreateOrderParams is built with CreateOrderParams::new, then optional fields are set on it.
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 mut params = CreateOrderParams::new("BTC-USDT", CreateSide::Buy, CreateOrderType::Limit);
params.quantity = Some(Quantity::from_decimal_str(
"0.001",
quantity_scale,
Some("BTC-USDT".into()),
None,
)?);
params.price = Some(Price::from_decimal_str("50000", Some("BTC-USDT".into()))?);
params.time_in_force = Some(CreateTimeInForce::Gtc);
params.client_order_id = Some(client_order_id.clone());
params.post_only = Some(true);
let result = client.orders.create(params).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.