diff --git a/README.md b/README.md index 5ca9870..cd8fe6f 100644 --- a/README.md +++ b/README.md @@ -40,29 +40,25 @@ Maven Example io.github.wuhewuhe bybit-java-api - 1.2.3 + 1.2.4 ``` Gradle Example ```java -implementation group: 'io.github.wuhewuhe', name: 'bybit-java-api', version: '1.2.3' +implementation group: 'io.github.wuhewuhe', name: 'bybit-java-api', version: '1.2.4' ``` Furthermore, build tool, please check [sonar type central repository](https://central.sonatype.com/artifact/io.github.wuhewuhe/bybit-java-api/1.2.3) ## Release-Notes -### HTTP Sync & Async Request -- Position new endpoints: Move Positions and Get Move Positions History -- Account new endpoint: Batch Set Collateral Coin -- TradeOrderRequest add a new parameter: marketUnit +### Websockets +- Add WebSocketMessage handler class to all public and private channels ### Improvements -- Fix Switch Position Mode Issue +- public and private websocket channel set message handler ### Change Log -- C:\Net\GithubProjects\open-api-sdk\bybit-java-api -- Set Tp/SL and Set Risk Limit endpoints are deprecated -- GetExecutionList move from PositionService to TradeService and rename to GetTradeHistory - +- Spot Margin Trade endpoints are decrypted for classical users +- ## Usage Note: Replace placeholders (like YOUR_API_KEY, links, or other details) with the actual information. You can also customize this template to better fit the actual state and details of your Java API. ### HttP Client Factory & Websocket Client @@ -224,16 +220,42 @@ client.getPublicChannelStream(List.of("orderbook.50.BTCUSDT"), BybitApiConfig.V5 client.getPublicChannelStream(List.of("orderbook.50.BTCUSDT","orderbook.1.ETHUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); ``` +- Ticker Subscribe +```java +var client = BybitApiClientFactory.newInstance(BybitApiConfig.STREAM_MAINNET_DOMAIN, true).newWebsocketClient(); + +client.setMessageHandler(message -> { + var tickerData = (new ObjectMapper()).readValue(message, WebSocketTickerMessage.class); + // Process message data here + System.out.println("Websocket Message Data: " + tickerData.getData().toString()); +}); + +// Ticker +client.getPublicChannelStream(List.of("tickers.BTCUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); +``` + ### Websocket private channel -- Order Subscribe +- Position Subscribe ```java -var client = BybitApiClientFactory.newInstance("YOUR_API_KEY", "YOUR_API_SECRET", BybitApiConfig.STREAM_TESTNET_DOMAIN).newWebsocketClient(5, "60s", (message) -> System.out.println("Handle message :" + message)); +var client = BybitApiClientFactory.newInstance("YOUR_API_KEY", "YOUR_API_SECRET", BybitApiConfig.STREAM_TESTNET_DOMAIN).newWebsocketClient(); + // Position -// client.getOrderBookStream(List.of("position.linear"), BybitApiConfig.V5_PRIVATE); +client.getPrivateChannelStream(List.of("position"), BybitApiConfig.V5_PRIVATE); +``` + +- Order Channel active Message Handler & Max Alive Time & Ping Interval +```java +var client = BybitApiClientFactory.newInstance("YOUR_API_KEY", "YOUR_API_SECRET", BybitApiConfig.STREAM_TESTNET_DOMAIN, true) + .newWebsocketClient(5, "60s", (message) -> { + var orderMessage = (new ObjectMapper()).readValue(message, WebSocketOrderMessage.class); + // Process message data here + System.out.println("Websocket Message Data: " + orderMessage.getData().toString()); + }); // Order client.getPrivateChannelStream(List.of("order"), BybitApiConfig.V5_PRIVATE); ``` + ## Contact For support, join our Bybit API community on [Telegram](https://t.me/Bybitapi). diff --git a/pom.xml b/pom.xml index 0b8f3ff..32d5101 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.wuhewuhe bybit-java-api - 1.2.3 + 1.2.4-SNAPSHOT bybit-java-api https://github.com/wuhewuhe/bybit-java-api diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/CoinData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/CoinData.java new file mode 100644 index 0000000..4c0098c --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/CoinData.java @@ -0,0 +1,30 @@ +package com.bybit.api.client.domain.websocket_message.private_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class CoinData { + private String coin; + private String equity; + private String usdValue; + private String walletBalance; + private String free; + private String locked; + private String spotHedgingQty; + private String borrowAmount; + private String availableToBorrow; + private String availableToWithdraw; + private String accruedInterest; + private String totalOrderIM; + private String totalPositionIM; + private String totalPositionMM; + private String unrealisedPnl; + private String cumRealisedPnl; + private String bonus; + private Boolean collateralSwitch; + private Boolean marginCollateral; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/ExecutionData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/ExecutionData.java new file mode 100644 index 0000000..19ff812 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/ExecutionData.java @@ -0,0 +1,40 @@ +package com.bybit.api.client.domain.websocket_message.private_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class ExecutionData { + private String category; + private String symbol; + private String isLeverage; + private String orderId; + private String orderLinkId; + private String side; + private String orderPrice; + private String orderQty; + private String leavesQty; + private String createType; + private String orderType; + private String stopOrderType; + private String execFee; + private String execId; + private String execPrice; + private String execQty; + private String execType; + private String execValue; + private String execTime; + private Boolean isMaker; + private String feeRate; + private String tradeIv; + private String markIv; + private String markPrice; + private String indexPrice; + private String underlyingPrice; + private String blockTradeId; + private String closedSize; + private Long seq; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/GreekData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/GreekData.java new file mode 100644 index 0000000..1d09b3e --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/GreekData.java @@ -0,0 +1,16 @@ +package com.bybit.api.client.domain.websocket_message.private_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class GreekData { + private String baseCoin; + private String totalDelta; + private String totalGamma; + private String totalVega; + private String totalTheta; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/OrderData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/OrderData.java new file mode 100644 index 0000000..1cd6613 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/OrderData.java @@ -0,0 +1,57 @@ +package com.bybit.api.client.domain.websocket_message.private_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class OrderData { + private String category; + private String orderId; + private String orderLinkId; + private String isLeverage; + private String blockTradeId; + private String symbol; + private String price; + private String qty; + private String side; + private Integer positionIdx; + private String orderStatus; + private String createType; + private String cancelType; + private String rejectReason; + private String avgPrice; + private String leavesQty; + private String leavesValue; + private String cumExecQty; + private String cumExecValue; + private String cumExecFee; + private String feeCurrency; + private String timeInForce; + private String orderType; + private String stopOrderType; + private String ocoTriggerType; + private String orderIv; + private String marketUnit; + private String triggerPrice; + private String takeProfit; + private String stopLoss; + private String tpslMode; + private String tpLimitPrice; + private String slLimitPrice; + private String tpTriggerBy; + private String slTriggerBy; + private Integer triggerDirection; + private String triggerBy; + private String lastPriceOnCreated; + private Boolean reduceOnly; + private Boolean closeOnTrigger; + private String placeType; + private String smpType; + private Integer smpGroup; + private String smpOrderId; + private String createdTime; + private String updatedTime; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/PositionData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/PositionData.java new file mode 100644 index 0000000..9b07bed --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/PositionData.java @@ -0,0 +1,43 @@ +package com.bybit.api.client.domain.websocket_message.private_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class PositionData { + private String category; + private String symbol; + private String side; + private String size; + private Integer positionIdx; + private Integer tradeMode; + private String positionValue; + private Integer riskId; + private String riskLimitValue; + private String entryPrice; + private String markPrice; + private String leverage; + private String positionBalance; + private Integer autoAddMargin; + private String positionMM; + private String positionIM; + private String liqPrice; + private String bustPrice; + private String tpslMode; + private String takeProfit; + private String stopLoss; + private String trailingStop; + private String unrealisedPnl; + private String cumRealisedPnl; + private String positionStatus; + private Integer adlRankIndicator; + private Boolean isReduceOnly; + private String mmrSysUpdatedTime; + private String leverageSysUpdatedTime; + private String createdTime; + private String updatedTime; + private Long seq; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WalletData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WalletData.java new file mode 100644 index 0000000..a151270 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WalletData.java @@ -0,0 +1,26 @@ +package com.bybit.api.client.domain.websocket_message.private_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class WalletData { + private String accountType; + private String accountLTV; + private String accountIMRate; + private String accountMMRate; + private String totalEquity; + private String totalWalletBalance; + private String totalMarginBalance; + private String totalAvailableBalance; + private String totalPerpUPL; + private String totalInitialMargin; + private String totalMaintenanceMargin; + private List coin; + +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketExecutionMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketExecutionMessage.java new file mode 100644 index 0000000..bbe0c95 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketExecutionMessage.java @@ -0,0 +1,15 @@ +package com.bybit.api.client.domain.websocket_message.private_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebSocketExecutionMessage { + private String id; + private String topic; + private Long creationTime; + private List data; // Assuming 'data' is an array of KlineData objects +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketGreekMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketGreekMessage.java new file mode 100644 index 0000000..fde28a5 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketGreekMessage.java @@ -0,0 +1,15 @@ +package com.bybit.api.client.domain.websocket_message.private_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebSocketGreekMessage { + private String id; + private String topic; + private Long creationTime; + private List data; // Assuming 'data' is an array of KlineData objects +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketOrderMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketOrderMessage.java new file mode 100644 index 0000000..e983f69 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketOrderMessage.java @@ -0,0 +1,16 @@ +package com.bybit.api.client.domain.websocket_message.private_channel; + +import com.bybit.api.client.domain.websocket_message.public_channel.KlineData; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebSocketOrderMessage { + private String id; + private String topic; + private Long creationTime; + private List data; // Assuming 'data' is an array of KlineData objects +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketPositionMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketPositionMessage.java new file mode 100644 index 0000000..e1e39a9 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketPositionMessage.java @@ -0,0 +1,15 @@ +package com.bybit.api.client.domain.websocket_message.private_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebSocketPositionMessage { + private String id; + private String topic; + private Long creationTime; + private List data; // Assuming 'data' is an array of KlineData objects +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketWalletMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketWalletMessage.java new file mode 100644 index 0000000..9047ede --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/private_channel/WebSocketWalletMessage.java @@ -0,0 +1,15 @@ +package com.bybit.api.client.domain.websocket_message.private_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebSocketWalletMessage { + private String id; + private String topic; + private Long creationTime; + private List data; // Assuming 'data' is an array of KlineData objects +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/KlineData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/KlineData.java new file mode 100644 index 0000000..3e47109 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/KlineData.java @@ -0,0 +1,22 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class KlineData { + private Long start; + private Long end; + private String interval; + private String open; + private String close; + private String high; + private String low; + private String volume; + private String turnover; + private Boolean confirm; + private Long timestamp; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/LiquidationData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/LiquidationData.java new file mode 100644 index 0000000..066d2d2 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/LiquidationData.java @@ -0,0 +1,16 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class LiquidationData { + private Long updateTime; + private String symbol; + private String side; + private String size; + private String price; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/LtKlineData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/LtKlineData.java new file mode 100644 index 0000000..92b9cae --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/LtKlineData.java @@ -0,0 +1,20 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class LtKlineData { + private Long start; + private Long end; + private String interval; + private String open; + private String close; + private String high; + private String low; + private Boolean confirm; + private Long timestamp; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/LtTicketData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/LtTicketData.java new file mode 100644 index 0000000..c327dbe --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/LtTicketData.java @@ -0,0 +1,17 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class LtTicketData { + private String symbol; + private String price24hPcnt; + private String lastPrice; + private String prevPrice24h; + private String highPrice24h; + private String lowPrice24h; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/NavData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/NavData.java new file mode 100644 index 0000000..69570e3 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/NavData.java @@ -0,0 +1,19 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class NavData { + private Long time; + private String symbol; + private String nav; + private String basketPosition; + private String leverage; + private String basketLoan; + private String circulation; + private String basket; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/PublicOrderBookData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/PublicOrderBookData.java new file mode 100644 index 0000000..166b6f7 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/PublicOrderBookData.java @@ -0,0 +1,19 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class PublicOrderBookData { + private String s; // Symbol name + private List> b; // Bids + private List> a; // Asks + private Long u; // Update ID + private Long seq; // Sequence + private Long cts; // Timestamp from the match engine +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/PublicTickerData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/PublicTickerData.java new file mode 100644 index 0000000..591e1bb --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/PublicTickerData.java @@ -0,0 +1,102 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class PublicTickerData { + private String symbol; + private String tickDirection; + private String bidPrice; + private String bidSize; + private String bidIv; + private String askPrice; + private String askSize; + private String askIv; + private String lastPrice; + private String highPrice24h; + private String lowPrice24h; + private String prevPrice24h; + private String volume24h; + private String turnover24h; + private String price24hPcnt; + private String usdIndexPrice; + private String underlyingPrice; + private String markPrice; + private String indexPrice; + private String markPriceIv; + private String openInterest; + private String openInterestValue; + private String totalVolume; + private String totalTurnover; + private String nextFundingTime; + private String fundingRate; + private String bid1Price; + private String bid1Size; + private String ask1Price; + private String ask1Size; + private String delta; // Option + private String gamma; // Option + private String vega; // Option + private String theta; // Option + private String deliveryTime; // Linear and Inverse + private String basisRate; // Linear and Inverse + private String deliveryFeeRate; // Linear and Inverse + private String predictedDeliveryPrice; + private String change24h; + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("PublicTickerData{"); + + if (symbol != null) sb.append("symbol='").append(symbol).append("', "); + if (tickDirection != null) sb.append("tickDirection='").append(tickDirection).append("', "); + if (bidPrice != null) sb.append("bidPrice='").append(bidPrice).append("', "); + if (bidSize != null) sb.append("bidSize='").append(bidSize).append("', "); + if (bidIv != null) sb.append("bidIv='").append(bidIv).append("', "); + if (askPrice != null) sb.append("askPrice='").append(askPrice).append("', "); + if (askSize != null) sb.append("askSize='").append(askSize).append("', "); + if (askIv != null) sb.append("askIv='").append(askIv).append("', "); + if (lastPrice != null) sb.append("lastPrice='").append(lastPrice).append("', "); + if (highPrice24h != null) sb.append("highPrice24h='").append(highPrice24h).append("', "); + if (lowPrice24h != null) sb.append("lowPrice24h='").append(lowPrice24h).append("', "); + if (prevPrice24h != null) sb.append("prevPrice24h='").append(prevPrice24h).append("', "); + if (volume24h != null) sb.append("volume24h='").append(volume24h).append("', "); + if (turnover24h != null) sb.append("turnover24h='").append(turnover24h).append("', "); + if (price24hPcnt != null) sb.append("price24hPcnt='").append(price24hPcnt).append("', "); + if (usdIndexPrice != null) sb.append("usdIndexPrice='").append(usdIndexPrice).append("', "); + if (underlyingPrice != null) sb.append("underlyingPrice='").append(underlyingPrice).append("', "); + if (markPrice != null) sb.append("markPrice='").append(markPrice).append("', "); + if (indexPrice != null) sb.append("indexPrice='").append(indexPrice).append("', "); + if (markPriceIv != null) sb.append("markPriceIv='").append(markPriceIv).append("', "); + if (openInterest != null) sb.append("openInterest='").append(openInterest).append("', "); + if (openInterestValue != null) sb.append("openInterestValue='").append(openInterestValue).append("', "); + if (totalVolume != null) sb.append("totalVolume='").append(totalVolume).append("', "); + if (totalTurnover != null) sb.append("totalTurnover='").append(totalTurnover).append("', "); + if (nextFundingTime != null) sb.append("nextFundingTime='").append(nextFundingTime).append("', "); + if (fundingRate != null) sb.append("fundingRate='").append(fundingRate).append("', "); + if (bid1Price != null) sb.append("bid1Price='").append(bid1Price).append("', "); + if (bid1Size != null) sb.append("bid1Size='").append(bid1Size).append("', "); + if (ask1Price != null) sb.append("ask1Price='").append(ask1Price).append("', "); + if (ask1Size != null) sb.append("ask1Size='").append(ask1Size).append("', "); + if (delta != null) sb.append("delta='").append(delta).append("', "); + if (gamma != null) sb.append("gamma='").append(gamma).append("', "); + if (vega != null) sb.append("vega='").append(vega).append("', "); + if (theta != null) sb.append("theta='").append(theta).append("', "); + if (deliveryTime != null) sb.append("deliveryTime='").append(deliveryTime).append("', "); + if (basisRate != null) sb.append("basisRate='").append(basisRate).append("', "); + if (deliveryFeeRate != null) sb.append("deliveryFeeRate='").append(deliveryFeeRate).append("', "); + if (predictedDeliveryPrice != null) sb.append("predictedDeliveryPrice='").append(predictedDeliveryPrice).append("', "); + if (change24h != null) sb.append("change24h='").append(change24h).append("'"); + + if (sb.length() > "PublicTickerData{".length()) { + sb.setLength(sb.length() - (sb.charAt(sb.length() - 2) == ',' ? 2 : 0)); // Remove last comma and space if present + } + sb.append("}"); + return sb.toString(); + } +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/TradeData.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/TradeData.java new file mode 100644 index 0000000..92a092b --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/TradeData.java @@ -0,0 +1,19 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonIgnoreProperties(ignoreUnknown = true) +public class TradeData { + private Long T; // Timestamp of the order filled + private String s; // Symbol name + private String S; // Side of taker (Buy, Sell) + private String v; // Trade size + private String p; // Trade price + private String L; // Direction of price change + private String i; // Trade ID + private Boolean BT; // Whether it is a block trade order or not +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketKlineMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketKlineMessage.java new file mode 100644 index 0000000..05ad7de --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketKlineMessage.java @@ -0,0 +1,15 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebSocketKlineMessage { + private String topic; + private String type; + private Long ts; + private List data; // Assuming 'data' is an array of KlineData objects +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketLiquidationMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketLiquidationMessage.java new file mode 100644 index 0000000..8db56ea --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketLiquidationMessage.java @@ -0,0 +1,13 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebSocketLiquidationMessage { + private String topic; + private String type; + private Long ts; + private LiquidationData data; // Assuming 'data' is an array of KlineData objects +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketLtKlineMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketLtKlineMessage.java new file mode 100644 index 0000000..5c07baa --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketLtKlineMessage.java @@ -0,0 +1,15 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebSocketLtKlineMessage { + private String topic; + private String type; + private Long ts; + private List data; // Assuming 'data' is an array of LtKlineData objects +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketLtTicketMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketLtTicketMessage.java new file mode 100644 index 0000000..20affcc --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketLtTicketMessage.java @@ -0,0 +1,15 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebSocketLtTicketMessage { + private String topic; + private String type; + private Long ts; + private List data; // Assuming 'data' is an array of LtTicketData objects +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketTickerMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketTickerMessage.java new file mode 100644 index 0000000..6bd485f --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketTickerMessage.java @@ -0,0 +1,14 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebSocketTickerMessage { + private String topic; + private Long ts; + private String type; + private Long cs; + private PublicTickerData data; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketTradeMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketTradeMessage.java new file mode 100644 index 0000000..4a412a1 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebSocketTradeMessage.java @@ -0,0 +1,16 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebSocketTradeMessage { + private String id; + private String topic; + private String type; + private Long ts; + private List data; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebsocketLtNavMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebsocketLtNavMessage.java new file mode 100644 index 0000000..6fb6c9d --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebsocketLtNavMessage.java @@ -0,0 +1,15 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebsocketLtNavMessage { + private String topic; + private String type; + private Long ts; + private List data; +} diff --git a/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebsocketOrderbookMessage.java b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebsocketOrderbookMessage.java new file mode 100644 index 0000000..adf4816 --- /dev/null +++ b/src/main/java/com/bybit/api/client/domain/websocket_message/public_channel/WebsocketOrderbookMessage.java @@ -0,0 +1,13 @@ +package com.bybit.api.client.domain.websocket_message.public_channel; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebsocketOrderbookMessage { + private String topic; + private String type; + private Long ts; + private PublicOrderBookData data; +} diff --git a/src/main/java/com/bybit/api/client/impl/BybitApiAsyncSpotMarginRestClientImpl.java b/src/main/java/com/bybit/api/client/impl/BybitApiAsyncSpotMarginRestClientImpl.java index 09efd45..da98fe5 100644 --- a/src/main/java/com/bybit/api/client/impl/BybitApiAsyncSpotMarginRestClientImpl.java +++ b/src/main/java/com/bybit/api/client/impl/BybitApiAsyncSpotMarginRestClientImpl.java @@ -85,6 +85,7 @@ public void getUTASpotMarginTradeLeverageState(BybitApiCallback callback // Spot Margin Normal @Override + @Deprecated public void getNormalVipSpotMarginTradeData(SpotMarginDataRequest normalMarginDataRequest, BybitApiCallback callback) { bybitApiService.getNormalVipSpotMarginTradeData( normalMarginDataRequest.getVipLevel() == null ? null : normalMarginDataRequest.getVipLevel().getLevel(), @@ -92,45 +93,53 @@ public void getNormalVipSpotMarginTradeData(SpotMarginDataRequest normalMarginDa .enqueue(new BybitApiCallbackAdapter<>(callback)); } + @Deprecated @Override public void getNormalSpotMarginTradeCoinInfo(SpotMarginDataRequest normalMarginDataRequest, BybitApiCallback callback) { bybitApiService.getNormalSpotMarginTradeCoinInfo(normalMarginDataRequest.getCoin()).enqueue(new BybitApiCallbackAdapter<>(callback)); } @Override + @Deprecated public void getNormalSpotMarginTradeBorrowCoinInfo(SpotMarginDataRequest normalMarginDataRequest, BybitApiCallback callback) { bybitApiService.getNormalSpotMarginTradeBorrowCoinInfo(normalMarginDataRequest.getCoin()).enqueue(new BybitApiCallbackAdapter<>(callback)); } @Override + @Deprecated public void getNormalSpotMarginTradeInterestQuota(SpotMarginDataRequest spotMarginDataRequest, BybitApiCallback callback) { bybitApiService.getNormalSpotMarginTradeInterestQuota(spotMarginDataRequest.getCoin()).enqueue(new BybitApiCallbackAdapter<>(callback)); } @Override + @Deprecated public void getNormalSpotMarginTradeAccountInfo(BybitApiCallback callback) { bybitApiService.getNormalSpotMarginTradeAccountInfo().enqueue(new BybitApiCallbackAdapter<>(callback)); } @Override + @Deprecated public void setNormalSpotToggleMarginTrade(SpotMarginDataRequest spotMarginDataRequest, BybitApiCallback callback) { int switchStatus = spotMarginDataRequest.getSwitchStatus() == null ? 0 : spotMarginDataRequest.getSwitchStatus().getValue(); bybitApiService.setNormalSpotToggleMarginTrade(switchStatus).enqueue(new BybitApiCallbackAdapter<>(callback)); } @Override + @Deprecated public void loanNormalSpotMarginTrade(SpotMarginDataRequest spotMarginDataRequest, BybitApiCallback callback) { var spotMarginTradeBorrowRequest = converter.mapToSpotMarginBorrowRequest(spotMarginDataRequest); bybitApiService.loanNormalSpotMarginTrade(spotMarginTradeBorrowRequest).enqueue(new BybitApiCallbackAdapter<>(callback)); } @Override + @Deprecated public void repayNormalSpotMarginTrade(SpotMarginDataRequest spotMarginDataRequest, BybitApiCallback callback) { var spotMarginTradeRePayRequest = converter.mapToSpotMarginRepayRequest(spotMarginDataRequest); bybitApiService.repayNormalSpotMarginTrade(spotMarginTradeRePayRequest).enqueue(new BybitApiCallbackAdapter<>(callback)); } @Override + @Deprecated public void getNormalSpotMarginTradeBorrowOrders(SpotMarginDataRequest spotMarginTradeBorrowOrdersRequest, BybitApiCallback callback) { bybitApiService.getNormalMarginTradeBorrowOrders( spotMarginTradeBorrowOrdersRequest.getStartTime(), @@ -142,6 +151,7 @@ public void getNormalSpotMarginTradeBorrowOrders(SpotMarginDataRequest spotMargi } @Override + @Deprecated public void getNormalSpotMarginTradeRepayOrders(SpotMarginDataRequest spotMarginTradeRepayOrdersRequest, BybitApiCallback callback) { bybitApiService.getNormalMarginTradeRepayOrders( spotMarginTradeRepayOrdersRequest.getStartTime(), diff --git a/src/main/java/com/bybit/api/client/impl/BybitApiSpotMarginRestClientImpl.java b/src/main/java/com/bybit/api/client/impl/BybitApiSpotMarginRestClientImpl.java index 719eecb..7b45377 100644 --- a/src/main/java/com/bybit/api/client/impl/BybitApiSpotMarginRestClientImpl.java +++ b/src/main/java/com/bybit/api/client/impl/BybitApiSpotMarginRestClientImpl.java @@ -83,6 +83,7 @@ public Object getUTASpotMarginTradeLeverageState() { } // Spot Margin Normal + @Deprecated @Override public Object getNormalVipSpotMarginTradeData(SpotMarginDataRequest normalMarginDataRequest) { return executeSync(bybitApiService.getNormalVipSpotMarginTradeData( @@ -91,44 +92,52 @@ public Object getNormalVipSpotMarginTradeData(SpotMarginDataRequest normalMargin ); } + @Deprecated @Override public Object getNormalSpotMarginTradeCoinInfo(SpotMarginDataRequest normalMarginDataRequest) { return executeSync(bybitApiService.getNormalSpotMarginTradeCoinInfo(normalMarginDataRequest.getCoin())); } + @Deprecated @Override public Object getNormalSpotMarginTradeBorrowCoinInfo(SpotMarginDataRequest normalMarginDataRequest) { return executeSync(bybitApiService.getNormalSpotMarginTradeBorrowCoinInfo(normalMarginDataRequest.getCoin())); } + @Deprecated @Override public Object getNormalSpotMarginTradeInterestQuota(SpotMarginDataRequest spotMarginDataRequest) { return executeSync(bybitApiService.getNormalSpotMarginTradeInterestQuota(spotMarginDataRequest.getCoin())); } + @Deprecated @Override public Object getNormalSpotMarginTradeAccountInfo() { return executeSync(bybitApiService.getNormalSpotMarginTradeAccountInfo()); } + @Deprecated @Override public Object setNormalSpotToggleMarginTrade(SpotMarginDataRequest spotMarginDataRequest) { int switchStatus = spotMarginDataRequest.getSwitchStatus() == null ? 0 : spotMarginDataRequest.getSwitchStatus().getValue(); return executeSync(bybitApiService.setNormalSpotToggleMarginTrade(switchStatus)); } + @Deprecated @Override public Object loanNormalSpotMarginTrade(SpotMarginDataRequest spotMarginDataRequest) { var spotMarginTradeBorrowRequest = converter.mapToSpotMarginBorrowRequest(spotMarginDataRequest); return executeSync(bybitApiService.loanNormalSpotMarginTrade(spotMarginTradeBorrowRequest)); } + @Deprecated @Override public Object repayNormalSpotMarginTrade(SpotMarginDataRequest spotMarginDataRequest) { var spotMarginTradeRePayRequest = converter.mapToSpotMarginRepayRequest(spotMarginDataRequest); return executeSync(bybitApiService.repayNormalSpotMarginTrade(spotMarginTradeRePayRequest)); } + @Deprecated @Override public Object getNormalSpotMarginTradeBorrowOrders(SpotMarginDataRequest spotMarginTradeBorrowOrdersRequest) { return executeSync(bybitApiService.getNormalMarginTradeBorrowOrders( @@ -140,6 +149,7 @@ public Object getNormalSpotMarginTradeBorrowOrders(SpotMarginDataRequest spotMar )); } + @Deprecated @Override public Object getNormalSpotMarginTradeRepayOrders(SpotMarginDataRequest spotMarginTradeRepayOrdersRequest) { return executeSync(bybitApiService.getNormalMarginTradeRepayOrders( diff --git a/src/main/java/com/bybit/api/client/restApi/BybitApiService.java b/src/main/java/com/bybit/api/client/restApi/BybitApiService.java index 2d6561e..327ba74 100644 --- a/src/main/java/com/bybit/api/client/restApi/BybitApiService.java +++ b/src/main/java/com/bybit/api/client/restApi/BybitApiService.java @@ -4412,6 +4412,7 @@ Call getUtaVipSpotMarginTradeData(@Query("vipLevel") String vipLevel, * > > maxBorrowingAmount string Max borrow amount * > vipLevel string Vip level */ + @Deprecated @Headers(BybitApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @GET("/v5/spot-cross-margin-trade/data") Call getNormalVipSpotMarginTradeData(@Query("vipLevel") String vipLevel, @@ -4432,6 +4433,7 @@ Call getNormalVipSpotMarginTradeData(@Query("vipLevel") String vipLevel, * > conversionRate string Convert ratio * > liquidationOrder integer Liquidation order */ + @Deprecated @Headers(BybitApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @GET("/v5/spot-cross-margin-trade/pledge-token") Call getNormalSpotMarginTradeCoinInfo(@Query("coin") String coin); @@ -4454,6 +4456,7 @@ Call getNormalVipSpotMarginTradeData(@Query("vipLevel") String vipLevel, * > borrowingPrecision integer Accuracy of loan amount * > repaymentPrecision integer Accuracy of repayment amount */ + @Deprecated @Headers(BybitApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @GET("/v5/spot-cross-margin-trade/borrow-token") Call getNormalSpotMarginTradeBorrowCoinInfo(@Query("coin") String coin); @@ -4472,6 +4475,7 @@ Call getNormalVipSpotMarginTradeData(@Query("vipLevel") String vipLevel, * loanAbleAmount string The estimated amount can be loaned * maxLoanAmount string The fixed loanable amount per user on platform */ + @Deprecated @Headers(BybitApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @GET("/v5/spot-cross-margin-trade/loan-info") Call getNormalSpotMarginTradeInterestQuota(@Query("coin") String coin); @@ -4502,6 +4506,7 @@ Call getNormalVipSpotMarginTradeData(@Query("vipLevel") String vipLevel, * 4: liquidated * switchStatus integer 0: margin trade off, 1: margin trade on */ + @Deprecated @Headers(BybitApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @GET("/v5/spot-cross-margin-trade/account") Call getNormalSpotMarginTradeAccountInfo(); @@ -4519,6 +4524,7 @@ Call getNormalVipSpotMarginTradeData(@Query("vipLevel") String vipLevel, * Parameter Type Comments * switchStatus integer Margin trade status. 1: on, 0: off */ + @Deprecated @Headers(BybitApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @POST("/v5/spot-cross-margin-trade/switch") Call setNormalSpotToggleMarginTrade(@Body int switchStatus); @@ -4535,6 +4541,7 @@ Call getNormalVipSpotMarginTradeData(@Query("vipLevel") String vipLevel, * Parameter Type Comments * transactId string Borrow transaction ID */ + @Deprecated @Headers(BybitApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @POST("/v5/spot-cross-margin-trade/loan") Call loanNormalSpotMarginTrade(@Body SpotMarginTradeBorrowRequest spotMarginTradeBorrowRequest); @@ -4554,6 +4561,7 @@ Call getNormalVipSpotMarginTradeData(@Query("vipLevel") String vipLevel, * Parameter Type Comments * repayId string Repayment transaction ID */ + @Deprecated @Headers(BybitApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @POST("/v5/spot-cross-margin-trade/repay") Call repayNormalSpotMarginTrade(@Body SpotMarginTradeRePayRequest spotMarginTradeRePayRequest); @@ -4587,6 +4595,7 @@ Call getNormalVipSpotMarginTradeData(@Query("vipLevel") String vipLevel, * > status integer Status 1:uncleared, 2:cleared * > type integer Order Type 1: manual loan, 2: auto loan */ + @Deprecated @Headers(BybitApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @GET("/v5/spot-cross-margin-trade/orders") Call getNormalMarginTradeBorrowOrders(@Query("startTime") Long startTime, @@ -4620,6 +4629,7 @@ Call getNormalMarginTradeBorrowOrders(@Query("startTime") Long startTime * > > repaidSerialNumber string Repayment No. (Borrowing Order) * > > transactId string Borrowing transaction ID */ + @Deprecated @Headers(BybitApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @GET("/v5/spot-cross-margin-trade/repay-history") Call getNormalMarginTradeRepayOrders(@Query("startTime") Long startTime, diff --git a/src/main/java/com/bybit/api/client/websocket/WebsocketClient.java b/src/main/java/com/bybit/api/client/websocket/WebsocketClient.java index 0554750..5121532 100644 --- a/src/main/java/com/bybit/api/client/websocket/WebsocketClient.java +++ b/src/main/java/com/bybit/api/client/websocket/WebsocketClient.java @@ -1,11 +1,12 @@ package com.bybit.api.client.websocket; +import com.fasterxml.jackson.core.JsonProcessingException; import okhttp3.WebSocket; import java.util.List; public interface WebsocketClient { - void onMessage(String msg); + void onMessage(String msg) throws JsonProcessingException; void onError(Throwable t); void onClose(int code, String reason); void onOpen(WebSocket ws); @@ -44,6 +45,8 @@ public interface WebsocketClient { */ void getPublicChannelStream(List argNames, String path); void getPrivateChannelStream(List argNames, String path); + + void setMessageHandler(WebsocketMessageHandler websocketMessageHandler); /** * Trade * Subscribe to the recent trades stream. diff --git a/src/main/java/com/bybit/api/client/websocket/WebsocketClientImpl.java b/src/main/java/com/bybit/api/client/websocket/WebsocketClientImpl.java index 98f37e9..06568d6 100644 --- a/src/main/java/com/bybit/api/client/websocket/WebsocketClientImpl.java +++ b/src/main/java/com/bybit/api/client/websocket/WebsocketClientImpl.java @@ -28,7 +28,7 @@ public class WebsocketClientImpl implements WebsocketClient { private static final Logger LOGGER = LoggerFactory.getLogger(WebsocketClientImpl.class); private static final ObjectMapper objectMapper = new ObjectMapper(); - private final WebsocketMessageHandler messageHandler; + private WebsocketMessageHandler messageHandler; private final WebSocketHttpClientSingleton webSocketHttpClientSingleton; private final String apikey; @@ -176,7 +176,11 @@ public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nulla @Override public void onMessage(@NotNull WebSocket webSocket, @NotNull String text) { - WebsocketClientImpl.this.onMessage(text); + try { + WebsocketClientImpl.this.onMessage(text); + } catch (Exception e) { + WebsocketClientImpl.this.onError(e); + } } @Override @@ -186,8 +190,12 @@ public void onOpen(@NotNull WebSocket webSocket, @NotNull Response response) { }; } + public void setMessageHandler(WebsocketMessageHandler handler) { + this.messageHandler = handler; + } + @Override - public void onMessage(String msg) { + public void onMessage(String msg) throws JsonProcessingException { if (messageHandler != null) { messageHandler.handleMessage(msg); } else { diff --git a/src/main/java/com/bybit/api/client/websocket/WebsocketMessage.java b/src/main/java/com/bybit/api/client/websocket/WebsocketMessage.java new file mode 100644 index 0000000..3bb1683 --- /dev/null +++ b/src/main/java/com/bybit/api/client/websocket/WebsocketMessage.java @@ -0,0 +1,10 @@ +package com.bybit.api.client.websocket; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Data; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class WebsocketMessage { + private Object websocketMessage; +} diff --git a/src/main/java/com/bybit/api/client/websocket/WebsocketMessageHandler.java b/src/main/java/com/bybit/api/client/websocket/WebsocketMessageHandler.java index f51252f..a06987e 100644 --- a/src/main/java/com/bybit/api/client/websocket/WebsocketMessageHandler.java +++ b/src/main/java/com/bybit/api/client/websocket/WebsocketMessageHandler.java @@ -1,6 +1,8 @@ -package com.bybit.api.client.websocket; - -@FunctionalInterface -public interface WebsocketMessageHandler { - void handleMessage(String message); -} +package com.bybit.api.client.websocket; + +import com.fasterxml.jackson.core.JsonProcessingException; + +@FunctionalInterface +public interface WebsocketMessageHandler { + void handleMessage(String message) throws JsonProcessingException; +} diff --git a/src/test/java/com/bybit/api/examples/Websocket/WebsocketPrivateChannelExamples.java b/src/test/java/com/bybit/api/examples/Websocket/WebsocketPrivateChannelExamples.java index 2839f09..a4a6bf7 100644 --- a/src/test/java/com/bybit/api/examples/Websocket/WebsocketPrivateChannelExamples.java +++ b/src/test/java/com/bybit/api/examples/Websocket/WebsocketPrivateChannelExamples.java @@ -7,11 +7,11 @@ public class WebsocketPrivateChannelExamples { public static void main(String[] args) { - var client = BybitApiClientFactory.newInstance("8wYkmpLsMg10eNQyPm", "Ouxc34myDnXvei54XsBZgoQzfGxO4bkr2Zsj", BybitApiConfig.STREAM_TESTNET_DOMAIN, true).newWebsocketClient(5, "60s", (message) -> System.out.println("Handle message :" + message)); + var client = BybitApiClientFactory.newInstance("YOUR_API_KEY", "YOUR_API_SECRET", BybitApiConfig.STREAM_TESTNET_DOMAIN, true).newWebsocketClient(5, "60s", (message) -> System.out.println("Handle message :" + message)); // Position - // client.getOrderBookStream(List.of("position.linear"), BybitApiConfig.V5_PRIVATE); + // client.getPrivateChannelStream(List.of("position"), BybitApiConfig.V5_PRIVATE); // Order - client.getPrivateChannelStream(List.of("execution"), BybitApiConfig.V5_PRIVATE); + client.getPrivateChannelStream(List.of("order"), BybitApiConfig.V5_PRIVATE); } } diff --git a/src/test/java/com/bybit/api/examples/Websocket/WebsocketPublicChannelExamples.java b/src/test/java/com/bybit/api/examples/Websocket/WebsocketPublicChannelExamples.java index 4615076..b5795fa 100644 --- a/src/test/java/com/bybit/api/examples/Websocket/WebsocketPublicChannelExamples.java +++ b/src/test/java/com/bybit/api/examples/Websocket/WebsocketPublicChannelExamples.java @@ -8,8 +8,13 @@ public class WebsocketPublicChannelExamples { public static void main(String[] args) { var client = BybitApiClientFactory.newInstance(BybitApiConfig.STREAM_MAINNET_DOMAIN, true).newWebsocketClient(); + client.setMessageHandler(message -> { + // Process message data here + System.out.println("Websocket Message Data: " + message); + }); + // Subscribe Orderbook more than one args - client.getPublicChannelStream(List.of("orderbook.25.BTC-23FEB24-51000-P"), BybitApiConfig.V5_PUBLIC_OPTION); + //client.getPublicChannelStream(List.of("orderbook.25.BTC-23FEB24-51000-P"), BybitApiConfig.V5_PUBLIC_OPTION); // Orderbook // client.getPublicChannelStream(List.of("orderbook.50.BTCUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); @@ -17,7 +22,7 @@ public static void main(String[] args) { // client.getPublicChannelStream(List.of("publicTrade.BTCUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); // Ticker - // client.getPublicChannelStream(List.of("tickers.BTCUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); + client.getPublicChannelStream(List.of("tickers.BTCUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); // Kline // client.getPublicChannelStream(List.of("kline.D.BTCUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); diff --git a/src/test/java/com/bybit/api/websocket/KlineChannelMessageHandler.java b/src/test/java/com/bybit/api/websocket/KlineChannelMessageHandler.java new file mode 100644 index 0000000..706de4c --- /dev/null +++ b/src/test/java/com/bybit/api/websocket/KlineChannelMessageHandler.java @@ -0,0 +1,24 @@ +package com.bybit.api.websocket; + +import com.bybit.api.client.config.BybitApiConfig; +import com.bybit.api.client.domain.websocket_message.public_channel.WebSocketKlineMessage; +import com.bybit.api.client.domain.websocket_message.public_channel.WebSocketTradeMessage; +import com.bybit.api.client.service.BybitApiClientFactory; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.List; + +public class KlineChannelMessageHandler { + public static void main(String[] args) { + var client = BybitApiClientFactory.newInstance(BybitApiConfig.STREAM_MAINNET_DOMAIN, true).newWebsocketClient(); + + client.setMessageHandler(message -> { + var klineData = (new ObjectMapper()).readValue(message, WebSocketKlineMessage.class); + // Process message data here + System.out.println("Websocket Message Data: " + klineData.getData().toString()); + }); + + // Kline + client.getPublicChannelStream(List.of("kline.D.BTCUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); + } +} diff --git a/src/test/java/com/bybit/api/websocket/LiquidationChannelMessageHandler.java b/src/test/java/com/bybit/api/websocket/LiquidationChannelMessageHandler.java new file mode 100644 index 0000000..aac2d5d --- /dev/null +++ b/src/test/java/com/bybit/api/websocket/LiquidationChannelMessageHandler.java @@ -0,0 +1,23 @@ +package com.bybit.api.websocket; + +import com.bybit.api.client.config.BybitApiConfig; +import com.bybit.api.client.domain.websocket_message.public_channel.WebSocketLiquidationMessage; +import com.bybit.api.client.service.BybitApiClientFactory; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.List; + +public class LiquidationChannelMessageHandler { + public static void main(String[] args) { + var client = BybitApiClientFactory.newInstance(BybitApiConfig.STREAM_MAINNET_DOMAIN, true).newWebsocketClient(); + + client.setMessageHandler(message -> { + var liquidationData = (new ObjectMapper()).readValue(message, WebSocketLiquidationMessage.class); + // Process message data here + System.out.println("Websocket Message Data: " + liquidationData.getData().toString()); + }); + + // Liquidation + client.getPublicChannelStream(List.of("liquidation.BTCUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); + } +} diff --git a/src/test/java/com/bybit/api/websocket/OrderBookChannelMessageHandler.java b/src/test/java/com/bybit/api/websocket/OrderBookChannelMessageHandler.java new file mode 100644 index 0000000..99c91d7 --- /dev/null +++ b/src/test/java/com/bybit/api/websocket/OrderBookChannelMessageHandler.java @@ -0,0 +1,23 @@ +package com.bybit.api.websocket; + +import com.bybit.api.client.config.BybitApiConfig; +import com.bybit.api.client.domain.websocket_message.public_channel.WebsocketOrderbookMessage; +import com.bybit.api.client.service.BybitApiClientFactory; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.List; + +public class OrderBookChannelMessageHandler { + public static void main(String[] args) { + var client = BybitApiClientFactory.newInstance(BybitApiConfig.STREAM_MAINNET_DOMAIN, true).newWebsocketClient(); + + client.setMessageHandler(message -> { + var orderbookMessage = (new ObjectMapper()).readValue(message, WebsocketOrderbookMessage.class); + // Process message data here + System.out.println("Websocket Message Data: " + orderbookMessage.getData().toString()); + }); + + // Order book + client.getPublicChannelStream(List.of("orderbook.50.BTCUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); + } +} diff --git a/src/test/java/com/bybit/api/websocket/OrderChannelMessageHandler.java b/src/test/java/com/bybit/api/websocket/OrderChannelMessageHandler.java new file mode 100644 index 0000000..b6bb970 --- /dev/null +++ b/src/test/java/com/bybit/api/websocket/OrderChannelMessageHandler.java @@ -0,0 +1,22 @@ +package com.bybit.api.websocket; + +import com.bybit.api.client.config.BybitApiConfig; +import com.bybit.api.client.domain.websocket_message.private_channel.WebSocketOrderMessage; +import com.bybit.api.client.service.BybitApiClientFactory; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.List; + +public class OrderChannelMessageHandler { + public static void main(String[] args) { + var client = BybitApiClientFactory.newInstance("YOUR_API_KEY", "YOUR_API_SECRET", BybitApiConfig.STREAM_TESTNET_DOMAIN, true) + .newWebsocketClient(5, "60s", (message) -> { + var orderMessage = (new ObjectMapper()).readValue(message, WebSocketOrderMessage.class); + // Process message data here + System.out.println("Websocket Message Data: " + orderMessage.getData().toString()); + }); + + // Order + client.getPrivateChannelStream(List.of("order"), BybitApiConfig.V5_PRIVATE); + } +} diff --git a/src/test/java/com/bybit/api/websocket/TickerChannelMessageHandler.java b/src/test/java/com/bybit/api/websocket/TickerChannelMessageHandler.java new file mode 100644 index 0000000..1745496 --- /dev/null +++ b/src/test/java/com/bybit/api/websocket/TickerChannelMessageHandler.java @@ -0,0 +1,23 @@ +package com.bybit.api.websocket; + +import com.bybit.api.client.config.BybitApiConfig; +import com.bybit.api.client.domain.websocket_message.public_channel.WebSocketTickerMessage; +import com.bybit.api.client.service.BybitApiClientFactory; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.List; + +public class TickerChannelMessageHandler { + public static void main(String[] args) { + var client = BybitApiClientFactory.newInstance(BybitApiConfig.STREAM_MAINNET_DOMAIN, true).newWebsocketClient(); + + client.setMessageHandler(message -> { + var tickerData = (new ObjectMapper()).readValue(message, WebSocketTickerMessage.class); + // Process message data here + System.out.println("Websocket Message Data: " + tickerData.getData().toString()); + }); + + // Ticker + client.getPublicChannelStream(List.of("tickers.BTCUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); + } +} diff --git a/src/test/java/com/bybit/api/websocket/TradeChannelMessageHandler.java b/src/test/java/com/bybit/api/websocket/TradeChannelMessageHandler.java new file mode 100644 index 0000000..86bc635 --- /dev/null +++ b/src/test/java/com/bybit/api/websocket/TradeChannelMessageHandler.java @@ -0,0 +1,24 @@ +package com.bybit.api.websocket; + +import com.bybit.api.client.config.BybitApiConfig; +import com.bybit.api.client.domain.websocket_message.public_channel.WebSocketTickerMessage; +import com.bybit.api.client.domain.websocket_message.public_channel.WebSocketTradeMessage; +import com.bybit.api.client.service.BybitApiClientFactory; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.List; + +public class TradeChannelMessageHandler { + public static void main(String[] args) { + var client = BybitApiClientFactory.newInstance(BybitApiConfig.STREAM_MAINNET_DOMAIN, true).newWebsocketClient(); + + client.setMessageHandler(message -> { + var tradeData = (new ObjectMapper()).readValue(message, WebSocketTradeMessage.class); + // Process message data here + System.out.println("Websocket Message Data: " + tradeData.getData().toString()); + }); + + // Trade + client.getPublicChannelStream(List.of("publicTrade.BTCUSDT"), BybitApiConfig.V5_PUBLIC_LINEAR); + } +}