Skip to main content

futu_server/trade_packet_id/
mod.rs

1//! Helpers for surface adapters that need to synthesize FTAPI trade PacketID.
2
3use prost::Message;
4
5/// Fill an omitted FTAPI trade `PacketID` for public surface adapters.
6///
7/// Raw TCP keeps C++ `IsReplayAttack(nConnID, packetID)` semantics in the trade
8/// handlers. REST/gRPC do not expose a real FTAPI connection to users, so they
9/// may submit `packetID=(0,0)` and let the surface adapter synthesize the
10/// current virtual `conn_id`/`serial_no` before dispatch.
11pub fn fill_omitted_trade_packet_id_bytes(
12    proto_id: u32,
13    body: Vec<u8>,
14    conn_id: u64,
15    serial_no: u32,
16) -> Result<Vec<u8>, prost::DecodeError> {
17    match proto_id {
18        futu_core::proto_id::TRD_PLACE_ORDER => {
19            let request = futu_proto::trd_place_order::Request::decode(body.as_slice())?;
20            Ok(fill_omitted_place_order_packet_id(request, conn_id, serial_no).encode_to_vec())
21        }
22        futu_core::proto_id::TRD_PLACE_COMBO_ORDER => {
23            let request = futu_proto::trd_place_combo_order::Request::decode(body.as_slice())?;
24            Ok(fill_omitted_trade_packet_id(proto_id, request, conn_id, serial_no).encode_to_vec())
25        }
26        futu_core::proto_id::TRD_MODIFY_ORDER => {
27            let request = futu_proto::trd_modify_order::Request::decode(body.as_slice())?;
28            Ok(fill_omitted_modify_order_packet_id(request, conn_id, serial_no).encode_to_vec())
29        }
30        _ => Ok(body),
31    }
32}
33
34pub fn fill_omitted_trade_packet_id(
35    proto_id: u32,
36    mut request: futu_proto::trd_place_combo_order::Request,
37    conn_id: u64,
38    serial_no: u32,
39) -> futu_proto::trd_place_combo_order::Request {
40    if proto_id == futu_core::proto_id::TRD_PLACE_COMBO_ORDER
41        && request.c2s.packet_id.conn_id == 0
42        && request.c2s.packet_id.serial_no == 0
43    {
44        request.c2s.packet_id = futu_proto::common::PacketId { conn_id, serial_no };
45    }
46    request
47}
48
49pub fn fill_omitted_place_order_packet_id(
50    mut request: futu_proto::trd_place_order::Request,
51    conn_id: u64,
52    serial_no: u32,
53) -> futu_proto::trd_place_order::Request {
54    if request.c2s.packet_id.conn_id == 0 && request.c2s.packet_id.serial_no == 0 {
55        request.c2s.packet_id = futu_proto::common::PacketId { conn_id, serial_no };
56    }
57    request
58}
59
60pub fn fill_omitted_modify_order_packet_id(
61    mut request: futu_proto::trd_modify_order::Request,
62    conn_id: u64,
63    serial_no: u32,
64) -> futu_proto::trd_modify_order::Request {
65    if request.c2s.packet_id.conn_id == 0 && request.c2s.packet_id.serial_no == 0 {
66        request.c2s.packet_id = futu_proto::common::PacketId { conn_id, serial_no };
67    }
68    request
69}
70
71#[cfg(test)]
72mod tests;