pub trait ExecutionClientwhere
Self: Clone,{
type Config: Clone;
type AccountStream: Stream<Item = UnindexedAccountEvent> + Send;
const EXCHANGE: ExchangeId;
// Required methods
fn new(config: Self::Config) -> Self;
fn account_snapshot(
&self,
assets: &[AssetNameExchange],
instruments: &[InstrumentNameExchange],
) -> impl Future<Output = Result<UnindexedAccountSnapshot, UnindexedClientError>> + Send;
fn account_stream(
&self,
assets: &[AssetNameExchange],
instruments: &[InstrumentNameExchange],
) -> impl Future<Output = Result<Self::AccountStream, UnindexedClientError>> + Send;
fn cancel_order(
&self,
request: OrderRequestCancel<ExchangeId, &InstrumentNameExchange>,
) -> impl Future<Output = Option<UnindexedOrderResponseCancel>> + Send;
fn open_order(
&self,
request: OrderRequestOpen<ExchangeId, &InstrumentNameExchange>,
) -> impl Future<Output = Option<Order<ExchangeId, InstrumentNameExchange, UnindexedOrderState>>> + Send;
fn fetch_balances(
&self,
assets: &[AssetNameExchange],
) -> impl Future<Output = Result<Vec<AssetBalance<AssetNameExchange>>, UnindexedClientError>> + Send;
fn fetch_open_orders(
&self,
instruments: &[InstrumentNameExchange],
) -> impl Future<Output = Result<Vec<Order<ExchangeId, InstrumentNameExchange, Open>>, UnindexedClientError>> + Send;
fn fetch_trades(
&self,
time_since: DateTime<Utc>,
instruments: &[InstrumentNameExchange],
) -> impl Future<Output = Result<Vec<Trade<AssetNameExchange, InstrumentNameExchange>>, UnindexedClientError>> + Send;
// Provided methods
fn cancel_orders<'a>(
&self,
requests: impl IntoIterator<Item = OrderRequestCancel<ExchangeId, &'a InstrumentNameExchange>>,
) -> impl Stream<Item = Option<UnindexedOrderResponseCancel>> + Send { ... }
fn open_orders<'a>(
&self,
requests: impl IntoIterator<Item = OrderRequestOpen<ExchangeId, &'a InstrumentNameExchange>>,
) -> impl Stream<Item = Option<Order<ExchangeId, InstrumentNameExchange, UnindexedOrderState>>> + Send { ... }
}Required Associated Constants§
const EXCHANGE: ExchangeId
Required Associated Types§
type Config: Clone
type AccountStream: Stream<Item = UnindexedAccountEvent> + Send
Required Methods§
fn new(config: Self::Config) -> Self
fn account_snapshot( &self, assets: &[AssetNameExchange], instruments: &[InstrumentNameExchange], ) -> impl Future<Output = Result<UnindexedAccountSnapshot, UnindexedClientError>> + Send
Sourcefn account_stream(
&self,
assets: &[AssetNameExchange],
instruments: &[InstrumentNameExchange],
) -> impl Future<Output = Result<Self::AccountStream, UnindexedClientError>> + Send
fn account_stream( &self, assets: &[AssetNameExchange], instruments: &[InstrumentNameExchange], ) -> impl Future<Output = Result<Self::AccountStream, UnindexedClientError>> + Send
Returns a live stream of account events (fills, order updates, balance changes).
§Startup race window
There is an unavoidable gap between the WebSocket subscribe response and the
first event being delivered: fills arriving in this window (typically milliseconds,
no sub-millisecond guarantee) are silently dropped. account_snapshot reconciles
open-order state, but TRADE fills in this window are not recoverable from the stream
alone. Callers that require fill completeness at startup must call
ExecutionClient::fetch_trades with at least a 1-second lookback after this method returns.
§Backpressure
Implementations use unbounded internal channels. If the consumer cannot keep up, events queue in memory rather than being dropped — per library philosophy, OOM crashes are preferable to silent data loss. Consumers requiring backpressure should implement it at their boundary (e.g., bounded channel with overflow policy).
fn cancel_order( &self, request: OrderRequestCancel<ExchangeId, &InstrumentNameExchange>, ) -> impl Future<Output = Option<UnindexedOrderResponseCancel>> + Send
Sourcefn open_order(
&self,
request: OrderRequestOpen<ExchangeId, &InstrumentNameExchange>,
) -> impl Future<Output = Option<Order<ExchangeId, InstrumentNameExchange, UnindexedOrderState>>> + Send
fn open_order( &self, request: OrderRequestOpen<ExchangeId, &InstrumentNameExchange>, ) -> impl Future<Output = Option<Order<ExchangeId, InstrumentNameExchange, UnindexedOrderState>>> + Send
Place an order on the exchange.
§Return value
Returns OrderState directly rather than Result<Open, OrderError>:
OrderState::Active(Open)- order is resting on the order bookOrderState::Inactive(FullyFilled)- order was immediately filled (includesavg_pricewhen available)OrderState::Inactive(OpenFailed)- order placement failed (API error, connectivity, etc.)
This design allows immediate fills to carry metadata (e.g., avg_price) that
would be lost if we had to infer terminal state from Open::filled_quantity.
Sourcefn fetch_balances(
&self,
assets: &[AssetNameExchange],
) -> impl Future<Output = Result<Vec<AssetBalance<AssetNameExchange>>, UnindexedClientError>> + Send
fn fetch_balances( &self, assets: &[AssetNameExchange], ) -> impl Future<Output = Result<Vec<AssetBalance<AssetNameExchange>>, UnindexedClientError>> + Send
Fetch current balances for the specified assets.
An empty assets slice is the “return all” sentinel: implementations must return
balances for every asset held. When non-empty, only the listed assets are returned.
Sourcefn fetch_open_orders(
&self,
instruments: &[InstrumentNameExchange],
) -> impl Future<Output = Result<Vec<Order<ExchangeId, InstrumentNameExchange, Open>>, UnindexedClientError>> + Send
fn fetch_open_orders( &self, instruments: &[InstrumentNameExchange], ) -> impl Future<Output = Result<Vec<Order<ExchangeId, InstrumentNameExchange, Open>>, UnindexedClientError>> + Send
Fetch currently open orders, optionally filtered by instrument.
An empty instruments slice is the “return all” sentinel: implementations must
return open orders across all instruments. When non-empty, only orders for the
listed instruments are returned.
Sourcefn fetch_trades(
&self,
time_since: DateTime<Utc>,
instruments: &[InstrumentNameExchange],
) -> impl Future<Output = Result<Vec<Trade<AssetNameExchange, InstrumentNameExchange>>, UnindexedClientError>> + Send
fn fetch_trades( &self, time_since: DateTime<Utc>, instruments: &[InstrumentNameExchange], ) -> impl Future<Output = Result<Vec<Trade<AssetNameExchange, InstrumentNameExchange>>, UnindexedClientError>> + Send
Fetch trades (fills) since time_since, optionally filtered by instrument.
An empty instruments slice is the “return all” sentinel: implementations must
return trades across all instruments. When non-empty, only trades for the listed
instruments are returned.
The fee asset (AssetNameExchange) may be quote, base, or third-party (e.g., BNB).
Use fees.fees_quote for quote-equivalent value when available.
Note: MockExecution currently ignores instruments and always returns all trades.
Provided Methods§
fn cancel_orders<'a>( &self, requests: impl IntoIterator<Item = OrderRequestCancel<ExchangeId, &'a InstrumentNameExchange>>, ) -> impl Stream<Item = Option<UnindexedOrderResponseCancel>> + Send
fn open_orders<'a>( &self, requests: impl IntoIterator<Item = OrderRequestOpen<ExchangeId, &'a InstrumentNameExchange>>, ) -> impl Stream<Item = Option<Order<ExchangeId, InstrumentNameExchange, UnindexedOrderState>>> + Send
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.