Skip to main content
Agent instructions

Types: Tick = Int32 (log-price), Side = #buy | #sell, OrderId = Nat, TriggerId = Nat, PollVersions = { platform: Nat, orderbook: Nat, candle: Nat, user: Nat }

Candid conventions: #buy = { buy: null } in JS, ?value = [value] (present) or [] (absent), Nat = BigInt, all ok/err variants use lowercase.

Trading

Orders

create_orders

create_orders(
cancel_ids : [OrderId], // cancel these first (freeing slots + balance)
book_orders : [BookOrderSpec], // limit orders — resting or IOC
pool_swaps : [PoolSwapSpec], // AMM swaps — execute first
)

Cancels execute first, then pool swaps, then book orders.

See Trading Overview for the input token convention (input_amount denomination by side).

// Book-only limit orders
create_orders([], [
{ side: #buy, limit_tick: -230_000, input_amount: 500_000_000, immediate_or_cancel: false },
{ side: #sell, limit_tick: -229_800, input_amount: 10_000_000, immediate_or_cancel: false },
], [])

// Routed order (book + pools) via quote
quote = quote_order(#buy, 1_000_000, ?limit_tick, ?50)
create_orders(
[],
quote.book_order != null ? [quote.book_order] : [],
quote.pool_swaps
)

// Atomic replace: cancel old orders, create new ones in single call
create_orders([old_id_1, old_id_2], [new_spec_1, new_spec_2], [])

Pool swaps and book orders fill independently — swap_results[i] corresponds 1:1 to pool_swaps[i], order_results[i] to book_orders[i].

// Response
{
versions: PollVersions,
cancel_results: [{ order_id, result: #ok(()) | #err(...) }],
cancel_summary: BatchSummary, // { succeeded, failed }
order_results: [{ index, result: #ok({ order_id }) | #err(...) }],
swap_results: [{
index,
result: #ok({
input_amount, // gross input consumed (includes fee), may be < spec.input_amount on partial fill
output_amount, // net output received
fee, // pool fee extracted from input (input_amount = net_input + fee)
}) | #err(...)
}],
order_summary: BatchSummary,
available_base: Nat,
available_quote: Nat,
}

Zero-fill (input_amount = 0, output_amount = 0, fee = 0) means no liquidity at that tier — not failure.

quote_order

quote_order(side, amount, ?limit_tick, ?slippage_bps) — both limit_tick (opt Tick) and slippage_bps (opt Nat32) are optional. limit_tick is the worst acceptable price tick (null = no limit), slippage_bps is max slippage in basis points (null = no constraint). Returns variant { ok: QuoteResult, err: ApiError }.

QuoteResult {
input_amount: Nat,
output_amount: Nat,
pool_swaps: [PoolSwapSpec], // pass to create_orders / pass_through_trade
book_order: ?BookOrderSpec, // pass to create_orders / pass_through_trade
venue_breakdown: [VenueBreakdown],
total_fees: Nat,
effective_tick: Tick,
reference_tick: Tick,
}

Agents with proprietary routing can construct BookOrderSpec and PoolSwapSpec directly from get_routing_state() instead of using quote_order.

Triggers

create_triggers(cancel_ids, specs) (up to 20) — conditional orders that activate when book trade tick crosses a threshold. Pass cancel_ids to atomically cancel existing triggers first.

create_triggers([], [{
side: #sell,
trigger_tick: -231_000,
limit_tick: -231_500,
input_amount: 10_000_000,
reference_tick: -230_000,
immediate_or_cancel: true,
}])
// Response
{
versions: PollVersions,
cancel_results: [{ trigger_id, result: #ok(()) | #err(...) }],
cancel_summary: BatchSummary,
results: [{ index, result: #ok({ trigger_id }) | #err(...) }],
summary: BatchSummary,
available_base: Nat,
available_quote: Nat,
}
Activation Source

Triggers are only evaluated during book-based trades (limit order matches). Pool swaps do not activate triggers.

update_order

update_order(order_id, new_tick, new_input_amount)

Returns variant { ok: variant { ... }, err: ApiError }. The ok variant is #replaced when tick changes (new entity) or #modified when only amount decreases at same tick (same entity, retains queue priority).

// Response: ok variant (one of)
#replaced({ versions, order_id, available_base, available_quote })
#modified({ versions, refunded, available_base, available_quote })

Cancellation

cancel_orders(order_ids), cancel_triggers(trigger_ids) — batch cancel by ID.

// Response (both follow same shape)
{
versions: PollVersions,
results: [{ order_id|trigger_id, result: #ok(()) | #err(...) }],
summary: BatchSummary,
available_base: Nat,
available_quote: Nat,
}

cancel_all_orders(), cancel_all_triggers() — parameterless kill switches. No per-item results.

// Response (both follow same shape)
{
versions: PollVersions,
cancelled: Nat32,
available_base: Nat,
available_quote: Nat,
}

Pass-Through (wallet-to-wallet)

Bypasses trading balance entirely. Tokens move from wallet → routing engine → wallet. Needs ICRC-2 approval instead of deposit.

// Routed (book + pools) via quote
icrc2_approve(token_ledger, spot_canister, amount)
quote = quote_order(#buy, 1_000_000, ?limit_tick, ?50)
pass_through_trade({
book_order: quote.book_order,
pool_swaps: quote.pool_swaps,
recipient: ?my_principal, // optional, defaults to caller
})

// Pool-swaps-only (no book order)
pass_through_trade({
book_order: null,
pool_swaps: quote.pool_swaps,
recipient: null,
})
// Response
{
versions: PollVersions,
order_results: [{ index, result: #ok({ order_id }) | #err(...) }],
swap_results: [{ index, result: #ok({ input_amount, output_amount, fee }) | #err(...) }],
output: TransferLeg,
refund: TransferLeg,
}

TransferLeg {
amount: Nat, // tokens transferred (or credited to trading balance on failure)
block_index: ?Nat, // ICRC transfer block (null if transfer failed)
error: ?Text, // error message if transfer failed
}

On outbound transfer failure, funds credit to your trading balance as fallback (not lost, but not in your wallet). Check trading balance if output.block_index is null.

Type Reference

BookOrderSpec {
side: #buy | #sell
input_amount: Nat // native decimals
limit_tick: Tick
immediate_or_cancel: Bool // true = refund unfilled
}

PoolSwapSpec {
side: #buy | #sell
input_amount: Nat // native decimals
limit_tick: Tick // slippage protection
fee_pips: Nat32 // pool tier: multiples of 100 (100–10000)
}

TriggerSpec {
side: #buy | #sell
trigger_tick: Tick // activation price
limit_tick: Tick // slippage tolerance for resulting order
input_amount: Nat // native decimals
reference_tick: Tick // caller's current price → direction (#above if trigger > reference, #below otherwise)
immediate_or_cancel: Bool
}

VenueBreakdown {
venue_id: #book | #pool(fee_pips)
input_amount: Nat
output_amount: Nat
fee_amount: Nat
}

BatchSummary { succeeded: Nat32, failed: Nat32 }

See also: Liquidity Management for LP position operations.