1use futu_core::error::{FutuError, Result};
2use futu_core::proto_id;
3use futu_net::client::FutuClient;
4
5use crate::types::{QotMarket, Security};
6
7#[derive(Debug, Clone)]
9pub struct SecurityStaticInfo {
10 pub security: Security,
11 pub id: i64,
12 pub lot_size: i32,
13 pub sec_type: i32,
14 pub name: String,
15 pub list_time: String,
16 pub delisting: bool,
17}
18
19impl SecurityStaticInfo {
20 pub fn from_proto(info: &futu_proto::qot_common::SecurityStaticInfo) -> Self {
21 let basic = &info.basic;
22 Self {
23 security: Security::from_proto(&basic.security),
24 id: basic.id,
25 lot_size: basic.lot_size,
26 sec_type: basic.sec_type,
27 name: basic.name.clone(),
28 list_time: basic.list_time.clone(),
29 delisting: basic.delisting.unwrap_or(false),
30 }
31 }
32}
33
34pub async fn get_static_info(
38 client: &FutuClient,
39 securities: &[Security],
40) -> Result<Vec<SecurityStaticInfo>> {
41 let req = futu_proto::qot_get_static_info::Request {
42 c2s: futu_proto::qot_get_static_info::C2s {
43 market: None,
44 sec_type: None,
45 security_list: securities.iter().map(|s| s.to_proto()).collect(),
46 },
47 };
48
49 let body = prost::Message::encode_to_vec(&req);
50 let resp_frame = client.request(proto_id::QOT_GET_STATIC_INFO, body).await?;
51
52 let resp: futu_proto::qot_get_static_info::Response =
53 prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
54
55 if resp.ret_type != 0 {
56 return Err(FutuError::ServerError {
57 ret_type: resp.ret_type,
58 msg: resp.ret_msg.unwrap_or_default(),
59 });
60 }
61
62 let s2c = resp
63 .s2c
64 .ok_or(FutuError::Codec("missing s2c in GetStaticInfo".into()))?;
65
66 Ok(s2c
67 .static_info_list
68 .iter()
69 .map(SecurityStaticInfo::from_proto)
70 .collect())
71}
72
73pub async fn get_static_info_by_market(
75 client: &FutuClient,
76 market: QotMarket,
77 sec_type: i32,
78) -> Result<Vec<SecurityStaticInfo>> {
79 let req = futu_proto::qot_get_static_info::Request {
80 c2s: futu_proto::qot_get_static_info::C2s {
81 market: Some(market as i32),
82 sec_type: Some(sec_type),
83 security_list: vec![],
84 },
85 };
86
87 let body = prost::Message::encode_to_vec(&req);
88 let resp_frame = client.request(proto_id::QOT_GET_STATIC_INFO, body).await?;
89
90 let resp: futu_proto::qot_get_static_info::Response =
91 prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
92
93 if resp.ret_type != 0 {
94 return Err(FutuError::ServerError {
95 ret_type: resp.ret_type,
96 msg: resp.ret_msg.unwrap_or_default(),
97 });
98 }
99
100 let s2c = resp
101 .s2c
102 .ok_or(FutuError::Codec("missing s2c in GetStaticInfo".into()))?;
103
104 Ok(s2c
105 .static_info_list
106 .iter()
107 .map(SecurityStaticInfo::from_proto)
108 .collect())
109}