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_COMBO_ORDER => {
19            let request = futu_proto::trd_place_combo_order::Request::decode(body.as_slice())?;
20            Ok(fill_omitted_trade_packet_id(proto_id, request, conn_id, serial_no).encode_to_vec())
21        }
22        _ => Ok(body),
23    }
24}
25
26pub fn fill_omitted_trade_packet_id(
27    proto_id: u32,
28    mut request: futu_proto::trd_place_combo_order::Request,
29    conn_id: u64,
30    serial_no: u32,
31) -> futu_proto::trd_place_combo_order::Request {
32    if proto_id == futu_core::proto_id::TRD_PLACE_COMBO_ORDER
33        && request.c2s.packet_id.conn_id == 0
34        && request.c2s.packet_id.serial_no == 0
35    {
36        request.c2s.packet_id = futu_proto::common::PacketId { conn_id, serial_no };
37    }
38    request
39}
40
41#[cfg(test)]
42mod tests;