[Orderbook/Proto] rework protocol v1#26
Conversation
… cancel by instrument; send amounts as fixed-point; add batch place/cancel and streaming market-data RPCs
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 699f812. Configure here.
| return Some((Err(Status::not_found("No trades yet")), idx)); | ||
| } | ||
| idx = (idx + 1) % resp.len(); | ||
| Some((Ok(resp[idx].clone()), idx)) |
There was a problem hiding this comment.
Stream trade history skips first trade each cycle
High Severity
In stream_trade_history, the trade history index is incremented before accessing the response vector. This causes the newest trade (resp[0]) to be skipped on the first emission and subsequently delivered out of order in the stream.
Reviewed by Cursor Bugbot for commit 699f812. Configure here.
| results.push(result); | ||
| } | ||
| Ok(Response::new(OrderBatchResponse { orders: responses })) | ||
| Ok(Response::new(OrderBatchResponse { results })) |
There was a problem hiding this comment.
AllOrNone batch doesn't rollback placed orders
High Severity
In place_orders, BatchMode::AllOrNone processes orders sequentially. If an order fails, previously successful orders are not rolled back, leaving the matching engine in a partially updated state and violating the "all or none" atomicity guarantee.
Reviewed by Cursor Bugbot for commit 699f812. Configure here.
| defp to_proto_response(response) do | ||
| %Orderbook.OrderResponse{ | ||
| id: response.id, | ||
| price: to_string(response.price), |
There was a problem hiding this comment.
Gateway batch response uses outdated proto field
High Severity
The place_orders handler constructs Orderbook.OrderBatchResponse with an orders field containing OrderResponse items. The updated proto definition now uses a results field with OrderBatchItemResult items. This creates an incompatible wire format and will break once the Elixir proto module is regenerated.
Reviewed by Cursor Bugbot for commit 699f812. Configure here.
| units: value.mantissa() as i64, | ||
| scale: value.scale() as i32, | ||
| } | ||
| } |
There was a problem hiding this comment.
Decimal mantissa silently truncated from i128 to i64
Medium Severity
The decimal_to_proto function converts the i128 mantissa to i64 using a direct as cast. This silently truncates values exceeding the i64 range, which can corrupt financial data like prices and quantities in the wire representation.
Reviewed by Cursor Bugbot for commit 699f812. Configure here.


Note
High Risk
High risk because it changes the gRPC protocol (field types, enum values, and request shapes) and rewires core orderbook RPC behavior around instrument-scoped lanes, which can break compatibility across gateway/CLI/OB if any client/server stubs aren’t regenerated and updated consistently.
Overview
Reworks the orderbook gRPC protocol to be instrument-scoped and fixed-point: price/quantity fields move from strings to
DecimalValue, enums gain explicit *_UNSPECIFIED values (shifting numeric values), and requests forcancel_order,get_order_book,get_order_status, andget_trade_historynow requireinstrument_id.Adds new RPCs and batching semantics: introduces
cancel_ordersbatch RPC, streaming RPCs for order book and trades, and updatesplace_ordersto return per-item results (OrderBatchItemResult) with structuredErrorDetailandBatchMode(PARTIAL_OKvsALL_OR_NONE).Updates implementations and clients: the Rust orderbook service routes work by instrument/lane (no cross-lane scans), adds cancel idempotency caching, and implements polling-based streaming responses; the Elixir gateway and Python CLI switch to the new decimal/instrument-aware request/response shapes (including updated parsing/formatting and a CLI
--instrumentflag), with the gateway explicitly marking streaming RPCs as unimplemented for now.Reviewed by Cursor Bugbot for commit 699f812. Bugbot is set up for automated code reviews on this repo. Configure here.