From 97a08b04196588a7a357518a7cf55a0adef757d9 Mon Sep 17 00:00:00 2001 From: Nils Wiersema Date: Wed, 25 Apr 2018 23:04:26 +0200 Subject: [PATCH 1/6] Route exceptions via onFailure callback rather than throwing them --- .../api/client/impl/BinanceApiCallbackAdapter.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/binance/api/client/impl/BinanceApiCallbackAdapter.java b/src/main/java/com/binance/api/client/impl/BinanceApiCallbackAdapter.java index 6ec5a3614..10b896ac6 100644 --- a/src/main/java/com/binance/api/client/impl/BinanceApiCallbackAdapter.java +++ b/src/main/java/com/binance/api/client/impl/BinanceApiCallbackAdapter.java @@ -33,15 +33,19 @@ public void onResponse(Call call, Response response) { } try { BinanceApiError apiError = getBinanceApiError(response); - throw new BinanceApiException(apiError); + onFailure(call, new BinanceApiException(apiError)); } catch (IOException e) { - throw new BinanceApiException(e); + onFailure(call, new BinanceApiException(e)); } } } @Override public void onFailure(Call call, Throwable throwable) { - throw new BinanceApiException(throwable); + if (throwable instanceof BinanceApiException) { + callback.onFailure(throwable); + } else { + callback.onFailure(new BinanceApiException(throwable)); + } } } From 1c90686d4e915c3e6ab67b27ebcdb524776817c3 Mon Sep 17 00:00:00 2001 From: Nils Wiersema Date: Sun, 29 Apr 2018 20:06:49 +0200 Subject: [PATCH 2/6] Add support for newOrderRespType (v3 API) --- .../api/client/domain/account/NewOrder.java | 16 ++++ .../domain/account/NewOrderResponse.java | 84 +++++++++++++++++++ .../domain/account/NewOrderResponseType.java | 12 +++ .../impl/BinanceApiAsyncRestClientImpl.java | 4 +- .../client/impl/BinanceApiRestClientImpl.java | 4 +- .../api/client/impl/BinanceApiService.java | 7 +- 6 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/binance/api/client/domain/account/NewOrderResponseType.java diff --git a/src/main/java/com/binance/api/client/domain/account/NewOrder.java b/src/main/java/com/binance/api/client/domain/account/NewOrder.java index af76a78b2..635e1ddac 100644 --- a/src/main/java/com/binance/api/client/domain/account/NewOrder.java +++ b/src/main/java/com/binance/api/client/domain/account/NewOrder.java @@ -56,6 +56,11 @@ public class NewOrder { */ private String icebergQty; + /** + * Set the response JSON. ACK, RESULT, or FULL; default: RESULT. + */ + private NewOrderResponseType newOrderRespType; + /** * Receiving window. */ @@ -75,6 +80,7 @@ public NewOrder(String symbol, OrderSide side, OrderType type, TimeInForce timeI this.type = type; this.timeInForce = timeInForce; this.quantity = quantity; + this.newOrderRespType = NewOrderResponseType.RESULT; this.timestamp = System.currentTimeMillis(); this.recvWindow = BinanceApiConstants.DEFAULT_RECEIVING_WINDOW; } @@ -168,6 +174,15 @@ public NewOrder icebergQty(String icebergQty) { return this; } + public NewOrderResponseType getNewOrderRespType() { + return newOrderRespType; + } + + public NewOrder newOrderRespType(NewOrderResponseType newOrderRespType) { + this.newOrderRespType = newOrderRespType; + return this; + } + public Long getRecvWindow() { return recvWindow; } @@ -234,6 +249,7 @@ public String toString() { .append("newClientOrderId", newClientOrderId) .append("stopPrice", stopPrice) .append("icebergQty", icebergQty) + .append("newOrderRespType", newOrderRespType) .append("recvWindow", recvWindow) .append("timestamp", timestamp) .toString(); diff --git a/src/main/java/com/binance/api/client/domain/account/NewOrderResponse.java b/src/main/java/com/binance/api/client/domain/account/NewOrderResponse.java index 7485f175e..c42246057 100644 --- a/src/main/java/com/binance/api/client/domain/account/NewOrderResponse.java +++ b/src/main/java/com/binance/api/client/domain/account/NewOrderResponse.java @@ -1,9 +1,16 @@ package com.binance.api.client.domain.account; import com.binance.api.client.constant.BinanceApiConstants; +import com.binance.api.client.domain.OrderSide; +import com.binance.api.client.domain.OrderStatus; +import com.binance.api.client.domain.OrderType; +import com.binance.api.client.domain.TimeInForce; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.apache.commons.lang3.builder.ToStringBuilder; +import java.util.List; +import java.util.stream.Collectors; + /** * Response returned when placing a new order on the system. * @@ -28,6 +35,20 @@ public class NewOrderResponse { */ private String clientOrderId; + private String price; + + private String executedQty; + + private OrderStatus status; + + private TimeInForce timeInForce; + + private OrderType type; + + private OrderSide side; + + private List fills; + /** * Transact time for this order. */ @@ -65,6 +86,62 @@ public void setTransactTime(Long transactTime) { this.transactTime = transactTime; } + public String getPrice() { + return price; + } + + public void setPrice(String price) { + this.price = price; + } + + public String getExecutedQty() { + return executedQty; + } + + public void setExecutedQty(String executedQty) { + this.executedQty = executedQty; + } + + public OrderStatus getStatus() { + return status; + } + + public void setStatus(OrderStatus status) { + this.status = status; + } + + public TimeInForce getTimeInForce() { + return timeInForce; + } + + public void setTimeInForce(TimeInForce timeInForce) { + this.timeInForce = timeInForce; + } + + public OrderType getType() { + return type; + } + + public void setType(OrderType type) { + this.type = type; + } + + public OrderSide getSide() { + return side; + } + + public void setSide(OrderSide side) { + this.side = side; + } + + public List getFills() { + return fills; + } + + public void setFills(List fills) { + this.fills = fills; + } + @Override public String toString() { return new ToStringBuilder(this, BinanceApiConstants.TO_STRING_BUILDER_STYLE) @@ -72,6 +149,13 @@ public String toString() { .append("orderId", orderId) .append("clientOrderId", clientOrderId) .append("transactTime", transactTime) + .append("price", price) + .append("executedQty", executedQty) + .append("status", status) + .append("timeInForce", timeInForce) + .append("type", type) + .append("side", side) + .append("fills", fills.stream().map(Object::toString).collect(Collectors.joining(", "))) .toString(); } } diff --git a/src/main/java/com/binance/api/client/domain/account/NewOrderResponseType.java b/src/main/java/com/binance/api/client/domain/account/NewOrderResponseType.java new file mode 100644 index 000000000..c465f85a7 --- /dev/null +++ b/src/main/java/com/binance/api/client/domain/account/NewOrderResponseType.java @@ -0,0 +1,12 @@ +package com.binance.api.client.domain.account; + +/** + * Desired response type of NewOrder requests. + * @see NewOrderResponse + */ +public enum NewOrderResponseType { + ACK, + RESULT, + FULL +} + diff --git a/src/main/java/com/binance/api/client/impl/BinanceApiAsyncRestClientImpl.java b/src/main/java/com/binance/api/client/impl/BinanceApiAsyncRestClientImpl.java index 5f97af80c..e35a29e85 100644 --- a/src/main/java/com/binance/api/client/impl/BinanceApiAsyncRestClientImpl.java +++ b/src/main/java/com/binance/api/client/impl/BinanceApiAsyncRestClientImpl.java @@ -132,14 +132,14 @@ public void getBookTickers(BinanceApiCallback> callback) { public void newOrder(NewOrder order, BinanceApiCallback callback) { binanceApiService.newOrder(order.getSymbol(), order.getSide(), order.getType(), order.getTimeInForce(), order.getQuantity(), order.getPrice(), order.getNewClientOrderId(), order.getStopPrice(), - order.getIcebergQty(), order.getRecvWindow(), order.getTimestamp()).enqueue(new BinanceApiCallbackAdapter<>(callback)); + order.getIcebergQty(), order.getNewOrderRespType(), order.getRecvWindow(), order.getTimestamp()).enqueue(new BinanceApiCallbackAdapter<>(callback)); } @Override public void newOrderTest(NewOrder order, BinanceApiCallback callback) { binanceApiService.newOrderTest(order.getSymbol(), order.getSide(), order.getType(), order.getTimeInForce(), order.getQuantity(), order.getPrice(), order.getNewClientOrderId(), order.getStopPrice(), - order.getIcebergQty(), order.getRecvWindow(), order.getTimestamp()).enqueue(new BinanceApiCallbackAdapter<>(callback)); + order.getIcebergQty(), order.getNewOrderRespType(), order.getRecvWindow(), order.getTimestamp()).enqueue(new BinanceApiCallbackAdapter<>(callback)); } // Account endpoints diff --git a/src/main/java/com/binance/api/client/impl/BinanceApiRestClientImpl.java b/src/main/java/com/binance/api/client/impl/BinanceApiRestClientImpl.java index 301a08aab..364f48a58 100644 --- a/src/main/java/com/binance/api/client/impl/BinanceApiRestClientImpl.java +++ b/src/main/java/com/binance/api/client/impl/BinanceApiRestClientImpl.java @@ -129,14 +129,14 @@ public List getBookTickers() { public NewOrderResponse newOrder(NewOrder order) { return executeSync(binanceApiService.newOrder(order.getSymbol(), order.getSide(), order.getType(), order.getTimeInForce(), order.getQuantity(), order.getPrice(), order.getNewClientOrderId(), order.getStopPrice(), - order.getIcebergQty(), order.getRecvWindow(), order.getTimestamp())); + order.getIcebergQty(), order.getNewOrderRespType(), order.getRecvWindow(), order.getTimestamp())); } @Override public void newOrderTest(NewOrder order) { executeSync(binanceApiService.newOrderTest(order.getSymbol(), order.getSide(), order.getType(), order.getTimeInForce(), order.getQuantity(), order.getPrice(), order.getNewClientOrderId(), order.getStopPrice(), - order.getIcebergQty(), order.getRecvWindow(), order.getTimestamp())); + order.getIcebergQty(), order.getNewOrderRespType(), order.getRecvWindow(), order.getTimestamp())); } // Account endpoints diff --git a/src/main/java/com/binance/api/client/impl/BinanceApiService.java b/src/main/java/com/binance/api/client/impl/BinanceApiService.java index 5d7921df8..37b4cc881 100644 --- a/src/main/java/com/binance/api/client/impl/BinanceApiService.java +++ b/src/main/java/com/binance/api/client/impl/BinanceApiService.java @@ -8,6 +8,7 @@ import com.binance.api.client.domain.account.DepositAddress; import com.binance.api.client.domain.account.DepositHistory; import com.binance.api.client.domain.account.NewOrderResponse; +import com.binance.api.client.domain.account.NewOrderResponseType; import com.binance.api.client.domain.account.Order; import com.binance.api.client.domain.account.Trade; import com.binance.api.client.domain.account.TradeHistoryItem; @@ -94,14 +95,16 @@ Call> getCandlestickBars(@Query("symbol") String symbol, @Quer Call newOrder(@Query("symbol") String symbol, @Query("side") OrderSide side, @Query("type") OrderType type, @Query("timeInForce") TimeInForce timeInForce, @Query("quantity") String quantity, @Query("price") String price, @Query("newClientOrderId") String newClientOrderId, @Query("stopPrice") String stopPrice, - @Query("icebergQty") String icebergQty, @Query("recvWindow") Long recvWindow, @Query("timestamp") Long timestamp); + @Query("icebergQty") String icebergQty, @Query("newOrderRespType") NewOrderResponseType newOrderRespType, + @Query("recvWindow") Long recvWindow, @Query("timestamp") Long timestamp); @Headers(BinanceApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @POST("/api/v3/order/test") Call newOrderTest(@Query("symbol") String symbol, @Query("side") OrderSide side, @Query("type") OrderType type, @Query("timeInForce") TimeInForce timeInForce, @Query("quantity") String quantity, @Query("price") String price, @Query("newClientOrderId") String newClientOrderId, @Query("stopPrice") String stopPrice, - @Query("icebergQty") String icebergQty, @Query("recvWindow") Long recvWindow, @Query("timestamp") Long timestamp); + @Query("icebergQty") String icebergQty, @Query("newOrderRespType") NewOrderResponseType newOrderRespType, + @Query("recvWindow") Long recvWindow, @Query("timestamp") Long timestamp); @Headers(BinanceApiConstants.ENDPOINT_SECURITY_TYPE_SIGNED_HEADER) @GET("/api/v3/order") From 7b92e7a40f13c7a77710fc894d1eca354a5580dd Mon Sep 17 00:00:00 2001 From: Nils Wiersema Date: Sun, 29 Apr 2018 20:11:33 +0200 Subject: [PATCH 3/6] Demonstrate use of newOrderRespType in OrdersExample --- src/test/java/com/binance/api/examples/OrdersExample.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/binance/api/examples/OrdersExample.java b/src/test/java/com/binance/api/examples/OrdersExample.java index 0b8be5256..c133e7432 100644 --- a/src/test/java/com/binance/api/examples/OrdersExample.java +++ b/src/test/java/com/binance/api/examples/OrdersExample.java @@ -4,6 +4,7 @@ import com.binance.api.client.BinanceApiRestClient; import com.binance.api.client.domain.TimeInForce; import com.binance.api.client.domain.account.NewOrderResponse; +import com.binance.api.client.domain.account.NewOrderResponseType; import com.binance.api.client.domain.account.Order; import com.binance.api.client.domain.account.request.AllOrdersRequest; import com.binance.api.client.domain.account.request.CancelOrderRequest; @@ -51,7 +52,7 @@ public static void main(String[] args) { client.newOrderTest(marketBuy("LINKETH", "1000")); // Placing a real LIMIT order - NewOrderResponse newOrderResponse = client.newOrder(limitBuy("LINKETH", TimeInForce.GTC, "1000", "0.0001")); + NewOrderResponse newOrderResponse = client.newOrder(limitBuy("LINKETH", TimeInForce.GTC, "1000", "0.0001").newOrderRespType(NewOrderResponseType.FULL)); System.out.println(newOrderResponse); } From ce38cb8c0903585de8e1bf2230afda32318242c3 Mon Sep 17 00:00:00 2001 From: Nils Wiersema Date: Sun, 29 Apr 2018 21:24:35 +0200 Subject: [PATCH 4/6] Parse both 'id' and 'tradeId' into Trade#id to deal with inconsistent API models on Binance --- .../com/binance/api/client/domain/account/Trade.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/binance/api/client/domain/account/Trade.java b/src/main/java/com/binance/api/client/domain/account/Trade.java index feb639faa..c64431118 100644 --- a/src/main/java/com/binance/api/client/domain/account/Trade.java +++ b/src/main/java/com/binance/api/client/domain/account/Trade.java @@ -2,6 +2,7 @@ import com.binance.api.client.constant.BinanceApiConstants; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; import org.apache.commons.lang3.builder.ToStringBuilder; /** @@ -54,10 +55,18 @@ public Long getId() { return id; } + @JsonSetter("id") public void setId(Long id) { this.id = id; } + @JsonSetter("tradeId") + public void setTradeId(Long id) { + if (this.id == null) { + setId(id); + } + } + public String getPrice() { return price; } From d7835f50356e3553235b5824039a0bcc63d5a814 Mon Sep 17 00:00:00 2001 From: Nils Wiersema Date: Sun, 29 Apr 2018 21:24:53 +0200 Subject: [PATCH 5/6] Add NewOrderResponse#origQty --- .../api/client/domain/account/NewOrderResponse.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/com/binance/api/client/domain/account/NewOrderResponse.java b/src/main/java/com/binance/api/client/domain/account/NewOrderResponse.java index c42246057..e1c1e7569 100644 --- a/src/main/java/com/binance/api/client/domain/account/NewOrderResponse.java +++ b/src/main/java/com/binance/api/client/domain/account/NewOrderResponse.java @@ -37,6 +37,8 @@ public class NewOrderResponse { private String price; + private String origQty; + private String executedQty; private OrderStatus status; @@ -94,6 +96,14 @@ public void setPrice(String price) { this.price = price; } + public String getOrigQty() { + return origQty; + } + + public void setOrigQty(String origQty) { + this.origQty = origQty; + } + public String getExecutedQty() { return executedQty; } @@ -150,6 +160,7 @@ public String toString() { .append("clientOrderId", clientOrderId) .append("transactTime", transactTime) .append("price", price) + .append("origQty", origQty) .append("executedQty", executedQty) .append("status", status) .append("timeInForce", timeInForce) From 16e94f36983b0768811912c23affd2d847dd8396 Mon Sep 17 00:00:00 2001 From: Nils Wiersema Date: Sun, 29 Apr 2018 21:39:32 +0200 Subject: [PATCH 6/6] Demonstrate use of newOrderRespType in README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 46e008f74..102a0b1ac 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,8 @@ System.out.println(order.getExecutedQty()); #### Placing a MARKET order ```java -NewOrderResponse newOrderResponse = client.newOrder(marketBuy("LINKETH", "1000")); +NewOrderResponse newOrderResponse = client.newOrder(marketBuy("LINKETH", "1000").orderRespType(OrderResponseType.FULL)); +List fills = newOrderResponse.getFills(); System.out.println(newOrderResponse.getClientOrderId()); ```