Spot Canister API Reference
Each Spot canister serves exactly one trading pair (base/quote). It combines a central limit order book (CLOB) with Uniswap V3-style concentrated liquidity AMM pools, unified under a single-canister architecture on the Internet Computer.
Queries (Public)
No authentication required. Anonymous callers allowed.
get_reference_tick
query get_reference_tick() → opt Tick
Current market reference tick. Derived as: book mid > viable pool median > last trade tick > null.
get_routing_state
query get_routing_state() → RoutingState
Atomic snapshot of the complete routing state for external routers. Single call provides token metadata, reference tick, pool state, and order book — everything needed to simulate order execution off-chain.
get_control
query get_control() → FrozenControl
Canister control plane state: system state, token config, fee parameters, entity counts, admin principals.
get_pool
query get_pool(fee_pips: Nat32) → opt PoolState
Detailed state for a specific pool tier. Returns null if no pool exists for the given fee tier.
| Param | Type | |
|---|---|---|
fee_pips | Nat32 | Pool fee tier: 100–10000 in steps of 100 |
get_pools_overview
query get_pools_overview() → vec PoolOverview
All active pools with fee tier, position count, TVL, volume, and APR.
get_market_depth
query get_market_depth(levels: Nat32, tick_bucket_size: Nat32) → MarketDepthResponse
Separated order book and pool liquidity depth.
| Param | Type | |
|---|---|---|
levels | Nat32 | Price levels per side |
tick_bucket_size | Nat32 | Aggregation width in ticks (0 = finest) |
get_balance_sheet
query get_balance_sheet() → BalanceSheet
Complete balance sheet with invariant checks: INV-1a (balance sheet), INV-2 (user fund conservation), INV-3 (pool consistency).
get_lock_schedule
query get_lock_schedule() → LiquidityLockSummary
Liquidity lock schedule: locked vs unlocked TVL and upcoming unlock times.
get_indexer_data
query get_indexer_data() → IndexerData
Aggregate token stats and per-pool breakdowns for the indexer canister.
get_transactions
query get_transactions(limit: opt Nat32, cursor: opt Nat64) → { data: vec SpotTransactionResponse, has_more: Bool, next_cursor: opt Nat64 }
Recent trades with cursor-based pagination (newest first). limit defaults to 20 (max 100).
get_chart
query get_chart(interval: ChartInterval, before_ts: opt Nat64, limit: Nat32) → { data: vec SpotCandle, has_more: Bool, next_cursor: opt Nat64 }
Historical OHLCV candles with pagination.
get_live_candle
query get_live_candle(interval: ChartInterval) → CandleData
Current unclosed candle. CandleData = (timestamp, open_e12, high_e12, low_e12, close_e12, volume_native).
get_pool_snapshots
query get_pool_snapshots(fee_pips: Nat32, before_timestamp: opt Nat64, limit: Nat32, interval_hours: Nat32) → PoolSnapshotsResponse
Historical fee snapshots for a specific pool at any hourly interval.
get_market_snapshots
query get_market_snapshots(before_timestamp: opt Nat64, limit: Nat32, interval_hours: Nat32) → MarketSnapshotsResponse
Historical market-level snapshots for TVL charts. Aggregates all pools and the order book.
get_position
query get_position(id: PositionId) → opt PositionView
Position details by ID. Returns null if the position does not exist.
quote_order
query quote_order(side: Side, input_amount: Nat, limit_tick: opt Tick, slippage_bps: opt Nat32) → QuoteOrderResult
Simulate an order for UI preview. Does not modify state. Returns pool_swaps and book_order specs passable directly to create_orders or pass_through_trade.
| Param | Type | |
|---|---|---|
side | Side | #buy or #sell |
input_amount | Nat | Input in native decimals |
limit_tick | opt Tick | Worst acceptable price tick (null = no limit) |
slippage_bps | opt Nat32 | Max slippage in basis points (null = no constraint) |
Returns
ok: {
input_amount : Nat,
output_amount : Nat,
pool_swaps : vec PoolSwapSpec, // pass to create_orders
book_order : opt BookOrderSpec, // pass to create_orders
venue_breakdown : vec VenueBreakdown, // per-venue input/output/fee
total_fees : Nat,
effective_tick : Tick,
reference_tick : Tick,
}
Queries (Authenticated)
Use the caller's principal for user-specific data. Anonymous callers return null/empty.
get_user
query get_user() → UserData
User account data: orders, positions, triggers, trading/locked balances, fees, and net flow tracking. UserData is opt { ... } — returns null if no account exists. Auth: caller
get_versions
query get_versions() → PollVersions
Version counters for cache invalidation. Primary polling endpoint (~500ms interval). Compare fields to determine which data endpoints need re-fetching. Auth: caller
get_hydration
query get_hydration(interval: ChartInterval, chart_limit: Nat32, levels: Nat32, tick_bucket_size: Nat32) → HydrateResponse
All data for initial page load in a single atomic call. Includes platform data, user data, chart history, and recent trades. Works for both logged-in and anonymous callers. Auth: caller (optional)
get_platform
query get_platform(interval: ChartInterval, levels: Nat32, tick_bucket_size: Nat32) → PlatformData
Platform data fetched conditionally when platform_version changes. Returns price, liquidity, live candle, market depth, and statistics.
get_user_activity
query get_user_activity(cursor: opt ChainCursor, limit: opt Nat32) → GetUserActivityResult
Unified activity history (orders, triggers, LP events, transfers). limit defaults to 20 (max 100). Auth: caller
Deposits & Withdrawals
deposit
deposit(token: TokenSide, amount: Nat) → DepositResult
Deposit tokens to trading balance via ICRC-2 transfer_from. Requires a prior icrc2_approve on the token ledger. Auth: caller
| Param | Type | |
|---|---|---|
token | TokenSide | #base or #quote |
amount | Nat | Amount in native decimals |
withdraw
withdraw(token: TokenSide, amount: Nat) → WithdrawResult
Withdraw tokens from trading balance to wallet. Deducts before the async transfer; credits back on failure. Auth: caller
| Param | Type | |
|---|---|---|
token | TokenSide | #base or #quote |
amount | Nat | Amount in native decimals |
Orders
create_orders
create_orders(
cancel_ids : vec OrderId,
book_orders : vec BookOrderSpec,
pool_swaps : vec PoolSwapSpec,
) → CreateOrdersResult
Unified order creation: optional cancels + book orders + pool swaps in a single call. Cancels execute first (freeing slots and balance), then pool swaps, then book orders. Uses pre-deposited trading balance. Auth: caller
| Param | Type | |
|---|---|---|
cancel_ids | vec OrderId | Orders to cancel first (frees balance + slots) |
book_orders | vec BookOrderSpec | Limit orders to place on the book |
pool_swaps | vec PoolSwapSpec | AMM swaps to execute against pool tiers |
Returns
ok: {
cancel_results : vec CancelOrderResultItem, // per-cancel { order_id, result }
cancel_summary : BatchSummary, // { succeeded, failed }
swap_results : vec SwapResultItem, // per-swap { index, result: { input_amount, output_amount, fee } }
order_results : vec OrderResultItem, // per-order { index, result: { order_id } }
order_summary : BatchSummary,
available_base : Nat, // updated trading balance
available_quote : Nat,
versions : PollVersions,
}
cancel_orders
cancel_orders(order_ids: vec OrderId) → CancelOrdersResult
Batch cancel by ID. Per-order cancellation — individual failures do not block others. Auth: caller
update_order
update_order(order_id: OrderId, new_tick: Tick, new_input_amount: Nat) → UpdateOrderResult
Update an order's tick and/or input amount. Returns #replaced (new order) or #modified (in-place decrease at same tick, retains queue priority). Delta vs remaining_input is debited/refunded from trading balance. Auth: caller
| Param | Type | |
|---|---|---|
order_id | OrderId | Order to update |
new_tick | Tick | New price tick |
new_input_amount | Nat | New input amount |
cancel_all_orders
cancel_all_orders() → CancelAllOrdersResult
Cancel all orders for the caller. Works in degraded mode. Auth: caller
Triggers
create_triggers
create_triggers(
cancel_ids : vec TriggerId,
triggers : vec TriggerSpec,
) → CreateTriggersResult
Unified trigger creation: optional cancels + batch create. Cancels execute first (freeing slots and balance), then creates. Auth: caller
| Param | Type | |
|---|---|---|
cancel_ids | vec TriggerId | Triggers to cancel first |
triggers | vec TriggerSpec | Triggers to create |
cancel_triggers
cancel_triggers(trigger_ids: vec TriggerId) → CancelTriggersResult
Bulk cancel by ID. Per-trigger cancellation — individual failures do not block others. Auth: caller
cancel_all_triggers
cancel_all_triggers() → CancelAllTriggersResult
Cancel all triggers for the caller. Works in degraded mode. Auth: caller
Liquidity
add_liquidity
add_liquidity(
fee_pips : Nat32,
t_lo : Tick,
t_hi : Tick,
amt_base : Nat,
amt_quote : Nat,
initial_tick : opt Tick,
lock_until_ms : opt Nat64,
amt_base_min : Nat,
amt_quote_min : Nat,
) → LiquidityResult
Add liquidity to a new concentrated position. First LP in a pool must supply initial_tick to set the price. Excess tokens credited to trading balance. Auth: caller
| Param | Type | |
|---|---|---|
fee_pips | Nat32 | Pool tier: 100–10000 in steps of 100 |
t_lo / t_hi | Tick | Lower and upper tick bounds |
amt_base / amt_quote | Nat | Desired amounts in native decimals |
initial_tick | opt Tick | Required for first LP in pool (sets price) |
lock_until_ms | opt Nat64 | Optional lock expiry (ms since epoch) |
amt_base_min / amt_quote_min | Nat | Slippage protection minimums |
increase_liquidity
increase_liquidity(
id : PositionId,
amt_base_desired : Nat,
amt_quote_desired : Nat,
amt_base_min : Nat,
amt_quote_min : Nat,
) → IncreaseLiquidityResult
Increase liquidity in an existing position. Excess tokens credited to trading balance. Auth: caller (position owner)
decrease_liquidity
decrease_liquidity(
id : PositionId,
liquidity_delta : Nat,
amt_base_min : Nat,
amt_quote_min : Nat,
) → DecreaseLiquidityResult
Decrease liquidity from an existing position. Full withdrawal auto-collects fees and deletes the position. Partial stores tokens in tokensOwed. Blocked while locked. Auth: caller (position owner)
collect_fees
collect_fees(id: PositionId) → CollectFeesResult
Collect accumulated fees and withdrawn tokens from a position into trading balance. Auth: caller (position owner)
lock_position
lock_position(id: PositionId, lock_until_ms: Nat64) → LockPositionResult
Lock a position until lock_until_ms. One-way ratchet: can only extend, never shorten. Blocks decrease_liquidity and close_all_positions while locked. Auth: caller (position owner)
transfer_position
transfer_position(position_id: PositionId, recipient: Principal) → TransferPositionResult
Transfer ownership to another user. Locked positions are transferable. Accrued fees carry over. Auth: caller (position owner)
close_all_positions
close_all_positions() → CloseAllPositionsResult
Close all positions. Full withdrawal with fees auto-collected. Locked positions skipped. Works in degraded mode. Auth: caller
Pass-Through Trade
pass_through_trade
pass_through_trade(args: PassThroughTradeArgs) → PassThroughTradeResult
Execute a trade directly from wallet using ICRC-2 approval flow. Pulls input via transfer_from, settles output and refund to wallet (or optional recipient). Always executes as a market order. No pre-deposited trading balance required. Auth: caller
Returns
ok: {
swap_results : vec SwapResultItem,
order_results : vec OrderResultItem,
output : TransferLeg, // { amount, block_index, error }
refund : TransferLeg,
versions : PollVersions,
}
Miscellaneous
release_rate_limit
release_rate_limit(target: Principal) → ApiResult<Bool>
Pay to release a rate-limited principal. Costs 11x quote ledger fee via ICRC-2 approval. Auth: caller
Types
Primitives
| Type | Definition | |
|---|---|---|
Tick | Int32 | Log₁.₀₀₀₁ of price |
SqrtPriceX96 | Nat | √price in Q64.96 fixed-point |
Liquidity | Nat | Pool liquidity units |
PositionId | Nat64 | Monotonic position ID |
OrderId | Nat | Monotonic order ID |
TriggerId | Nat | Monotonic trigger ID |
Side | variant { buy; sell } | Trade direction |
TokenSide | variant { base; quote } | Token selector |
ChartInterval | variant { min1; min15; hour1; hour4; day1 } | Chart timeframe |
SystemState | variant { normal; degraded; halted } | Canister state |
BookOrderSpec
{
side : Side,
input_amount : Nat, // input in native decimals
limit_tick : Tick, // price tick
immediate_or_cancel : Bool, // true → unfilled portion cancelled after execution
}
PoolSwapSpec
{
side : Side,
input_amount : Nat, // input in native decimals
limit_tick : Tick, // slippage protection tick limit
fee_pips : Nat32, // pool tier: 100–10000 in steps of 100
}
TriggerSpec
{
side : Side,
trigger_tick : Tick, // activation price
input_amount : Nat, // input in native decimals
limit_tick : Tick, // slippage tolerance for resulting order
immediate_or_cancel : Bool,
reference_tick : Tick, // reference tick at creation
}
PassThroughTradeArgs
{
book_order : opt BookOrderSpec, // optional book order component
pool_swaps : vec PoolSwapSpec, // pool swap components
recipient : opt Principal, // output recipient (null → caller)
}
BatchSummary
{ succeeded : Nat32, failed : Nat32 }
PollVersions
{
platform : Nat, // trades, liquidity changes, price updates
orderbook : Nat, // limit order add/cancel (no match)
candle : Nat, // timer boundary (candle archived)
user : Nat, // user-specific changes (per caller)
}