1use async_trait::async_trait;
2use futu_core::error::FutuError;
3use futu_core::proto_id;
4
5#[async_trait]
7pub trait TradeHandler: Send + Sync + 'static {
8 async fn on_order_update(&self, _header: OrderUpdateInfo) {}
10
11 async fn on_order_fill_update(&self, _header: OrderFillUpdateInfo) {}
13
14 async fn on_trd_notify(&self, _info: TrdNotifyInfo) {}
16}
17
18#[derive(Debug, Clone)]
20pub struct OrderUpdateInfo {
21 pub trd_env: i32,
23 pub acc_id: u64,
25 pub trd_market: i32,
27 pub raw_body: bytes::Bytes,
30}
31
32#[derive(Debug, Clone)]
34pub struct OrderFillUpdateInfo {
35 pub trd_env: i32,
37 pub acc_id: u64,
39 pub trd_market: i32,
41 pub raw_body: bytes::Bytes,
43}
44
45pub struct TradePushDispatcher;
47
48impl TradePushDispatcher {
49 pub async fn dispatch(
51 handler: &dyn TradeHandler,
52 proto_id_val: u32,
53 body: &[u8],
54 ) -> Result<(), FutuError> {
55 match proto_id_val {
56 proto_id::TRD_UPDATE_ORDER => {
57 let resp: futu_proto::trd_update_order::Response =
58 prost::Message::decode(body).map_err(FutuError::Proto)?;
59 if let Some(s2c) = &resp.s2c {
60 let info = OrderUpdateInfo {
61 trd_env: s2c.header.trd_env,
62 acc_id: s2c.header.acc_id,
63 trd_market: s2c.header.trd_market,
64 raw_body: bytes::Bytes::copy_from_slice(body),
65 };
66 handler.on_order_update(info).await;
67 }
68 }
69 proto_id::TRD_UPDATE_ORDER_FILL => {
70 let resp: futu_proto::trd_update_order_fill::Response =
71 prost::Message::decode(body).map_err(FutuError::Proto)?;
72 if let Some(s2c) = &resp.s2c {
73 let info = OrderFillUpdateInfo {
74 trd_env: s2c.header.trd_env,
75 acc_id: s2c.header.acc_id,
76 trd_market: s2c.header.trd_market,
77 raw_body: bytes::Bytes::copy_from_slice(body),
78 };
79 handler.on_order_fill_update(info).await;
80 }
81 }
82 proto_id::TRD_NOTIFY => {
83 let resp: futu_proto::trd_notify::Response =
84 prost::Message::decode(body).map_err(FutuError::Proto)?;
85 if let Some(s2c) = &resp.s2c {
86 let info = TrdNotifyInfo {
87 trd_env: s2c.header.trd_env,
88 acc_id: s2c.header.acc_id,
89 trd_market: s2c.header.trd_market,
90 notify_type: s2c.r#type,
91 };
92 handler.on_trd_notify(info).await;
93 }
94 }
95 _ => {
96 tracing::debug!(proto_id = proto_id_val, "unhandled trade push");
97 }
98 }
99 Ok(())
100 }
101}
102
103#[derive(Debug, Clone)]
105pub struct TrdNotifyInfo {
106 pub trd_env: i32,
108 pub acc_id: u64,
110 pub trd_market: i32,
112 pub notify_type: i32,
114}