API Reference
The Aspens Market Stack exposes three gRPC services. Source of truth is the protos repository:
| Service | Proto file | Used by |
|---|---|---|
ArborterService | arborter.proto | Trading: orders, cancels, streams |
ConfigService | arborter_config.proto | Read-only stack configuration |
AuthService | arborter_auth.proto | Admin login, JWT issuance |
This page documents the trading service. The full proto bundle is at github.com/aspensprotocol/protos.
ArborterService
service ArborterService {
rpc SendOrder (SendOrderRequest) returns (SendOrderResponse);
rpc CancelOrder (CancelOrderRequest) returns (CancelOrderResponse);
rpc Trades (TradeRequest) returns (stream Trade);
rpc Orderbook (OrderbookRequest) returns (stream OrderbookEntry);
}SendOrder
message SendOrderRequest {
Order order = 1;
bytes signature_hash = 2; // EIP-191 (EVM) / Ed25519 (Solana) over the encoded Order
OrderAuthorization authorization = 3; // required — see below
}The arborter authenticates order entry by the signature_hash envelope
and rejects requests without an authorization. (The legacy on-chain
lock path — and the old GaslessAuthorization message — were removed.)
message OrderAuthorization {
string order_id = 1; // 0x-prefixed 32-byte hex; SDK-derived canonical id
string amount_in = 2; // committed input amount, base units, decimal-string u128
}order_id must match aspens::orders::derive_order_id(...) — the same
SHA-256 derivation the arborter recomputes server-side. Drift here is
silently fatal (the arborter uses this id throughout matching and
settlement).
message Order {
Side side = 1; // SIDE_BID | SIDE_ASK
string quantity = 2;
optional string price = 3; // present = LIMIT, absent = MARKET
string market_id = 4; // base_chain_id::token_addr::quote_chain_id::token_addr
string base_account_address = 5;
string quote_account_address = 6;
ExecutionType execution_type = 7; // _UNSPECIFIED (=DIRECT) | _DISCRETIONARY
repeated uint64 matching_order_ids = 8; // discretionary only
}
enum Side { SIDE_UNSPECIFIED = 0; SIDE_BID = 1; SIDE_ASK = 2; }
enum ExecutionType { EXECUTION_TYPE_UNSPECIFIED = 0; EXECUTION_TYPE_DISCRETIONARY = 1; }message SendOrderResponse {
bool order_in_book = 1;
optional Order order = 2; // unfilled remainder, if any
repeated Trade trades = 3; // matches produced by this submit
repeated TransactionHash transaction_hashes = 4;
repeated OrderbookEntry current_orderbook = 5;
uint64 order_id = 6; // engine-internal id
}CancelOrder
message CancelOrderRequest {
OrderToCancel order = 1;
bytes signature_hash = 2;
}
message OrderToCancel {
string market_id = 1;
Side side = 2;
string token_address = 3;
uint64 order_id = 4; // engine-internal id from SendOrderResponse.order_id
}Trades / Orderbook (streams)
message TradeRequest {
bool continue_stream = 1;
string market_id = 2;
optional bool historical_closed_trades = 3;
optional string filter_by_trader = 4;
}
message OrderbookRequest {
bool continue_stream = 1;
string market_id = 2;
optional bool historical_open_orders = 3;
optional string filter_by_trader = 4;
}Stream entries:
message OrderbookEntry {
uint64 timestamp = 1;
uint64 order_id = 2;
string price = 3;
string quantity = 4;
Side side = 5;
string maker_base_address = 6;
string maker_quote_address = 7;
string market_id = 8;
OrderState state = 9; // PENDING | CONFIRMED | MATCHED | CANCELED | SETTLED
}
message Trade {
uint64 timestamp = 1;
string price = 2; // settled, net of fees
string qty = 3;
string maker_id = 4;
string taker_id = 5;
string maker_base_address = 6;
string maker_quote_address = 7;
string taker_base_address = 8;
string taker_quote_address = 9;
TradeRole buyer_is = 10; // MAKER | TAKER
TradeRole seller_is = 11;
uint64 order_hit = 12;
}Order request flow
- Client signs the encoded
Order(EIP-191 on EVM, Ed25519 on Solana) and sendsSendOrderRequestwith theOrderAuthorization{ order_id, amount_in }. No on-chain transaction. - Arborter verifies the envelope signature with the curve derived from
the chain architecture and verifies
authorization.order_idagainst its ownderive_order_id. - The engine reserves
amount_inagainst the user's off-chain ledger balance; if matchable,Trades are produced and balances move in the ledger immediately (no on-chain tx, no block wait). - Any unmatched remainder rests in the orderbook against that ledger reservation.
SendOrderResponsereturns immediately;TradesandOrderbooksubscribers are notified in parallel.- Separately, a background settler folds accumulated net deltas
on-chain in batches (
MidribV3.settleBatchon EVM,settle_batchon Solana).