Skip to main content

cow_sdk_trading/client/
mod.rs

1//! The stateful, high-level `Trading` client, its construction builder, and the
2//! fluent swap lifecycle.
3
4use std::{fmt, sync::Arc};
5
6use cow_sdk_core::{AddressPerChain, AppCode, CowEnv, SupportedChainId};
7
8use crate::{OrderbookClient, PartialTraderParams};
9
10/// Generates the optional setters shared by the fluent order-placement builders
11/// ([`SwapBuilder`](swap::SwapBuilder) and [`LimitBuilder`](limit::LimitBuilder)),
12/// mirroring `impl_common_trade_setters!` on the parameter structs. The required
13/// token and amount setters and the async terminals stay builder-specific; only
14/// the marker-preserving optional setters are shared, so a future common setter
15/// lands on both builders at once.
16macro_rules! impl_common_order_builder_setters {
17    ($builder:ident <$life:lifetime, $($marker:ident),+>) => {
18        impl<$life, $($marker),+> $builder<$life, $($marker),+> {
19            /// Sets an explicit owner. When omitted, the signer address resolves
20            /// the owner at the terminal.
21            #[must_use]
22            pub const fn owner(mut self, owner: Address) -> Self {
23                self.owner = Some(owner);
24                self
25            }
26
27            /// Sets an explicit receiver address.
28            #[must_use]
29            pub const fn receiver(mut self, receiver: Address) -> Self {
30                self.receiver = Some(receiver);
31                self
32            }
33
34            /// Sets a relative validity window in seconds.
35            #[must_use]
36            pub const fn valid_for(mut self, valid_for: u32) -> Self {
37                self.valid_for = Some(valid_for);
38                self
39            }
40
41            /// Sets an absolute expiry timestamp.
42            #[must_use]
43            pub const fn valid_to(mut self, valid_to: u32) -> Self {
44                self.valid_to = Some(valid_to);
45                self
46            }
47
48            /// Allows partial fills.
49            #[must_use]
50            pub const fn partially_fillable(mut self, partially_fillable: bool) -> Self {
51                self.partially_fillable = partially_fillable;
52                self
53            }
54        }
55    };
56}
57
58mod builder;
59mod helpers;
60mod limit;
61mod methods;
62mod swap;
63
64pub use self::builder::TradingBuilder;
65pub use self::limit::LimitBuilder;
66pub use self::swap::{QuotedSwap, Set, SwapBuilder, Unset};
67/// Typestate marker for a builder that has not yet been given a chain id.
68#[derive(Debug, Clone, Copy)]
69pub struct ChainIdUnset(());
70
71/// Typestate marker for a builder that has been given a chain id.
72#[derive(Debug, Clone, Copy)]
73pub struct ChainIdSet(());
74
75/// Typestate marker for a builder that has not yet been given an `appCode`.
76#[derive(Debug, Clone, Copy)]
77pub struct AppCodeUnset(());
78
79/// Typestate marker for a builder that has been given an `appCode`.
80#[derive(Debug, Clone, Copy)]
81pub struct AppCodeSet(());
82
83/// High-level trading facade that stores trader defaults plus an optional
84/// injected orderbook client.
85#[derive(Clone)]
86pub struct Trading {
87    trader_defaults: PartialTraderParams,
88    orderbook: Option<Arc<dyn OrderbookClient>>,
89}
90
91impl fmt::Debug for Trading {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        f.debug_struct("Trading")
94            .field("trader_defaults", &self.trader_defaults)
95            .field("orderbook", &self.orderbook.is_some())
96            .finish()
97    }
98}
99
100impl Trading {
101    /// Returns a new [`TradingBuilder`] in the `<ChainIdUnset, AppCodeUnset>` typestate.
102    #[must_use]
103    pub fn builder() -> TradingBuilder<ChainIdUnset, AppCodeUnset> {
104        TradingBuilder::new()
105    }
106
107    /// Returns the default chain id supplied at construction, if any.
108    #[must_use]
109    pub const fn chain_id(&self) -> Option<SupportedChainId> {
110        self.trader_defaults.chain_id
111    }
112
113    /// Returns the default app code supplied at construction, if any.
114    #[must_use]
115    pub const fn app_code(&self) -> Option<&AppCode> {
116        self.trader_defaults.app_code.as_ref()
117    }
118
119    /// Returns the default environment supplied at construction, if any.
120    #[must_use]
121    pub const fn env(&self) -> Option<CowEnv> {
122        self.trader_defaults.env
123    }
124
125    /// Returns the default settlement-contract overrides supplied at construction, if any.
126    #[must_use]
127    pub const fn settlement_contract_override(&self) -> Option<&AddressPerChain> {
128        self.trader_defaults.settlement_contract_override.as_ref()
129    }
130
131    /// Returns the default `EthFlow`-contract overrides supplied at construction, if any.
132    #[must_use]
133    pub const fn eth_flow_contract_override(&self) -> Option<&AddressPerChain> {
134        self.trader_defaults.eth_flow_contract_override.as_ref()
135    }
136}
137
138#[cfg(test)]
139mod tests {
140    use super::*;
141
142    #[test]
143    fn typestate_markers_are_sealed_against_external_construction() {
144        // These constructors are visible only inside this module because the
145        // tuple field is private; external callers cannot write `Marker(())`.
146        let _ = ChainIdUnset(());
147        let _ = ChainIdSet(());
148        let _ = AppCodeUnset(());
149        let _ = AppCodeSet(());
150    }
151}