import WebSocket from 'ws';
import * as proto from 'futu-sdk/proto';

interface WsUrl {
    host?: string;
    /** 默认WebSocket端口是33333, 不要传API端口11111 */
    port?: number;
    /** WebSocket密钥，必传（即可ssl设为false也要传，否则不能建立连接） */
    key: string;
}

type Message = {
    protobuf: Uint8Array;
    errorCode: number;
    errorMessage: string;
};
type RequestFn = (cmd: number, buf: Uint8Array, callback: (message: Message) => void) => () => void;
declare class WebRequest {
    private request;
    private subscribe;
    constructor(requestFn: Promise<RequestFn>);
    /**
     * @brief 初始化连接
     * @param [in] stReq 请求包，具体字段请参考InitWebSocket.proto协议
     */
    InitWebSocket: (c2s: proto.InitWebSocket.IRequest["c2s"], timeout?: number) => Promise<proto.InitWebSocket.IResponse["s2c"]>;
    /**
     * @brief 订阅，反订阅
     * @param [in] stReq 请求包，具体字段请参考Qot_Sub.proto协议
     */
    Sub: (c2s: proto.Qot_Sub.IRequest["c2s"]) => Generator<Promise<proto.Qot_Sub.IResponse["s2c"]>>;
    /**
     * @brief 获取交易帐号列表
     * @param [in] stReq 请求包，具体字段请参考Trd_GetAccList.proto协议
     */
    GetAccList: (c2s: proto.Trd_GetAccList.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_GetAccList.IResponse["s2c"]>;
    /**
     * @brief 解锁，针对OpenD解锁一次即可
     * @param [in] stReq 请求包，具体字段请参考Trd_UnlockTrade.proto协议
     */
    UnlockTrade: (c2s: proto.Trd_UnlockTrade.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_UnlockTrade.IResponse["s2c"]>;
    /**
     * @brief 订阅接收推送数据的交易账户
     * @param [in] stReq 请求包，具体字段请参考Trd_SubAccPush.proto协议
     */
    SubAccPush: (c2s: proto.Trd_SubAccPush.IRequest["c2s"]) => Generator<Promise<proto.Trd_SubAccPush.IResponse["s2c"]>>;
    /**
     * @brief 获取账户资金
     * @param [in] stReq 请求包，具体字段请参考Trd_GetFunds.proto协议
     */
    GetFunds: (c2s: proto.Trd_GetFunds.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_GetFunds.IResponse["s2c"]>;
    /**
     * @brief 获取账户持仓
     * @param [in] stReq 请求包，具体字段请参考Trd_GetPositionList.proto协议
     */
    GetPositionList: (c2s: proto.Trd_GetPositionList.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_GetPositionList.IResponse["s2c"]>;
    /**
     * @brief 获取最大交易数量
     * @param [in] stReq 请求包，具体字段请参考Trd_GetMaxTrdQtys.proto协议
     */
    GetMaxTrdQtys: (c2s: proto.Trd_GetMaxTrdQtys.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_GetMaxTrdQtys.IResponse["s2c"]>;
    /**
     * @brief 获取当日订单列表
     * @param [in] stReq 请求包，具体字段请参考Trd_GetOrderList.proto协议
     */
    GetOrderList: (c2s: proto.Trd_GetOrderList.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_GetOrderList.IResponse["s2c"]>;
    /**
     * @brief 下单
     * @param [in] stReq 请求包，具体字段请参考Trd_PlaceOrder.proto协议，PacketID不需填写，发送时接口会填
     */
    PlaceOrder: (c2s: proto.Trd_PlaceOrder.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_PlaceOrder.IResponse["s2c"]>;
    /**
     * @brief 修改订单
     * @param [in] stReq 请求包，具体字段请参考Trd_ModifyOrder.proto协议，PacketID不需填写，发送时接口会填
     */
    ModifyOrder: (c2s: proto.Trd_ModifyOrder.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_ModifyOrder.IResponse["s2c"]>;
    /**
     * @brief 获取当日成交列表
     * @param [in] stReq 请求包，具体字段请参考Trd_GetOrderFillList.proto协议
     */
    GetOrderFillList: (c2s: proto.Trd_GetOrderFillList.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_GetOrderFillList.IResponse["s2c"]>;
    /**
     * @brief 获取历史订单列表
     * @param [in] stReq 请求包，具体字段请参考Trd_GetHistoryOrderList.proto协议
     */
    GetHistoryOrderList: (c2s: proto.Trd_GetHistoryOrderList.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_GetHistoryOrderList.IResponse["s2c"]>;
    /**
     * @brief 获取历史成交列表
     * @param [in] stReq 请求包，具体字段请参考Trd_GetHistoryOrderFillList.proto协议
     */
    GetHistoryOrderFillList: (c2s: proto.Trd_GetHistoryOrderFillList.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_GetHistoryOrderFillList.IResponse["s2c"]>;
    /**
     * @brief 获取融资融券数据
     * @param [in] stReq 请求包，具体字段请参考Trd_GetMarginRatio.proto协议
     */
    GetMarginRatio: (c2s: proto.Trd_GetMarginRatio.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_GetMarginRatio.IResponse["s2c"]>;
    /**
     * @brief 获取订单收费明细数据
     * @param [in] stReq 请求包，具体字段请参考Trd_GetOrderFee.proto协议
     */
    GetOrderFee: (c2s: proto.Trd_GetOrderFee.IRequest["c2s"], timeout?: number) => Promise<proto.Trd_GetOrderFee.IResponse["s2c"]>;
    /**
     * @brief 请求全局状态
     * @praram 具体字段请参考GetGlobalState.proto协议
     */
    GetGlobalState: (c2s: proto.GetGlobalState.IRequest["c2s"], timeout?: number) => Promise<proto.GetGlobalState.IResponse["s2c"]>;
    /**
     * @brief 注册推送
     * @param 具体字段请参考Qot_RegQotPush.proto协议
     */
    RegQotPush: (c2s: proto.Qot_RegQotPush.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_RegQotPush.IResponse["s2c"]>;
    /**
     * @brief 获取订阅信息
     * @praram 具体字段请参考Qot_GetSubInfo.proto协议
     */
    GetSubInfo: (c2s: proto.GetUserInfo.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetSubInfo.IResponse["s2c"]>;
    /**
     * @brief 获取逐笔
     * @praram 具体字段请参考Qot_GetTicker.proto协议
     */
    GetTicker: (c2s: proto.Qot_GetTicker.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetTicker.IResponse["s2c"]>;
    /**
     * @brief 获取报价
     * @praram 具体字段请参考Qot_GetBasicQot.proto协议
     */
    GetBasicQot: (c2s: proto.Qot_GetBasicQot.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetBasicQot.IResponse["s2c"]>;
    /**
     * @brief 获取摆盘
     * @praram 具体字段请参考Qot_GetOrderBook.proto协议
     */
    GetOrderBook: (c2s: proto.Qot_GetOrderBook.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetOrderBook.IResponse["s2c"]>;
    /**
     * @brief 获取K线
     * @praram 具体字段请参考Qot_GetKL.proto协议
     */
    GetKL: (c2s: proto.Qot_GetKL.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetKL.IResponse["s2c"]>;
    /**
     * @brief 获取分时
     * @praram 具体字段请参考Qot_GetRT.proto协议
     */
    GetRT: (c2s: proto.Qot_GetRT.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetRT.IResponse["s2c"]>;
    /**
     * @brief 获取经纪队列
     * @praram 具体字段请参考Qot_GetBroker.proto协议
     */
    GetBroker: (c2s: proto.Qot_GetBroker.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetBroker.IResponse["s2c"]>;
    /**
     * @brief 在线请求历史复权信息，不读本地历史数据DB
     * @praram 具体字段请参考Qot_RequestRehab.proto协议
     */
    RequestRehab: (c2s: proto.Qot_RequestRehab.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_RequestRehab.IResponse["s2c"]>;
    /**
     * @brief 在线请求历史K线，不读本地历史数据DB
     * @praram 具体字段请参考Qot_RequestHistoryKL.proto协议
     */
    RequestHistoryKL: (c2s: proto.Qot_RequestHistoryKL.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_RequestHistoryKL.IResponse["s2c"]>;
    /**
     * @brief 获取历史K线已经用掉的额度
     * @praram 具体字段请参考Qot_RequestHistoryKLQuota.proto协议
     */
    RequestHistoryKLQuota: (c2s: proto.Qot_RequestHistoryKLQuota.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_RequestHistoryKLQuota.IResponse["s2c"]>;
    /**
     * @brief 获取静态信息
     * @praram 具体字段请参考Qot_GetStaticInfo.proto协议
     */
    GetStaticInfo: (c2s: proto.Qot_GetStaticInfo.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetStaticInfo.IResponse["s2c"]>;
    /**
     * @brief 获取股票快照
     * @praram 具体字段请参考Qot_GetSecuritySnapshot.proto协议
     */
    GetSecuritySnapshot: (c2s: proto.Qot_GetSecuritySnapshot.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetSecuritySnapshot.IResponse["s2c"]>;
    /**
     * @brief 获取板块集合下的板块
     * @praram 具体字段请参考Qot_GetPlateSet.proto协议
     */
    GetPlateSet: (c2s: proto.Qot_GetPlateSet.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetPlateSet.IResponse["s2c"]>;
    /**
     * @brief 获取板块下的股票
     * @praram 具体字段请参考Qot_GetPlateSecurity.proto协议
     */
    GetPlateSecurity: (c2s: proto.Qot_GetPlateSecurity.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetPlateSecurity.IResponse["s2c"]>;
    /**
     * @brief 获取相关股票
     * @praram 具体字段请参考Qot_GetReference.proto协议
     */
    GetReference: (c2s: proto.Qot_GetReference.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetReference.IResponse["s2c"]>;
    /**
     * @brief 获取股票所属的板块
     * @praram 具体字段请参考Qot_GetOwnerPlate.proto协议
     */
    GetOwnerPlate: (c2s: proto.Qot_GetOwnerPlate.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetOwnerPlate.IResponse["s2c"]>;
    /**
     * @brief 获取大股东持股变化列表
     * @praram 具体字段请参考Qot_GetHoldingChangeList.proto协议
     */
    GetHoldingChangeList: (c2s: proto.Qot_GetHoldingChangeList.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetHoldingChangeList.IResponse["s2c"]>;
    /**
     * @brief 筛选期权
     * @praram 具体字段请参考Qot_GetOptionChain.proto协议
     */
    GetOptionChain: (c2s: proto.Qot_GetOptionChain.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetOptionChain.IResponse["s2c"]>;
    /**
     * @brief 筛选窝轮
     * @praram 具体字段请参考Qot_GetWarrant.proto协议
     */
    GetWarrant: (c2s: proto.Qot_GetWarrant.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetWarrant.IResponse["s2c"]>;
    /**
     * @brief 获取资金流向
     * @praram 具体字段请参考Qot_GetCapitalFlow.proto协议
     */
    GetCapitalFlow: (c2s: proto.Qot_GetCapitalFlow.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetCapitalFlow.IResponse["s2c"]>;
    /**
     * @brief 获取资金分布
     * @praram 具体字段请参考Qot_GetCapitalDistribution.proto协议
     */
    GetCapitalDistribution: (c2s: proto.Qot_GetCapitalDistribution.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetCapitalDistribution.IResponse["s2c"]>;
    /**
     * @brief 获取自选股分组下的股票
     * @praram 具体字段请参考Qot_GetUserSecurity.proto协议
     */
    GetUserSecurity: (c2s: proto.Qot_GetUserSecurity.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetUserSecurity.IResponse["s2c"]>;
    /**
     * @brief 修改自选股分组下的股票
     * @praram 具体字段请参考Qot_ModifyUserSecurity.proto协议
     */
    ModifyUserSecurity: (c2s: proto.Qot_ModifyUserSecurity.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_ModifyUserSecurity.IResponse["s2c"]>;
    /**
     * @brief 条件选股
     * @praram 具体字段请参考Qot_StockFilter.proto协议
     */
    StockFilter: (c2s: proto.Qot_StockFilter.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_StockFilter.IResponse["s2c"]>;
    /**
     * @brief 获取股票代码变化信息
     * @praram 具体字段请参考Qot_GetCodeChange.proto协议
     */
    GetCodeChange: (c2s: proto.Qot_GetCodeChange.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetCodeChange.IResponse["s2c"]>;
    /**
     * @brief 新股IPO
     * @praram 具体字段请参考Qot_GetIpoList.proto协议
     */
    GetIpoList: (c2s: proto.Qot_GetIpoList.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetIpoList.IResponse["s2c"]>;
    /**
     * @brief 期货合约资料
     * @praram 具体字段请参考Qot_GetFutureInfo.proto协议
     */
    GetFutureInfo: (c2s: proto.Qot_GetFutureInfo.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetFutureInfo.IResponse["s2c"]>;
    /**
     * @brief 获取市场交易日
     * @praram 具体字段请参考QotRequestTradeDate.proto协议
     */
    RequestTradeDate: (c2s: proto.Qot_RequestTradeDate.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_RequestTradeDate.IResponse["s2c"]>;
    /**
     * @brief 设置到价提醒
     * @praram 具体字段请参考QotSetPriceReminder.proto协议
     */
    SetPriceReminder: (c2s: proto.Qot_SetPriceReminder.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_SetPriceReminder.IResponse["s2c"]>;
    /**
     * @brief 获取到价提醒
     * @praram 具体字段请参考QotGetPriceReminder.proto协议
     */
    GetPriceReminder: (c2s: proto.Qot_GetPriceReminder.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetPriceReminder.IResponse["s2c"]>;
    /**
     * @brief 获取自选股分组列表
     * @praram 具体字段请参考QotGetUserSecurityGroup.proto协议
     */
    GetUserSecurityGroup: (c2s: proto.Qot_GetUserSecurityGroup.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetUserSecurityGroup.IResponse["s2c"]>;
    /**
     * @brief 获取股票对应市场状态
     * @praram 具体字段请参考QotGetMarketState.proto协议
     */
    GetMarketState: (c2s: proto.Qot_GetMarketState.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetMarketState.IResponse["s2c"]>;
    /**
     * @brief 获取期权链到期日
     * @praram 具体字段请参考QotGetOptionExpirationDate.proto协议
     */
    GetOptionExpirationDate: (c2s: proto.Qot_GetOptionExpirationDate.IRequest["c2s"], timeout?: number) => Promise<proto.Qot_GetOptionExpirationDate.IResponse["s2c"]>;
}

interface IWebRequest extends Omit<WebRequest, 'InitWebSocket'> {
}
/**
 * getFutuApi 内部实例化 WebSocket 连接，并基于 WebSocket 封装了的查询对象 WebRequest, 你可以使用 `webRequest` 查询各种接口，
 * 也可以使用 `webSocket` 来关闭连接(`webSocket.close()`)和实现事件监听(如 onclose/onopen/onmessage等)
 *
 * Example:
 *
 * ```ts
 * import { getFutuApi } from 'futu-sdk';
 * // import { Trd_Common } from 'futu-sdk/proto';
 *
 * const { webRequest, webSocket } = getFutuApi('ws://127.0.0.1:33333', '9d261112869397f0');
 * try {
 *   const { accList } = (await webRequest.GetAccList({ userID: 0, needGeneralSecAccount: true })) || {};
 *   console.log({ accList });
 * } finally {
 *   webSocket.close();
 * }
 * ```
 * @param wsUrl 连接本地 WebSocket 的地址，如 `ws://127.0.0.1:33333`
 * @param key WebSocket 密钥，每次启动 OpenD 可能都不一样
 * @returns `{ webRequest: WebRequest, webSocket: WebSocket }`
 */
declare const getFutuApi: (wsUrl: string, key: string) => {
    webSocket: WebSocket;
    webRequest: IWebRequest;
};
/**
 * @deprecated 已废弃，请使用 `const { webRequest } = getFutuApi(`ws://${host}:${port}`, key);`
 */
declare const getWebRequest: ({ host, port, key }: WsUrl) => IWebRequest;

export { type IWebRequest, getFutuApi, getWebRequest };
