diff --git a/src/main/java/com/cf/ExchangeService.java b/src/main/java/com/cf/ExchangeService.java index 1283e0e..3ccc54e 100644 --- a/src/main/java/com/cf/ExchangeService.java +++ b/src/main/java/com/cf/ExchangeService.java @@ -1,14 +1,7 @@ package com.cf; -import com.cf.data.model.poloniex.PoloniexActiveLoanTypes; -import com.cf.data.model.poloniex.PoloniexChartData; -import com.cf.data.model.poloniex.PoloniexCompleteBalance; -import com.cf.data.model.poloniex.PoloniexFeeInfo; -import com.cf.data.model.poloniex.PoloniexOpenOrder; -import com.cf.data.model.poloniex.PoloniexOrderResult; -import com.cf.data.model.poloniex.PoloniexOrderTrade; -import com.cf.data.model.poloniex.PoloniexTicker; -import com.cf.data.model.poloniex.PoloniexTradeHistory; +import com.cf.data.model.poloniex.*; + import java.math.BigDecimal; import java.util.List; import java.util.Map; @@ -60,4 +53,8 @@ public interface ExchangeService { public PoloniexActiveLoanTypes returnActiveLoans(); + public PoloniexOrderStatus returnOrderStatus(String orderNumber); + + public PoloniexWithdrawResult withdraw(String currency, BigDecimal amount, String address, String paymentId); + } diff --git a/src/main/java/com/cf/TradingAPIClient.java b/src/main/java/com/cf/TradingAPIClient.java index 4510737..25a5ba1 100644 --- a/src/main/java/com/cf/TradingAPIClient.java +++ b/src/main/java/com/cf/TradingAPIClient.java @@ -20,6 +20,8 @@ public interface TradingAPIClient public String returnOrderTrades(String orderNumber); + public String returnOrderStatus(String orderNumber); + public String cancelOrder(String orderNumber); public String moveOrder(String orderNumber, BigDecimal rate); @@ -28,6 +30,8 @@ public interface TradingAPIClient public String buy(String currencyPair, BigDecimal buyPrice, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly); + public String withdraw(String currency, BigDecimal amount, String address, String paymentId); + // Lending APIs public String returnActiveLoans(); diff --git a/src/main/java/com/cf/client/HTTPClient.java b/src/main/java/com/cf/client/HTTPClient.java index 8b08de6..de3dfe4 100644 --- a/src/main/java/com/cf/client/HTTPClient.java +++ b/src/main/java/com/cf/client/HTTPClient.java @@ -1,11 +1,6 @@ package com.cf.client; -import java.io.IOException; -import java.util.List; -import org.apache.http.Consts; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; +import org.apache.http.*; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; @@ -14,12 +9,29 @@ import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; +import java.io.IOException; +import java.util.List; + /** * * @author David */ public class HTTPClient { + + private final HttpHost proxy; + + public HTTPClient() + { + this.proxy = null; + } + + public HTTPClient(HttpHost proxy) + { + this.proxy = proxy; + } + + public String postHttp(String url, List params, List headers) throws IOException { HttpPost post = new HttpPost(url); @@ -34,7 +46,7 @@ public String postHttp(String url, List params, List headers) throws IOExceptio } } - HttpClient httpClient = HttpClientBuilder.create().build(); + HttpClient httpClient = HttpClientBuilder.create().setProxy(proxy).build(); HttpResponse response = httpClient.execute(request); HttpEntity entity = response.getEntity(); diff --git a/src/main/java/com/cf/client/poloniex/PoloniexExchangeService.java b/src/main/java/com/cf/client/poloniex/PoloniexExchangeService.java index c2926f6..184ef7a 100644 --- a/src/main/java/com/cf/client/poloniex/PoloniexExchangeService.java +++ b/src/main/java/com/cf/client/poloniex/PoloniexExchangeService.java @@ -4,23 +4,16 @@ import com.cf.PriceDataAPIClient; import com.cf.TradingAPIClient; import com.cf.data.map.poloniex.PoloniexDataMapper; -import com.cf.data.model.poloniex.PoloniexActiveLoanTypes; -import com.cf.data.model.poloniex.PoloniexChartData; -import com.cf.data.model.poloniex.PoloniexCompleteBalance; -import com.cf.data.model.poloniex.PoloniexFeeInfo; -import com.cf.data.model.poloniex.PoloniexOpenOrder; -import com.cf.data.model.poloniex.PoloniexOrderResult; -import com.cf.data.model.poloniex.PoloniexOrderTrade; -import com.cf.data.model.poloniex.PoloniexTicker; -import com.cf.data.model.poloniex.PoloniexTradeHistory; +import com.cf.data.model.poloniex.*; +import org.apache.http.HttpHost; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - /** * * @author David @@ -39,6 +32,12 @@ public PoloniexExchangeService(String apiKey, String apiSecret) { this.mapper = new PoloniexDataMapper(); } + public PoloniexExchangeService(String apiKey, String apiSecret, HttpHost httpHost) { + this.publicClient = new PoloniexPublicAPIClient(httpHost); + this.tradingClient = new PoloniexTradingAPIClient(apiKey, apiSecret, httpHost); + this.mapper = new PoloniexDataMapper(); + } + public PoloniexExchangeService(PriceDataAPIClient publicClient, TradingAPIClient tradingClient, PoloniexDataMapper mapper) { this.publicClient = publicClient; this.tradingClient = tradingClient; @@ -225,6 +224,59 @@ public PoloniexActiveLoanTypes returnActiveLoans() { return activeLoanTypes; } + /** + * Returns order status for a given orderNumber + * + * @param orderNumber + * @return PoloniexOrderStatus + */ + @Override + public PoloniexOrderStatus returnOrderStatus(String orderNumber) { + long start = System.currentTimeMillis(); + PoloniexOrderStatus orderStatus = null; + PoloniexOrderStatusCheck orderStatusCheck; + try { + String orderStatusStr = tradingClient.returnOrderStatus(orderNumber); + orderStatusCheck = mapper.mapOrderStatusCheck(orderStatusStr); + if (orderStatusCheck.success == 1) { + orderStatus = mapper.mapOrderStatus(orderStatusStr); + } else { + PoloniexOrderStatusError error = mapper.mapOrderStatusError(orderStatusStr); + orderStatus = new PoloniexOrderStatus(0, error.result.get("error"), null); + } + LOG.trace("Retrieved and mapped {} {} order status in {} ms", orderStatusStr, orderNumber, System.currentTimeMillis() - start); + return orderStatus; + } catch (Exception ex) { + LOG.error("Error retrieving order status for {} - {}", orderNumber, ex.getMessage()); + } + + return orderStatus; + } + + /** + * Places a withdraw order + * + * @param currency Examples: USDT ETH + * @param amount the amount to withdraw + * @param address the address of currency + * @param paymentId For XMR withdrawals, you may optionally specify "paymentId". + * @return PoloniexWithdrawResult + */ + @Override + public PoloniexWithdrawResult withdraw(String currency, BigDecimal amount, String address, String paymentId) { + long start = System.currentTimeMillis(); + PoloniexWithdrawResult withdrawResult = null; + try { + String withdrawResultStr = tradingClient.withdraw(currency, amount, address, paymentId); + withdrawResult = mapper.mapWithdrawResult(withdrawResultStr); + LOG.trace("Retrieved and mapped {} {} withdraw in {} ms", withdrawResultStr, currency, System.currentTimeMillis() - start); + return withdrawResult; + } catch (Exception ex) { + LOG.error("Error retrieving withdraw for {} - {}", currency, ex.getMessage()); + } + return withdrawResult; + } + /** * * * Returns your open orders for a given currency pair diff --git a/src/main/java/com/cf/client/poloniex/PoloniexLendingService.java b/src/main/java/com/cf/client/poloniex/PoloniexLendingService.java index e381c78..a80ae71 100644 --- a/src/main/java/com/cf/client/poloniex/PoloniexLendingService.java +++ b/src/main/java/com/cf/client/poloniex/PoloniexLendingService.java @@ -7,6 +7,7 @@ import com.cf.data.model.poloniex.PoloniexLendingHistory; import com.cf.data.model.poloniex.PoloniexLendingResult; import com.cf.data.model.poloniex.PoloniexLoanOffer; +import org.apache.http.HttpHost; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -31,6 +32,12 @@ public PoloniexLendingService(String apiKey, String apiSecret) this.mapper = new PoloniexDataMapper(); } + public PoloniexLendingService(String apiKey, String apiSecret, HttpHost proxy) + { + this.tradingClient = new PoloniexTradingAPIClient(apiKey, apiSecret, proxy); + this.mapper = new PoloniexDataMapper(); + } + public PoloniexLendingService(TradingAPIClient tradingClient, PoloniexDataMapper mapper) { this.tradingClient = tradingClient; diff --git a/src/main/java/com/cf/client/poloniex/PoloniexPublicAPIClient.java b/src/main/java/com/cf/client/poloniex/PoloniexPublicAPIClient.java index 9c199d9..1012d7f 100644 --- a/src/main/java/com/cf/client/poloniex/PoloniexPublicAPIClient.java +++ b/src/main/java/com/cf/client/poloniex/PoloniexPublicAPIClient.java @@ -2,9 +2,11 @@ import com.cf.PriceDataAPIClient; import com.cf.client.HTTPClient; -import java.io.IOException; +import org.apache.http.HttpHost; import org.apache.logging.log4j.LogManager; +import java.io.IOException; + /** * * @author David @@ -20,6 +22,11 @@ public PoloniexPublicAPIClient() this.client = new HTTPClient(); } + public PoloniexPublicAPIClient(HttpHost proxy) + { + this.client = new HTTPClient(proxy); + } + public PoloniexPublicAPIClient(HTTPClient client) { this.client = client; diff --git a/src/main/java/com/cf/client/poloniex/PoloniexTradingAPIClient.java b/src/main/java/com/cf/client/poloniex/PoloniexTradingAPIClient.java index 99eaf0a..94a10fb 100644 --- a/src/main/java/com/cf/client/poloniex/PoloniexTradingAPIClient.java +++ b/src/main/java/com/cf/client/poloniex/PoloniexTradingAPIClient.java @@ -3,6 +3,7 @@ import com.cf.TradingAPIClient; import com.cf.client.HTTPClient; import org.apache.commons.codec.binary.Hex; +import org.apache.http.HttpHost; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; import org.apache.logging.log4j.LogManager; @@ -34,6 +35,12 @@ public PoloniexTradingAPIClient(String apiKey, String apiSecret) { this.client = new HTTPClient(); } + public PoloniexTradingAPIClient(String apiKey, String apiSecret, HttpHost httpHost) { + this.apiKey = apiKey; + this.apiSecret = apiSecret; + this.client = new HTTPClient(httpHost); + } + @Override public String returnBalances() { return this.returnTradingAPICommandResults("returnBalances"); @@ -82,6 +89,13 @@ public String returnOrderTrades(String orderNumber) { return returnTradingAPICommandResults("returnOrderTrades", additionalPostParams); } + @Override + public String returnOrderStatus(String orderNumber) { + List additionalPostParams = new ArrayList<>(); + additionalPostParams.add(new BasicNameValuePair("orderNumber", orderNumber)); + return returnTradingAPICommandResults("returnOrderStatus", additionalPostParams); + } + @Override public String cancelOrder(String orderNumber) { List additionalPostParams = new ArrayList<>(); @@ -109,6 +123,18 @@ public String buy(String currencyPair, BigDecimal buyPrice, BigDecimal amount, b return trade("buy", currencyPair, buyPrice, amount, fillOrKill, immediateOrCancel, postOnly); } + @Override + public String withdraw(String currency, BigDecimal amount, String address, String paymentId) { + List additionalPostParams = new ArrayList<>(); + additionalPostParams.add(new BasicNameValuePair("currency", currency)); + additionalPostParams.add(new BasicNameValuePair("amount", amount.toPlainString())); + additionalPostParams.add(new BasicNameValuePair("address", address)); + if (paymentId != null) { + additionalPostParams.add(new BasicNameValuePair("paymentId", paymentId)); + } + return returnTradingAPICommandResults("withdraw", additionalPostParams); + } + // Lending APIs @Override public String returnActiveLoans() { diff --git a/src/main/java/com/cf/data/map/poloniex/PoloniexDataMapper.java b/src/main/java/com/cf/data/map/poloniex/PoloniexDataMapper.java index f97312d..8c88d6e 100644 --- a/src/main/java/com/cf/data/map/poloniex/PoloniexDataMapper.java +++ b/src/main/java/com/cf/data/map/poloniex/PoloniexDataMapper.java @@ -1,27 +1,12 @@ package com.cf.data.map.poloniex; -import com.cf.data.model.poloniex.PoloniexActiveLoanTypes; -import com.cf.data.model.poloniex.PoloniexChartData; -import com.cf.data.model.poloniex.PoloniexCompleteBalance; -import com.cf.data.model.poloniex.PoloniexFeeInfo; -import com.cf.data.model.poloniex.PoloniexLendingHistory; -import com.cf.data.model.poloniex.PoloniexLendingResult; -import com.cf.data.model.poloniex.PoloniexLoanOffer; -import com.cf.data.model.poloniex.PoloniexOpenOrder; -import com.cf.data.model.poloniex.PoloniexOrderResult; -import com.cf.data.model.poloniex.PoloniexOrderTrade; -import com.cf.data.model.poloniex.PoloniexTicker; -import com.cf.data.model.poloniex.PoloniexTradeHistory; +import com.cf.data.model.poloniex.*; import com.cf.data.model.poloniex.deserialize.PoloniexChartDataDeserializer; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSyntaxException; +import com.google.gson.*; import com.google.gson.reflect.TypeToken; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.lang.reflect.Type; import java.math.BigDecimal; import java.time.ZoneOffset; @@ -31,9 +16,6 @@ import java.util.*; import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - /** * * @author David @@ -175,4 +157,24 @@ public PoloniexLendingResult mapLendingResult(String result) { return plr; } + public PoloniexOrderStatus mapOrderStatus(String result) { + return gson.fromJson(result, new TypeToken() { + }.getType()); + } + + public PoloniexOrderStatusCheck mapOrderStatusCheck(String result) { + return gson.fromJson(result, new TypeToken() { + }.getType()); + } + + public PoloniexOrderStatusError mapOrderStatusError(String result) { + return gson.fromJson(result, new TypeToken() { + }.getType()); + } + + public PoloniexWithdrawResult mapWithdrawResult(String result) { + return gson.fromJson(result, new TypeToken() { + }.getType()); + } + } diff --git a/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatus.java b/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatus.java new file mode 100644 index 0000000..10ded33 --- /dev/null +++ b/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatus.java @@ -0,0 +1,25 @@ +package com.cf.data.model.poloniex; + +import com.google.gson.Gson; + +import java.util.Map; + +/** + * @author guodong + */ +public class PoloniexOrderStatus { + public final Integer success; + public final String error; + public final Map result; + + public PoloniexOrderStatus(Integer success, String error, Map result) { + this.success = success; + this.error = error; + this.result = result; + } + + @Override + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatusCheck.java b/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatusCheck.java new file mode 100644 index 0000000..ec72961 --- /dev/null +++ b/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatusCheck.java @@ -0,0 +1,22 @@ +package com.cf.data.model.poloniex; + +import com.google.gson.Gson; + +/** + * @author guodong + */ +public class PoloniexOrderStatusCheck { + public final Integer success; + public final Object result; + + public PoloniexOrderStatusCheck(Integer success, Object result) { + this.success = success; + this.result = result; + } + + + @Override + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatusDetail.java b/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatusDetail.java new file mode 100644 index 0000000..756291c --- /dev/null +++ b/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatusDetail.java @@ -0,0 +1,33 @@ +package com.cf.data.model.poloniex; + +import com.google.gson.Gson; + +/** + * @author guodong + */ +public class PoloniexOrderStatusDetail { + public final String status; + public final String rate; + public final String amount; + public final String currencyPair; + public final String date; + public final String total; + public final String type; + public final String startingAmount; + + public PoloniexOrderStatusDetail(String status, String rate, String amount, String currencyPair, String date, String total, String type, String startingAmount) { + this.status = status; + this.rate = rate; + this.amount = amount; + this.currencyPair = currencyPair; + this.date = date; + this.total = total; + this.type = type; + this.startingAmount = startingAmount; + } + + @Override + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatusError.java b/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatusError.java new file mode 100644 index 0000000..6b35208 --- /dev/null +++ b/src/main/java/com/cf/data/model/poloniex/PoloniexOrderStatusError.java @@ -0,0 +1,24 @@ +package com.cf.data.model.poloniex; + +import com.google.gson.Gson; + +import java.util.Map; + +/** + * @author guodong + */ +public class PoloniexOrderStatusError { + public final Integer success; + public final Map result; + + public PoloniexOrderStatusError(Integer success, Map result) { + this.success = success; + this.result = result; + } + + + @Override + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/com/cf/data/model/poloniex/PoloniexWithdrawResult.java b/src/main/java/com/cf/data/model/poloniex/PoloniexWithdrawResult.java new file mode 100644 index 0000000..01a281a --- /dev/null +++ b/src/main/java/com/cf/data/model/poloniex/PoloniexWithdrawResult.java @@ -0,0 +1,21 @@ +package com.cf.data.model.poloniex; + +import com.google.gson.Gson; + +/** + * @author guodong + */ +public class PoloniexWithdrawResult { + public final String response; + public final String error; + + public PoloniexWithdrawResult(String response, String error) { + this.response = response; + this.error = error; + } + + @Override + public String toString() { + return new Gson().toJson(this); + } +}