place_order, cancel_order, get_order, open_orders, and order_trades implemented on SigningClient (Plan 3a, Task 1, branch autotrade-foundation, crates/polymarket-clob/src/lib.rs). Includes a critical serde landmine in the vendored SDK and the fix.

KEY FINDING — SignedOrder Is Not Deserializable

The original task spec called for round-tripping BuiltOrder.signed_payload through serde:

// DOES NOT COMPILE — SignedOrder has no Deserialize
serde_json::from_value::<SignedOrder>(built.signed_payload.0.clone())

SignedOrder (vendored rs-clob-client-v2) derives only #[derive(Debug, Builder, PartialEq)]no Serialize, no Deserialize.

Fix: Hold the Typed Value Directly

BuiltOrder was redesigned to hold the typed value instead of a serialized Value:

BeforeAfter
signed_payload: SignedPayload(serde_json::Value)signed_order: SignedOrder
SignedPayload wrapper struct existedSignedPayload struct dropped entirely

BuiltOrder now carries the typed SignedOrder through to place_order, which passes it directly to the vendored client without any serde round-trip.

Do not attempt to serialize/deserialize SignedOrder

The vendored type has no serde derives. Any code path requiring a Value representation must avoid SignedOrder as an intermediate — build a separate serializable struct if needed.

Vendored API Shapes (Verified)

OrdersRequest

  • Derives Default; all fields are Option<_>
  • Use OrdersRequest::default() to request all open orders (no filter)

TradesRequest

  • Derives Default; all fields are Option<_>
  • Use TradesRequest::default() to request all trades (no filter)

Pagination

Page<T>.data: Vec<T>

The paginated data lives in the .data field — not .items, .results, or .orders.

OpenOrderResponse Fields

FieldTypeNotes
.idStringCLOB order id
.statusOrderStatusTypeImplements Display
.size_matchedDecimalFilled portion

TradeResponse Fields

FieldTypeNotes
.idStringTrade id
.taker_order_idStringCLOB order id (not EIP-712 hash)
.statusTradeStatusTypeImplements Display
.sizeDecimalTrade size
.priceDecimalTrade price
.transaction_hashB256On-chain tx hash

TradeResponse has NO order_hash

TradeResponse carries no EIP-712 hash. TradeView.order_hash is always None — the field is populated client-side only by filtering taker_order_id == clob_order_id. Do not attempt to join on EIP-712 hashes when looking up trades for an order.

PostOrderResponse Fields

FieldTypeNotes
.order_idStringserde alias "orderID" (camelCase in JSON)
.statusOrderStatusTypeImplements Display
.making_amountDecimal
.taking_amountDecimal
.transaction_hashesVec<B256>On-chain tx hashes
.trade_idsVec<String>

orderID alias

The JSON key is "orderID" (camelCase). The Rust field is .order_id (snake_case). serde(alias = "orderID") handles the mapping — access the field via .order_id in code, not .orderID.

cancel_order Return Type

cancel_order(&str) -> Result<CancelOrdersResponse>

The response is discarded in the current implementation — cancel_order returns (). The CancelOrdersResponse carries confirmation data but is not needed for the autotrade flow.

Gate

cargo fmt + cargo build + 265 tests all pass, EXIT:0.