package com.xcong.excoin.modules.okxApi.wsHandler;
|
|
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONObject;
|
import com.xcong.excoin.modules.okxApi.OkxGridTradeService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.java_websocket.client.WebSocketClient;
|
|
/**
|
* OKX 私有频道 WS 处理器的抽象基类。
|
*
|
* <h3>与 Gate 版本的关键区别</h3>
|
* <ul>
|
* <li>OKX 私有频道连接到<b>独立的私有 WebSocket 端点</b> ({@code wss://ws.okx.com:8443/ws/v5/private}),
|
* 需要先发送 login 消息认证,不同于 Gate 的单一 WS + 签名订阅模式。</li>
|
* <li>订阅格式使用 {@code op/subscribe} 而非 event/subscribe。</li>
|
* <li>签名算法使用 HMAC-SHA256 + Base64,而非 Gate 的 HMAC-SHA512 + Hex。</li>
|
* </ul>
|
*
|
* <h3>架构</h3>
|
* 公有频道(如 k-line)连接到 public WS 端点,无需认证。
|
* 私有频道(如 positions、orders-algo)连接到 private WS 端点,由
|
* {@link com.xcong.excoin.modules.okxApi.OkxKlineWebSocketClient} 负责
|
* 在连接建立时发送 login 消息认证。
|
*
|
* <h3>订阅格式</h3>
|
* <pre>
|
* {"op":"subscribe","args":[{"channel":"positions","instType":"SWAP"}]}
|
* {"op":"subscribe","args":[{"channel":"orders-algo","instType":"SWAP","instId":"ETH-USDT-SWAP"}]}
|
* </pre>
|
*
|
* <h3>取消订阅格式</h3>
|
* <pre>
|
* {"op":"unsubscribe","args":[{"channel":"positions","instType":"SWAP"}]}
|
* </pre>
|
*
|
* @author Administrator
|
*/
|
@Slf4j
|
public abstract class AbstractOkxPrivateChannelHandler implements OkxChannelHandler {
|
|
/** 频道名称,如 "positions"、"orders-algo" */
|
private final String channelName;
|
|
/** OKX API Key */
|
protected final String apiKey;
|
|
/** OKX API Secret(用于签名) */
|
protected final String apiSecret;
|
|
/** OKX API Passphrase */
|
protected final String passphrase;
|
|
/** 交易对标识,如 "ETH-USDT-SWAP" */
|
private final String instId;
|
|
/** 网格交易服务实例 */
|
private final OkxGridTradeService gridTradeService;
|
|
/** 订阅确认状态 */
|
private volatile boolean subscribed = false;
|
|
/**
|
* 构造私有频道处理器。
|
*
|
* @param channelName 频道名称(如 "positions"、"orders-algo")
|
* @param apiKey OKX API Key
|
* @param apiSecret OKX API Secret
|
* @param passphrase OKX API Passphrase
|
* @param instId 交易对标识(如 "ETH-USDT-SWAP")
|
* @param gridTradeService 网格交易服务实例
|
*/
|
public AbstractOkxPrivateChannelHandler(String channelName,
|
String apiKey, String apiSecret,
|
String passphrase,
|
String instId,
|
OkxGridTradeService gridTradeService) {
|
this.channelName = channelName;
|
this.apiKey = apiKey;
|
this.apiSecret = apiSecret;
|
this.passphrase = passphrase;
|
this.instId = instId;
|
this.gridTradeService = gridTradeService;
|
}
|
|
/**
|
* @return 频道名称(如 "positions")
|
*/
|
@Override
|
public String getChannelName() {
|
return channelName;
|
}
|
|
/**
|
* @return 交易对标识(如 "ETH-USDT-SWAP")
|
*/
|
@Override
|
public String getInstId() {
|
return instId;
|
}
|
|
/**
|
* 发送订阅请求。
|
* 默认实现发送 {@code {"op":"subscribe","args":[{"channel":channelName,"instType":"SWAP"}]}}。
|
* 子类可覆盖以添加额外参数(如 instId)。
|
*
|
* @param ws 私有频道 WebSocket 客户端
|
*/
|
@Override
|
public void subscribe(WebSocketClient ws) {
|
JSONObject msg = new JSONObject();
|
msg.put("op", "subscribe");
|
JSONArray args = new JSONArray();
|
JSONObject arg = new JSONObject();
|
arg.put("channel", channelName);
|
arg.put("instType", "SWAP");
|
args.add(arg);
|
msg.put("args", args);
|
ws.send(msg.toJSONString());
|
log.info("[OKX-WS] 订阅私有频道: {}, instType: SWAP", channelName);
|
}
|
|
/**
|
* 发送取消订阅请求。
|
*
|
* @param ws 私有频道 WebSocket 客户端
|
*/
|
@Override
|
public void unsubscribe(WebSocketClient ws) {
|
JSONObject msg = new JSONObject();
|
msg.put("op", "unsubscribe");
|
JSONArray args = new JSONArray();
|
JSONObject arg = new JSONObject();
|
arg.put("channel", channelName);
|
arg.put("instType", "SWAP");
|
args.add(arg);
|
msg.put("args", args);
|
ws.send(msg.toJSONString());
|
log.info("[OKX-WS] 取消订阅私有频道: {}", channelName);
|
}
|
|
/**
|
* @return 网格交易服务实例
|
*/
|
protected OkxGridTradeService getGridTradeService() {
|
return gridTradeService;
|
}
|
|
// ==================== 订阅状态 ====================
|
|
@Override
|
public boolean isSubscribed() {
|
return subscribed;
|
}
|
|
@Override
|
public void setSubscribed(boolean subscribed) {
|
this.subscribed = subscribed;
|
}
|
}
|