Skip to main content

ExecutionClient

Trait ExecutionClient 

Source
pub trait ExecutionClient
where 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§

Required Associated Types§

Required Methods§

Source

fn new(config: Self::Config) -> Self

Source

fn account_snapshot( &self, assets: &[AssetNameExchange], instruments: &[InstrumentNameExchange], ) -> impl Future<Output = Result<UnindexedAccountSnapshot, UnindexedClientError>> + Send

Source

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).

Source

fn cancel_order( &self, request: OrderRequestCancel<ExchangeId, &InstrumentNameExchange>, ) -> impl Future<Output = Option<UnindexedOrderResponseCancel>> + Send

Source

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 book
  • OrderState::Inactive(FullyFilled) - order was immediately filled (includes avg_price when 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.

Source

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.

Source

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.

Source

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§

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.

Implementors§