diff --git a/CHANGELOG.md b/CHANGELOG.md index a2d6ea22c..861024b13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `market_rule`, `family_codes`, `calculate_option_price`, `calculate_implied_volatility`, and `next_valid_order_id` now retry a connection reset up to three times, like every other one-shot request. They previously surfaced `Error::ConnectionReset` to the caller on the first reset — a gateway reconnect mid-request failed the call outright. Nothing about these five made them unsafe to retry; they were the sites that had picked a helper without retry, `market_rule` and `family_codes` because the only helper bundling a server-version check was the non-retrying one (#741). - `head_timestamp`, `histogram_data`, `market_depth_exchanges`, and `historical_schedules(..).fetch()` retry a connection reset at most three times instead of unboundedly. The async `head_timestamp` recursed on a closed stream and the async `histogram_data`, `market_depth_exchanges`, and schedule fetch looped on one; a gateway that keeps resetting would hang the call rather than return. They also now agree with their blocking twins on what a closed stream means: `Error::UnexpectedEndOfStream` for `head_timestamp` and the schedule fetch, an empty list for `histogram_data` and `market_depth_exchanges` (#738). +- `Liquidity` now preserves unrecognized execution liquidity codes as a new `Unknown(i32)` variant instead of collapsing them to `Liquidity::None`. The documented codes 0–3 decode as before; any other value surfaces as `Unknown(code)` so callers can log, store, or reject it — previously an unknown code was indistinguishable from a genuine "no liquidity information", which is silent data loss (the official C# client has the same coercion). No official client or `Execution.proto` defines a code outside 0–3 today, so this is forward compatibility. `Liquidity` is deliberately exhaustive (no `#[non_exhaustive]`), so downstream exhaustive matches need a new arm — breaking (#760). + - `Client::wsh_event_data_by_contract` and `Client::wsh_event_data_by_filter` return builders instead of taking optional arguments positionally. The first took one required argument and four `Option`s, the second one and two; every call site in this repository passed `None` for all of them. Narrowing is now `.starting(date)` / `.ending(date)` / `.limit(n)` / `.auto_fill(spec)`, with `.fetch()` (single result) and `.subscribe()` (subscription) as the terminals. See `docs/migration-3.0.md` §37 (#752). ### Removed diff --git a/src/orders/mod.rs b/src/orders/mod.rs index bfb39df04..0051d0199 100644 --- a/src/orders/mod.rs +++ b/src/orders/mod.rs @@ -1468,6 +1468,7 @@ pub struct CommissionReport { /// Liquidity types for executions. #[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))] +#[repr(i32)] #[derive(Clone, Debug, Default, PartialEq)] pub enum Liquidity { /// No liquidity information. @@ -1479,15 +1480,18 @@ pub enum Liquidity { RemovedLiquidity = 2, /// Liquidity was routed out. LiquidityRoutedOut = 3, + /// Liquidity code not modeled by this version of the API. + Unknown(i32), } impl From for Liquidity { fn from(val: i32) -> Self { match val { + 0 => Liquidity::None, 1 => Liquidity::AddedLiquidity, 2 => Liquidity::RemovedLiquidity, 3 => Liquidity::LiquidityRoutedOut, - _ => Liquidity::None, + value => Liquidity::Unknown(value), } } } diff --git a/src/orders/tests.rs b/src/orders/tests.rs index 7f37a69bd..d31fe31d9 100644 --- a/src/orders/tests.rs +++ b/src/orders/tests.rs @@ -72,3 +72,10 @@ fn is_active_and_is_terminal_partition_eight_of_nine_variants() { } } } + +#[test] +fn liquidity_preserves_unknown_wire_code() { + assert_eq!(Liquidity::from(0), Liquidity::None); + assert_eq!(Liquidity::from(4), Liquidity::Unknown(4)); + assert_eq!(Liquidity::from(-1), Liquidity::Unknown(-1)); +}