Skip to content

Commit

Permalink
Adds DustLog History to Binance and adds additional response to Krake…
Browse files Browse the repository at this point in the history
…n. (#4370)

* Adds the new response "EGeneral:Too many requests" from Kraken to the base service. See #4369 (comment)

* Added new possibility to use the DustLog call (GET /sapi/v1/asset/dribblet) in Binance that gives you the history of your conversion results for small balances that are so small that they cannot be traded. See #4371.

* Implemented suggestions from @walec51.
  • Loading branch information
gregoreficint authored Jan 13, 2022
1 parent b93568b commit 6b23c4a
Show file tree
Hide file tree
Showing 10 changed files with 455 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.knowm.xchange.binance.dto.BinanceException;
import org.knowm.xchange.binance.dto.account.*;
import org.knowm.xchange.binance.dto.trade.BinanceCancelledOrder;
import org.knowm.xchange.binance.dto.trade.BinanceDustLog;
import org.knowm.xchange.binance.dto.trade.BinanceListenKey;
import org.knowm.xchange.binance.dto.trade.BinanceNewOrder;
import org.knowm.xchange.binance.dto.trade.BinanceOrder;
Expand Down Expand Up @@ -287,6 +288,33 @@ List<BinanceTrade> myTrades(
@QueryParam(SIGNATURE) ParamsDigest signature)
throws IOException, BinanceException;

/**
* Retrieves the dust log from Binance. If you have many currencies with low amount (=dust) that
* cannot be traded, because their amount is less than the minimum amount required for trading
* them, you can convert all these currencies at once into BNB with the button "Convert Small
* Balance to BNB".
*
* @param startTime optional. If set, also the endTime must be set. If neither time is set, the
* 100 most recent dust logs are returned.
* @param endTime optional. If set, also the startTime must be set. If neither time is set, the
* 100 most recent dust logs are returned.
* @param recvWindow optional
* @param timestamp mandatory
* @return
* @throws IOException
* @throws BinanceException
*/
@GET
@Path("/sapi/v1/asset/dribblet")
BinanceDustLog getDustLog(
@QueryParam("startTime") Long startTime,
@QueryParam("endTime") Long endTime,
@QueryParam("recvWindow") Long recvWindow,
@QueryParam("timestamp") SynchronizedValueFactory<Long> timestamp,
@HeaderParam(X_MBX_APIKEY) String apiKey,
@QueryParam(SIGNATURE) ParamsDigest signature)
throws IOException, BinanceException;

/**
* Submit a withdraw request.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.knowm.xchange.binance.dto.trade;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;

public final class BinanceDribbletDetails {
private final String transId;
private final BigDecimal serviceChargeAmount;
private final BigDecimal amount;
private final Long operateTime;
private final BigDecimal transferedAmount;
private final String fromAsset;

public BinanceDribbletDetails(
@JsonProperty("transId") String transId,
@JsonProperty("serviceChargeAmount") BigDecimal serviceChargeAmount,
@JsonProperty("amount") BigDecimal amount,
@JsonProperty("operateTime") Long operateTime,
@JsonProperty("transferedAmount") BigDecimal transferedAmount,
@JsonProperty("fromAsset") String fromAsset) {
this.transId = transId;
this.serviceChargeAmount = serviceChargeAmount;
this.amount = amount;
this.operateTime = operateTime;
this.transferedAmount = transferedAmount;
this.fromAsset = fromAsset;
}

public String getTransId() {
return transId;
}

public BigDecimal getServiceChargeAmount() {
return serviceChargeAmount;
}

public BigDecimal getAmount() {
return amount;
}

public Long getOperateTime() {
return operateTime;
}

public BigDecimal getTransferedAmount() {
return transferedAmount;
}

public String getFromAsset() {
return fromAsset;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.knowm.xchange.binance.dto.trade;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.util.List;

public final class BinanceDribblets {
private final Long operateTime;
private final BigDecimal totalTransferedAmount;
private final BigDecimal totalServiceChargeAmount;
private final String transId;
private final List<BinanceDribbletDetails> binanceDribbletDetails;

public BinanceDribblets(
@JsonProperty("operateTime") Long operateTime,
@JsonProperty("totalTransferedAmount") BigDecimal totalTransferedAmount,
@JsonProperty("totalServiceChargeAmount") BigDecimal totalServiceChargeAmount,
@JsonProperty("transId") String transId,
@JsonProperty("userAssetDribbletDetails")
List<BinanceDribbletDetails> binanceDribbletDetails) {
this.operateTime = operateTime;
this.totalTransferedAmount = totalTransferedAmount;
this.totalServiceChargeAmount = totalServiceChargeAmount;
this.transId = transId;
this.binanceDribbletDetails = binanceDribbletDetails;
}

public Long getOperateTime() {
return operateTime;
}

public BigDecimal getTotalTransferedAmount() {
return totalTransferedAmount;
}

public BigDecimal getTotalServiceChargeAmount() {
return totalServiceChargeAmount;
}

public String getTransId() {
return transId;
}

public List<BinanceDribbletDetails> getBinanceDribbletDetails() {
return binanceDribbletDetails;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.knowm.xchange.binance.dto.trade;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;

public final class BinanceDustLog {
private final Integer total;
private final List<BinanceDribblets> dribblets;

public BinanceDustLog(
@JsonProperty("total") Integer total,
@JsonProperty("userAssetDribblets") List<BinanceDribblets> dribblets) {
this.total = total;
this.dribblets = dribblets;
}

public Integer getTotal() {
return total;
}

public List<BinanceDribblets> getDribblets() {
return dribblets;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.knowm.xchange.binance.BinanceErrorAdapter;
import org.knowm.xchange.binance.BinanceExchange;
import org.knowm.xchange.binance.dto.BinanceException;
import org.knowm.xchange.binance.dto.trade.BinanceDustLog;
import org.knowm.xchange.binance.dto.trade.BinanceNewOrder;
import org.knowm.xchange.binance.dto.trade.BinanceOrder;
import org.knowm.xchange.binance.dto.trade.BinanceTrade;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.knowm.xchange.binance.BinanceExchange;
import org.knowm.xchange.binance.dto.BinanceException;
import org.knowm.xchange.binance.dto.trade.BinanceCancelledOrder;
import org.knowm.xchange.binance.dto.trade.BinanceDustLog;
import org.knowm.xchange.binance.dto.trade.BinanceListenKey;
import org.knowm.xchange.binance.dto.trade.BinanceNewOrder;
import org.knowm.xchange.binance.dto.trade.BinanceOrder;
Expand All @@ -21,6 +22,7 @@
import org.knowm.xchange.binance.dto.trade.TimeInForce;
import org.knowm.xchange.client.ResilienceRegistries;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.exceptions.ExchangeException;

public class BinanceTradeServiceRaw extends BinanceBaseService {

Expand Down Expand Up @@ -189,23 +191,55 @@ public List<BinanceTrade> myTrades(
CurrencyPair pair, Long orderId, Long startTime, Long endTime, Long fromId, Integer limit)
throws BinanceException, IOException {
return decorateApiCall(
() ->
binance.myTrades(
BinanceAdapters.toSymbol(pair),
orderId,
startTime,
endTime,
fromId,
limit,
getRecvWindow(),
getTimestampFactory(),
apiKey,
signatureCreator))
() ->
binance.myTrades(
BinanceAdapters.toSymbol(pair),
orderId,
startTime,
endTime,
fromId,
limit,
getRecvWindow(),
getTimestampFactory(),
apiKey,
signatureCreator))
.withRetry(retry("myTrades"))
.withRateLimiter(rateLimiter(REQUEST_WEIGHT_RATE_LIMITER), myTradesPermits(limit))
.call();
}

/**
* Retrieves the dust log from Binance. If you have many currencies with low amount (=dust) that
* cannot be traded, because their amount is less than the minimum amount required for trading
* them, you can convert all these currencies at once into BNB with the button "Convert Small
* Balance to BNB".
*
* @param startTime optional. If set, also the endTime must be set. If neither time is set, the
* 100 most recent dust logs are returned.
* @param endTime optional. If set, also the startTime must be set. If neither time is set, the
* 100 most recent dust logs are returned.
* @return
* @throws IOException
*/
public BinanceDustLog getDustLog(Long startTime, Long endTime) throws IOException {

if (((startTime != null) && (endTime == null)) || (startTime == null) && (endTime != null))
throw new ExchangeException("You need to specify both, the start and the end date, or none of them");

return decorateApiCall(
() ->
binance.getDustLog(
startTime,
endTime,
getRecvWindow(),
getTimestampFactory(),
apiKey,
signatureCreator))
.withRetry(retry("myDustLog"))
.withRateLimiter(rateLimiter(REQUEST_WEIGHT_RATE_LIMITER))
.call();
}

public BinanceListenKey startUserDataStream() throws IOException {
return decorateApiCall(() -> binance.startUserDataStream(apiKey))
.withRateLimiter(rateLimiter(REQUEST_WEIGHT_RATE_LIMITER))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import static org.assertj.core.api.Assertions.assertThat;

import com.github.tomakehurst.wiremock.junit.WireMockRule;
import java.io.IOException;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.knowm.xchange.ExchangeFactory;
import org.knowm.xchange.ExchangeSpecification;
Expand All @@ -13,7 +15,8 @@

public class BinanceExchangeIntegration {
protected static BinanceExchange exchange;

@Rule
public WireMockRule wireMockRule = new WireMockRule();
@BeforeClass
public static void beforeClass() throws Exception {
createExchange();
Expand Down Expand Up @@ -42,4 +45,16 @@ protected static void createExchange() throws Exception {
protected void assumeProduction() {
Assume.assumeFalse("Using sandbox", exchange.usingSandbox());
}

protected BinanceExchange createExchangeMocked() {
BinanceExchange exchangeMocked =
ExchangeFactory.INSTANCE.createExchangeWithoutSpecification(BinanceExchange.class);
ExchangeSpecification specification = exchangeMocked.getDefaultExchangeSpecification();
specification.setHost("localhost");
specification.setSslUri("http://localhost:" + wireMockRule.port() + "/");
specification.setPort(wireMockRule.port());
specification.setShouldLoadRemoteMetaData(false);
exchangeMocked.applySpecification(specification);
return exchangeMocked;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
package org.knowm.xchange.binance.service.trade;

import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.knowm.xchange.binance.dto.trade.OrderType.LIMIT;
import static org.knowm.xchange.binance.dto.trade.OrderType.MARKET;
import static org.knowm.xchange.binance.dto.trade.OrderType.STOP_LOSS_LIMIT;
Expand All @@ -9,17 +18,22 @@
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Optional;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;

import org.junit.Test;
import org.knowm.xchange.binance.BinanceExchange;
import org.knowm.xchange.binance.BinanceExchangeIntegration;
import org.knowm.xchange.binance.dto.trade.BinanceDustLog;
import org.knowm.xchange.binance.dto.trade.TimeInForce;
import org.knowm.xchange.binance.service.BinanceTradeService;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dto.trade.LimitOrder;
import org.knowm.xchange.dto.trade.MarketOrder;
import org.knowm.xchange.dto.trade.StopOrder;
import org.knowm.xchange.utils.ObjectMapperHelper;

public class TradeServiceIntegration extends BinanceExchangeIntegration {

Expand Down Expand Up @@ -128,4 +142,24 @@ private StopOrder sampleTakeProfitLimitOrder() throws IOException {
.flag(TimeInForce.GTC)
.build();
}

@Test
public void testDustLog() throws IOException {
BinanceExchange exchangeMocked = createExchangeMocked();
tradeService = (BinanceTradeService) exchangeMocked.getTradeService();
stubFor(
get(urlPathEqualTo("/sapi/v1/asset/dribblet"))
.willReturn(
ok()
.withHeader("Content-Type", "application/json")
.withBodyFile("dustlog.json")));

BinanceDustLog dustLog = tradeService.getDustLog(1639094400000L, 1639180800000L);
assertEquals(1, dustLog.getDribblets().size());
assertEquals(28, dustLog.getDribblets().get(0).getBinanceDribbletDetails().size());
assertEquals((Long) 1639129045000L, dustLog.getDribblets().get(0).getOperateTime());
assertEquals(
"90698471826",
dustLog.getDribblets().get(0).getBinanceDribbletDetails().get(0).getTransId());
}
}
Loading

0 comments on commit 6b23c4a

Please sign in to comment.