futu_mcp/handlers/reference/
code_change.rs1use std::sync::Arc;
5
6use anyhow::{Result, anyhow, bail};
7use futu_net::client::FutuClient;
8use prost::Message;
9use serde::Serialize;
10
11use crate::state::parse_symbol;
12
13#[derive(Serialize)]
18struct CodeChangeOut {
19 change_type: i32,
20 main_code: String,
21 related_code: String,
22 public_time: Option<String>,
23 effective_time: Option<String>,
24}
25
26pub async fn get_code_change(client: &Arc<FutuClient>, symbols: &[String]) -> Result<String> {
28 let sec_list: Vec<_> = symbols
29 .iter()
30 .map(|s| parse_symbol(s))
31 .collect::<Result<Vec<_>>>()?;
32 let proto_secs: Vec<_> = sec_list
33 .iter()
34 .map(|s| futu_proto::qot_common::Security {
35 market: s.market as i32,
36 code: s.code.clone(),
37 })
38 .collect();
39 let req = futu_proto::qot_get_code_change::Request {
40 c2s: futu_proto::qot_get_code_change::C2s {
41 place_holder: None,
42 security_list: proto_secs,
43 time_filter_list: vec![],
44 type_list: vec![],
45 header: None,
46 },
47 };
48 let body = req.encode_to_vec();
49 let frame = client
50 .request(futu_core::proto_id::QOT_GET_CODE_CHANGE, body)
51 .await?;
52 let resp = futu_proto::qot_get_code_change::Response::decode(frame.body.as_ref())
53 .map_err(|e| anyhow!("decode code_change: {e}"))?;
54 if resp.ret_type != 0 {
55 bail!(
56 "code_change ret_type={} msg={:?}",
57 resp.ret_type,
58 resp.ret_msg
59 );
60 }
61 let s2c = resp.s2c.ok_or_else(|| anyhow!("missing s2c"))?;
62 let out: Vec<CodeChangeOut> = s2c
63 .code_change_list
64 .iter()
65 .map(|c| CodeChangeOut {
66 change_type: c.r#type,
67 main_code: c.security.code.clone(),
68 related_code: c.related_security.code.clone(),
69 public_time: c.public_time.clone(),
70 effective_time: c.effective_time.clone(),
71 })
72 .collect();
73 Ok(serde_json::to_string_pretty(&out)?)
74}