diff --git a/README.md b/README.md index d549233..dc15cc7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,25 @@ # poloniex-api-java Java API client for the Poloniex exchange with focus on simplicity and usability. +### Maven configuration + +PoloniexClient is available on [Maven Central](http://search.maven.org/#search). You just have to add the following repository to your `pom.xml` file. + +```xml + + sonatype snapshots + https://oss.sonatype.org/content/repositories/snapshots + +``` +The current snapshot version is `1.1.1-SNAPSHOT` from the [master](https://github.com/TheCookieLab/poloniex-api-java) branch. +```xml + + com.github.thecookielab + PoloniexClient + 1.1.1-SNAPSHOT + +``` + Using this client is as simple as instantiating a new PoloniexExchangeService with your Poloniex API Key and API Secret as constructor parameters: ```java @@ -92,6 +111,15 @@ PoloniexExchangeService service = new PoloniexExchangeService(apiKey, apiSecret) List UsdtBtcTradeHistory = service.returnTradeHistory("USDT_BTC"); ``` +### Return order trades +```java +String apiKey = "foo"; +String apiSecret = "bar"; +PoloniexExchangeService service = new PoloniexExchangeService(apiKey, apiSecret); +String orderNumber = "12345678"; +List orderTrades = service.returnOrderTrades(orderNumber); +``` + ### Buy ```java String apiKey = "foo"; diff --git a/pom.xml b/pom.xml index 42a5022..fe9fde0 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,108 @@ 4.0.0 - com.cf + com.github.thecookielab PoloniexClient 1.1.1-SNAPSHOT jar + + + + David Pang + + + Cheolhee Han + + + + + + MIT License + All source code is under the MIT license. + + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + + + sonatype-oss-release + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://oss.sonatype.org/ + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + -Xdoclint:none + + + + attach-javadocs + + jar + + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + + + + + com.google.code.gson @@ -33,7 +131,7 @@ org.apache.logging.log4j log4j-core 2.9.1 - + io.netty netty-all diff --git a/src/main/java/com/cf/ExchangeService.java b/src/main/java/com/cf/ExchangeService.java index 523725d..1283e0e 100644 --- a/src/main/java/com/cf/ExchangeService.java +++ b/src/main/java/com/cf/ExchangeService.java @@ -1,12 +1,12 @@ 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 java.math.BigDecimal; @@ -17,8 +17,8 @@ * * @author David */ -public interface ExchangeService -{ +public interface ExchangeService { + public final static String USDT_BTC_CURRENCY_PAIR = "USDT_BTC"; public final static String USDT_ETH_CURRENCY_PAIR = "USDT_ETH"; public final static String BTC_CURRENCY_TYPE = "BTC"; @@ -29,9 +29,9 @@ public interface ExchangeService public final static Long TWO_HOUR_TIME_PERIOD = 7_200L; public final static Long DAILY_TIME_PERIOD = 86_400L; public final static Long LONG_LONG_AGO = 1_439_000_000L; - + public List returnChartData(String currencyPair, Long periodInSeconds, Long startEpochInSeconds); - + public Map returnTicker(); public PoloniexTicker returnTicker(String currencyName); @@ -43,19 +43,21 @@ public interface ExchangeService public PoloniexCompleteBalance returnCurrencyBalance(String currencyName); public PoloniexFeeInfo returnFeeInfo(); - + public List returnOpenOrders(String currencyName); - + public List returnTradeHistory(String currencyPair); - + + public List returnOrderTrades(String orderNumber); + public boolean cancelOrder(String orderNumber); - + public PoloniexOrderResult moveOrder(String orderNumber, BigDecimal rate, Boolean immediateOrCancel, Boolean postOnly); - + public PoloniexOrderResult sell(String currencyPair, BigDecimal sellPrice, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly); public PoloniexOrderResult buy(String currencyPair, BigDecimal buyPrice, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly); - public PoloniexActiveLoanTypes returnActiveLoans(); + public PoloniexActiveLoanTypes returnActiveLoans(); } diff --git a/src/main/java/com/cf/TradingAPIClient.java b/src/main/java/com/cf/TradingAPIClient.java index 22a3d3c..4510737 100644 --- a/src/main/java/com/cf/TradingAPIClient.java +++ b/src/main/java/com/cf/TradingAPIClient.java @@ -17,6 +17,8 @@ public interface TradingAPIClient public String returnOpenOrders(String currencyPair); public String returnTradeHistory(String currencyPair); + + public String returnOrderTrades(String orderNumber); public String cancelOrder(String orderNumber); diff --git a/src/main/java/com/cf/client/WSSClient.java b/src/main/java/com/cf/client/WSSClient.java index 28d1d7c..6c7ac71 100644 --- a/src/main/java/com/cf/client/WSSClient.java +++ b/src/main/java/com/cf/client/WSSClient.java @@ -58,25 +58,10 @@ public WSSClient(String url) throws Exception { subscriptions = new HashMap<>(); } - /** - * * - * - * @param subscription - * @param subscriptionMessageHandler - */ public void addSubscription(PoloniexWSSSubscription subscription, IMessageHandler subscriptionMessageHandler) { this.subscriptions.put(subscription, subscriptionMessageHandler); } - /** - * * - * - * @param runTimeInMillis The subscription time expressed in milliseconds. - * The minimum runtime is 1 minute. - * @throws InterruptedException - * @throws IOException - * @throws java.net.URISyntaxException - */ public void run(long runTimeInMillis) throws InterruptedException, IOException, URISyntaxException { final PoloniexWSSClientRouter router = new PoloniexWSSClientRouter(uri, subscriptions.entrySet().stream() diff --git a/src/main/java/com/cf/client/poloniex/PoloniexExchangeService.java b/src/main/java/com/cf/client/poloniex/PoloniexExchangeService.java index eeaa27b..c2926f6 100644 --- a/src/main/java/com/cf/client/poloniex/PoloniexExchangeService.java +++ b/src/main/java/com/cf/client/poloniex/PoloniexExchangeService.java @@ -10,6 +10,7 @@ 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 java.math.BigDecimal; @@ -24,23 +25,21 @@ * * @author David */ -public class PoloniexExchangeService implements ExchangeService -{ +public class PoloniexExchangeService implements ExchangeService { + private final PriceDataAPIClient publicClient; private final TradingAPIClient tradingClient; private final PoloniexDataMapper mapper; private final static Logger LOG = LogManager.getLogger(PoloniexExchangeService.class); - public PoloniexExchangeService(String apiKey, String apiSecret) - { + public PoloniexExchangeService(String apiKey, String apiSecret) { this.publicClient = new PoloniexPublicAPIClient(); this.tradingClient = new PoloniexTradingAPIClient(apiKey, apiSecret); this.mapper = new PoloniexDataMapper(); } - public PoloniexExchangeService(PriceDataAPIClient publicClient, TradingAPIClient tradingClient, PoloniexDataMapper mapper) - { + public PoloniexExchangeService(PriceDataAPIClient publicClient, TradingAPIClient tradingClient, PoloniexDataMapper mapper) { this.publicClient = publicClient; this.tradingClient = tradingClient; this.mapper = mapper; @@ -51,23 +50,22 @@ public PoloniexExchangeService(PriceDataAPIClient publicClient, TradingAPIClient * Returns candlestick chart data for the given currency pair * * @param currencyPair Examples: USDT_ETH, USDT_BTC, BTC_ETH - * @param periodInSeconds The candlestick chart data period. Valid values are 300 (5 min), 900 (15 minutes), 7200 (2 hours), 14400 (4 hours), 86400 (daily) - * @param startEpochInSeconds UNIX timestamp format and used to specify the start date of the data returned + * @param periodInSeconds The candlestick chart data period. Valid values + * are 300 (5 min), 900 (15 minutes), 7200 (2 hours), 14400 (4 hours), 86400 + * (daily) + * @param startEpochInSeconds UNIX timestamp format and used to specify the + * start date of the data returned * @return List of PoloniexChartData */ @Override - public List returnChartData(String currencyPair, Long periodInSeconds, Long startEpochInSeconds) - { + public List returnChartData(String currencyPair, Long periodInSeconds, Long startEpochInSeconds) { long start = System.currentTimeMillis(); List chartData = new ArrayList(); - try - { + try { String chartDataResult = publicClient.getChartData(currencyPair, periodInSeconds, startEpochInSeconds); chartData = mapper.mapChartData(chartDataResult); LOG.debug("Retrieved and mapped {} chart data in {} ms", currencyPair, (System.currentTimeMillis() - start)); - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error retrieving chart data for {} - {}", currencyPair, ex.getMessage()); } @@ -81,19 +79,15 @@ public List returnChartData(String currencyPair, Long periodI * @return ticker data mapped to pair */ @Override - public Map returnTicker() - { + public Map returnTicker() { long start = System.currentTimeMillis(); Map tickerResult = null; - try - { + try { String tickerData = publicClient.returnTicker(); tickerResult = mapper.mapTicker(tickerData); - + LOG.trace("Retrieved and mapped ticker in {} ms", System.currentTimeMillis() - start); - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error retrieving ticker - {}", ex.getMessage()); } @@ -108,18 +102,14 @@ public Map returnTicker() * @return PoloniexTicker */ @Override - public PoloniexTicker returnTicker(String currencyPair) - { + public PoloniexTicker returnTicker(String currencyPair) { long start = System.currentTimeMillis(); PoloniexTicker tickerResult = null; - try - { + try { String tickerData = publicClient.returnTicker(); tickerResult = mapper.mapTickerForCurrency(currencyPair, tickerData); LOG.trace("Retrieved and mapped {} ticker in {} ms", currencyPair, System.currentTimeMillis() - start); - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error retrieving ticker for {} - {}", currencyPair, ex.getMessage()); } @@ -127,18 +117,14 @@ public PoloniexTicker returnTicker(String currencyPair) } @Override - public List returnAllMarkets() - { + public List returnAllMarkets() { long start = System.currentTimeMillis(); List allMarkets = new ArrayList<>(); - try - { + try { String tickerData = publicClient.returnTicker(); allMarkets = mapper.mapMarkets(tickerData); LOG.trace("Retrieved and mapped market pairs in {} ms", System.currentTimeMillis() - start); - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error retrieving all markets - {}", ex.getMessage()); } @@ -147,17 +133,17 @@ public List returnAllMarkets() /** * * - * Returns the complete balances inclusive non-zero balances or not depending on parameter includeZeroBalances + * Returns the complete balances inclusive non-zero balances or not + * depending on parameter includeZeroBalances + * * @param includeZeroBalances The includeZeroBalances - * @return Map + * @return Map of String, PoloniexCompleteBalance */ @Override - public Map returnBalance(boolean includeZeroBalances) - { + public Map returnBalance(boolean includeZeroBalances) { long start = System.currentTimeMillis(); Map balance = null; - try - { + try { String completeBalancesResult = tradingClient.returnCompleteBalances(); if (includeZeroBalances) { balance = mapper.mapCompleteBalanceResult(completeBalancesResult); @@ -166,9 +152,7 @@ public Map returnBalance(boolean includeZeroBal balance = mapper.mapCompleteBalanceResultForNonZeroCurrencies(completeBalancesResult); LOG.trace("Retrieved and mapped non-zero balances in {} ms", System.currentTimeMillis() - start); } - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error retrieving complete balance - {}", ex.getMessage()); } @@ -183,18 +167,14 @@ public Map returnBalance(boolean includeZeroBal * @return PoloniexCompleteBalance */ @Override - public PoloniexCompleteBalance returnCurrencyBalance(String currencyType) - { + public PoloniexCompleteBalance returnCurrencyBalance(String currencyType) { long start = System.currentTimeMillis(); PoloniexCompleteBalance balance = null; - try - { + try { String completeBalancesResult = tradingClient.returnCompleteBalances(); balance = mapper.mapCompleteBalanceResultForCurrency(currencyType, completeBalancesResult); LOG.trace("Retrieved and mapped {} complete balance in {} ms", currencyType, System.currentTimeMillis() - start); - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error retrieving complete balance for {} - {}", currencyType, ex.getMessage()); } @@ -203,23 +183,21 @@ public PoloniexCompleteBalance returnCurrencyBalance(String currencyType) /** * * - * If you are enrolled in the maker-taker fee schedule, returns your current trading fees and trailing 30-day volume in BTC. This information is updated once every 24 hours. + * If you are enrolled in the maker-taker fee schedule, returns your current + * trading fees and trailing 30-day volume in BTC. This information is + * updated once every 24 hours. * * @return PoloniexFeeInfo */ @Override - public PoloniexFeeInfo returnFeeInfo() - { + public PoloniexFeeInfo returnFeeInfo() { long start = System.currentTimeMillis(); PoloniexFeeInfo feeInfo = null; - try - { + try { String feeInfoResult = tradingClient.returnFeeInfo(); feeInfo = mapper.mapFeeInfo(feeInfoResult); LOG.trace("Retrieved and mapped Poloniex fee info in {} ms", System.currentTimeMillis() - start); - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error retrieving fee info - {}", ex.getMessage()); } @@ -233,18 +211,14 @@ public PoloniexFeeInfo returnFeeInfo() * @return PoloniexActiveLoanTypes */ @Override - public PoloniexActiveLoanTypes returnActiveLoans() - { + public PoloniexActiveLoanTypes returnActiveLoans() { long start = System.currentTimeMillis(); PoloniexActiveLoanTypes activeLoanTypes = null; - try - { + try { String activeLoansResult = tradingClient.returnActiveLoans(); activeLoanTypes = mapper.mapActiveLoans(activeLoansResult); LOG.trace("Retrieved and mapped Poloniex active loans in {} ms", System.currentTimeMillis() - start); - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error retrieving active loans - {}", ex.getMessage()); } @@ -259,19 +233,15 @@ public PoloniexActiveLoanTypes returnActiveLoans() * @return List of PoloniexOpenOrder */ @Override - public List returnOpenOrders(String currencyPair) - { + public List returnOpenOrders(String currencyPair) { long start = System.currentTimeMillis(); List openOrders = new ArrayList(); - try - { + try { String openOrdersData = tradingClient.returnOpenOrders(currencyPair); openOrders = mapper.mapOpenOrders(openOrdersData); LOG.trace("Retrieved and mapped {} {} open orders in {} ms", openOrders.size(), currencyPair, System.currentTimeMillis() - start); return openOrders; - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error retrieving open orders for {} - {}", currencyPair, ex.getMessage()); } @@ -286,50 +256,63 @@ public List returnOpenOrders(String currencyPair) * @return List of PoloniexTradeHistory */ @Override - public List returnTradeHistory(String currencyPair) - { + public List returnTradeHistory(String currencyPair) { long start = System.currentTimeMillis(); List tradeHistory = new ArrayList(); - try - { + try { String tradeHistoryData = tradingClient.returnTradeHistory(currencyPair); tradeHistory = mapper.mapTradeHistory(tradeHistoryData); LOG.trace("Retrieved and mapped {} {} trade history in {} ms", tradeHistory.size(), currencyPair, System.currentTimeMillis() - start); return tradeHistory; - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error retrieving trade history for {} - {}", currencyPair, ex.getMessage()); } return tradeHistory; } + @Override + public List returnOrderTrades(String orderNumber) { + long start = System.currentTimeMillis(); + List orderTrades = new ArrayList<>(); + + try { + String orderTradesResult = tradingClient.returnOrderTrades(orderNumber); + orderTrades = mapper.mapOrderTrades(orderTradesResult); + LOG.trace("Executed and mapped return order trades for {} in {} ms", orderNumber, System.currentTimeMillis() - start); + } catch (Exception ex) { + LOG.error("Error executing return order trades for {} - {}", orderNumber, ex.getMessage()); + } + + return orderTrades; + } + /** * * * Places a sell order in a given market * * @param currencyPair Examples: USDT_ETH, USDT_BTC, BTC_ETH - * @param sellPrice - * @param amount - * @param fillOrKill Will either fill in its entirety or be completely aborted - * @param immediateOrCancel Order can be partially or completely filled, but any portion of the order that cannot be filled immediately will be canceled rather than left on the order book - * @param postOnly A post-only order will only be placed if no portion of it fills immediately; this guarantees you will never pay the taker fee on any part of the order that fills + * @param sellPrice the sell price + * @param amount the amount to sell + * @param fillOrKill Will either fill in its entirety or be completely + * aborted + * @param immediateOrCancel Order can be partially or completely filled, but + * any portion of the order that cannot be filled immediately will be + * canceled rather than left on the order book + * @param postOnly A post-only order will only be placed if no portion of it + * fills immediately; this guarantees you will never pay the taker fee on + * any part of the order that fills * @return PoloniexOrderResult */ @Override - public PoloniexOrderResult sell(String currencyPair, BigDecimal sellPrice, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly) - { + public PoloniexOrderResult sell(String currencyPair, BigDecimal sellPrice, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly) { long start = System.currentTimeMillis(); PoloniexOrderResult orderResult = null; - try - { + try { String sellTradeResult = tradingClient.sell(currencyPair, sellPrice, amount, fillOrKill, immediateOrCancel, postOnly); orderResult = mapper.mapTradeOrder(sellTradeResult); LOG.trace("Executed and mapped {} sell order {} in {} ms", currencyPair, sellTradeResult, System.currentTimeMillis() - start); - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error executing sell order for {} - {}", currencyPair, ex.getMessage()); } @@ -341,26 +324,27 @@ public PoloniexOrderResult sell(String currencyPair, BigDecimal sellPrice, BigDe * Places a buy order in a given market * * @param currencyPair Examples: USDT_ETH, USDT_BTC, BTC_ETH - * @param buyPrice - * @param amount - * @param fillOrKill Will either fill in its entirety or be completely aborted - * @param immediateOrCancel Order can be partially or completely filled, but any portion of the order that cannot be filled immediately will be canceled rather than left on the order book - * @param postOnly A post-only order will only be placed if no portion of it fills immediately; this guarantees you will never pay the taker fee on any part of the order that fills + * @param buyPrice the buy price + * @param amount the amount to buy + * @param fillOrKill Will either fill in its entirety or be completely + * aborted + * @param immediateOrCancel Order can be partially or completely filled, but + * any portion of the order that cannot be filled immediately will be + * canceled rather than left on the order book + * @param postOnly A post-only order will only be placed if no portion of it + * fills immediately; this guarantees you will never pay the taker fee on + * any part of the order that fills * @return PoloniexOrderResult */ @Override - public PoloniexOrderResult buy(String currencyPair, BigDecimal buyPrice, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly) - { + public PoloniexOrderResult buy(String currencyPair, BigDecimal buyPrice, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly) { long start = System.currentTimeMillis(); PoloniexOrderResult orderResult = null; - try - { + try { String buyTradeResult = tradingClient.buy(currencyPair, buyPrice, amount, fillOrKill, immediateOrCancel, postOnly); orderResult = mapper.mapTradeOrder(buyTradeResult); LOG.trace("Executed and mapped {} buy order {} in {} ms", currencyPair, buyTradeResult, System.currentTimeMillis() - start); - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error executing buy order for {} - {}", currencyPair, ex.getMessage()); } @@ -371,23 +355,19 @@ public PoloniexOrderResult buy(String currencyPair, BigDecimal buyPrice, BigDeci * * * Cancels an order you have placed in a given market * - * @param orderNumber + * @param orderNumber order identifier on the exchange * @return true if successful, false otherwise */ @Override - public boolean cancelOrder(String orderNumber) - { + public boolean cancelOrder(String orderNumber) { long start = System.currentTimeMillis(); boolean success = false; - try - { + try { String cancelOrderResult = tradingClient.cancelOrder(orderNumber); success = mapper.mapCancelOrder(cancelOrderResult); LOG.trace("Executed and mapped cancel order for {} in {} ms", orderNumber, System.currentTimeMillis() - start); return success; - } - catch (Exception ex) - { + } catch (Exception ex) { LOG.error("Error executing cancel order for {} - {}", orderNumber, ex.getMessage()); } @@ -395,18 +375,14 @@ public boolean cancelOrder(String orderNumber) } @Override - public PoloniexOrderResult moveOrder(String orderNumber, BigDecimal rate, Boolean immediateOrCancel, Boolean postOnly) - { + public PoloniexOrderResult moveOrder(String orderNumber, BigDecimal rate, Boolean immediateOrCancel, Boolean postOnly) { long start = System.currentTimeMillis(); PoloniexOrderResult orderResult = null; - try - { + try { String moveOrderResult = tradingClient.moveOrder(orderNumber, rate); orderResult = mapper.mapTradeOrder(moveOrderResult); LogManager.getLogger(PoloniexExchangeService.class).trace("Executed and mapped move order for {} in {} ms", orderNumber, System.currentTimeMillis() - start); - } - catch (Exception ex) - { + } catch (Exception ex) { LogManager.getLogger(PoloniexExchangeService.class).error("Error executing move order for {} - {}", orderNumber, ex.getMessage()); } diff --git a/src/main/java/com/cf/client/poloniex/PoloniexLendingService.java b/src/main/java/com/cf/client/poloniex/PoloniexLendingService.java index cbd22b7..e381c78 100644 --- a/src/main/java/com/cf/client/poloniex/PoloniexLendingService.java +++ b/src/main/java/com/cf/client/poloniex/PoloniexLendingService.java @@ -63,14 +63,6 @@ public List returnLendingHistory(int hours, int limit) return lendingHistory; } - /** - * @param currency - * @param amount - * @param lendingRate - * @param duration - * @param autoRenew - * @return - */ @Override public PoloniexLendingResult createLoanOffer(String currency, BigDecimal amount, BigDecimal lendingRate, int duration, boolean autoRenew) { @@ -94,10 +86,6 @@ public PoloniexLendingResult createLoanOffer(String currency, BigDecimal amount, return result; } - /** - * @param orderNumber - * @return - */ @Override public PoloniexLendingResult cancelLoanOffer(String orderNumber) { @@ -117,9 +105,6 @@ public PoloniexLendingResult cancelLoanOffer(String orderNumber) return result; } - /** - * @return - */ @Override public PoloniexActiveLoanTypes returnActiveLoans() { diff --git a/src/main/java/com/cf/client/poloniex/PoloniexTradingAPIClient.java b/src/main/java/com/cf/client/poloniex/PoloniexTradingAPIClient.java index 7bf8f2d..99eaf0a 100644 --- a/src/main/java/com/cf/client/poloniex/PoloniexTradingAPIClient.java +++ b/src/main/java/com/cf/client/poloniex/PoloniexTradingAPIClient.java @@ -1,6 +1,5 @@ package com.cf.client.poloniex; - import com.cf.TradingAPIClient; import com.cf.client.HTTPClient; import org.apache.commons.codec.binary.Hex; @@ -22,39 +21,35 @@ * @author David * @author cheolhee */ -public class PoloniexTradingAPIClient implements TradingAPIClient -{ +public class PoloniexTradingAPIClient implements TradingAPIClient { + private static final String TRADING_URL = "https://poloniex.com/tradingApi?"; private final String apiKey; private final String apiSecret; private final HTTPClient client; - public PoloniexTradingAPIClient(String apiKey, String apiSecret) - { + public PoloniexTradingAPIClient(String apiKey, String apiSecret) { this.apiKey = apiKey; this.apiSecret = apiSecret; this.client = new HTTPClient(); } @Override - public String returnBalances() - { + public String returnBalances() { return this.returnTradingAPICommandResults("returnBalances"); } @Override - public String returnFeeInfo() - { + public String returnFeeInfo() { return this.returnTradingAPICommandResults("returnFeeInfo"); } @Override - public String returnCompleteBalances() - { + public String returnCompleteBalances() { return returnCompleteBalances(false); } - public String returnCompleteBalances(boolean allAccounts) - { + + public String returnCompleteBalances(boolean allAccounts) { if (allAccounts) { returnCompleteBalances(); List additionalPostParams = new ArrayList<>(); @@ -65,18 +60,15 @@ public String returnCompleteBalances(boolean allAccounts) } } - @Override - public String returnOpenOrders(String currencyPair) - { + public String returnOpenOrders(String currencyPair) { List additionalPostParams = new ArrayList<>(); additionalPostParams.add(new BasicNameValuePair("currencyPair", currencyPair)); return returnTradingAPICommandResults("returnOpenOrders", additionalPostParams); } @Override - public String returnTradeHistory(String currencyPair) - { + public String returnTradeHistory(String currencyPair) { List additionalPostParams = new ArrayList<>(); additionalPostParams.add(new BasicNameValuePair("currencyPair", currencyPair == null ? "all" : currencyPair)); additionalPostParams.add(new BasicNameValuePair("start", PoloniexExchangeService.LONG_LONG_AGO.toString())); @@ -84,16 +76,21 @@ public String returnTradeHistory(String currencyPair) } @Override - public String cancelOrder(String orderNumber) - { + public String returnOrderTrades(String orderNumber) { + List additionalPostParams = new ArrayList<>(); + additionalPostParams.add(new BasicNameValuePair("orderNumber", orderNumber)); + return returnTradingAPICommandResults("returnOrderTrades", additionalPostParams); + } + + @Override + public String cancelOrder(String orderNumber) { List additionalPostParams = new ArrayList<>(); additionalPostParams.add(new BasicNameValuePair("orderNumber", orderNumber)); return returnTradingAPICommandResults("cancelOrder", additionalPostParams); } @Override - public String moveOrder(String orderNumber, BigDecimal rate) - { + public String moveOrder(String orderNumber, BigDecimal rate) { List additionalPostParams = new ArrayList<>(); additionalPostParams.add(new BasicNameValuePair("orderNumber", orderNumber)); additionalPostParams.add(new BasicNameValuePair("rate", rate.toPlainString())); @@ -103,25 +100,22 @@ public String moveOrder(String orderNumber, BigDecimal rate) } @Override - public String sell(String currencyPair, BigDecimal sellPrice, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly) - { + public String sell(String currencyPair, BigDecimal sellPrice, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly) { return trade("sell", currencyPair, sellPrice, amount, fillOrKill, immediateOrCancel, postOnly); } @Override - public String buy(String currencyPair, BigDecimal buyPrice, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly) - { + public String buy(String currencyPair, BigDecimal buyPrice, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly) { return trade("buy", currencyPair, buyPrice, amount, fillOrKill, immediateOrCancel, postOnly); } // Lending APIs - @Override public String returnActiveLoans() { return returnTradingAPICommandResults("returnActiveLoans"); } - @Override + @Override public String returnLendingHistory(int hours, int limit) { List additionalPostParams = new ArrayList<>(); long currentUnixtime = System.currentTimeMillis() / 1000; @@ -134,8 +128,7 @@ public String returnLendingHistory(int hours, int limit) { } @Override - public String createLoanOffer(String currency, BigDecimal amount, BigDecimal lendingRate, int duration, boolean autoRenew) - { + public String createLoanOffer(String currency, BigDecimal amount, BigDecimal lendingRate, int duration, boolean autoRenew) { List additionalPostParams = new ArrayList<>(); additionalPostParams.add(new BasicNameValuePair("currency", currency)); @@ -149,29 +142,25 @@ public String createLoanOffer(String currency, BigDecimal amount, BigDecimal len } @Override - public String cancelLoanOffer(String orderNumber) - { + public String cancelLoanOffer(String orderNumber) { List additionalPostParams = new ArrayList<>(); additionalPostParams.add(new BasicNameValuePair("orderNumber", orderNumber)); return returnTradingAPICommandResults("cancelLoanOffer", additionalPostParams); } @Override - public String returnOpenLoanOffers() - { + public String returnOpenLoanOffers() { return returnTradingAPICommandResults("returnOpenLoanOffers"); } @Override - public String toggleAutoRenew(String orderNumber) - { + public String toggleAutoRenew(String orderNumber) { List additionalPostParams = new ArrayList<>(); additionalPostParams.add(new BasicNameValuePair("orderNumber", orderNumber)); return returnTradingAPICommandResults("toggleAutoRenew", additionalPostParams); } - private String trade(String tradeType, String currencyPair, BigDecimal rate, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly) - { + private String trade(String tradeType, String currencyPair, BigDecimal rate, BigDecimal amount, boolean fillOrKill, boolean immediateOrCancel, boolean postOnly) { List additionalPostParams = new ArrayList<>(); additionalPostParams.add(new BasicNameValuePair("currencyPair", currencyPair)); additionalPostParams.add(new BasicNameValuePair("rate", rate.toPlainString())); @@ -182,24 +171,19 @@ private String trade(String tradeType, String currencyPair, BigDecimal rate, Big return returnTradingAPICommandResults(tradeType, additionalPostParams); } - private String returnTradingAPICommandResults(String commandValue, List additionalPostParams) - { - try - { + private String returnTradingAPICommandResults(String commandValue, List additionalPostParams) { + try { List postParams = new ArrayList<>(); postParams.add(new BasicNameValuePair("command", commandValue)); postParams.add(new BasicNameValuePair("nonce", String.valueOf(System.currentTimeMillis()))); - if (additionalPostParams != null && additionalPostParams.size() > 0) - { + if (additionalPostParams != null && additionalPostParams.size() > 0) { postParams.addAll(additionalPostParams); } StringBuilder sb = new StringBuilder(); - for (NameValuePair postParam : postParams) - { - if (sb.length() > 0) - { + for (NameValuePair postParam : postParams) { + if (sb.length() > 0) { sb.append("&"); } sb.append(postParam.getName()).append("=").append(postParam.getValue()); @@ -215,17 +199,14 @@ private String returnTradingAPICommandResults(String commandValue, List list = new ArrayList(); return returnTradingAPICommandResults(commandValue, list); } diff --git a/src/main/java/com/cf/client/poloniex/PoloniexWSSClientRouter.java b/src/main/java/com/cf/client/poloniex/PoloniexWSSClientRouter.java index 0e94091..fe8f284 100644 --- a/src/main/java/com/cf/client/poloniex/PoloniexWSSClientRouter.java +++ b/src/main/java/com/cf/client/poloniex/PoloniexWSSClientRouter.java @@ -1,6 +1,6 @@ package com.cf.client.poloniex; -import com.cf.client.wss.handler.LoggerMessageHandler; +import com.cf.client.wss.handler.LoggingMessageHandler; import com.google.gson.Gson; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -47,7 +47,7 @@ public PoloniexWSSClientRouter(URI url, Map subscriptio public PoloniexWSSClientRouter(WebSocketClientHandshaker handshaker, Map subscriptions) { this.handshaker = handshaker; this.subscriptions = subscriptions; - this.defaultSubscriptionMessageHandler = new LoggerMessageHandler(); + this.defaultSubscriptionMessageHandler = new LoggingMessageHandler(); this.gson = new Gson(); } diff --git a/src/main/java/com/cf/client/poloniex/wss/model/PoloniexOrderBook.java b/src/main/java/com/cf/client/poloniex/wss/model/PoloniexOrderBook.java new file mode 100644 index 0000000..aea0630 --- /dev/null +++ b/src/main/java/com/cf/client/poloniex/wss/model/PoloniexOrderBook.java @@ -0,0 +1,30 @@ +package com.cf.client.poloniex.wss.model; + +import com.google.gson.Gson; +import java.util.Map; +import java.util.TreeMap; + +/** + * + * @author David + */ +public class PoloniexOrderBook { + + public final Map bids; + public final Map asks; + + public PoloniexOrderBook() { + this.bids = new TreeMap<>(); + this.asks = new TreeMap<>(); + } + + public PoloniexOrderBook(Map bids, Map asks) { + this.bids = bids; + this.asks = asks; + } + + @Override + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/com/cf/client/poloniex/wss/model/PoloniexOrderBookEntry.java b/src/main/java/com/cf/client/poloniex/wss/model/PoloniexOrderBookEntry.java new file mode 100644 index 0000000..193d7e7 --- /dev/null +++ b/src/main/java/com/cf/client/poloniex/wss/model/PoloniexOrderBookEntry.java @@ -0,0 +1,26 @@ +package com.cf.client.poloniex.wss.model; + +import com.google.gson.Gson; +import java.math.BigDecimal; + +/** + * + * @author David + */ +public class PoloniexOrderBookEntry { + + public final String type; + public final BigDecimal rate; + public final BigDecimal amount; + + public PoloniexOrderBookEntry(String type, BigDecimal rate, BigDecimal amount) { + this.type = type; + this.rate = rate; + this.amount = amount; + } + + @Override + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/com/cf/client/poloniex/wss/model/PoloniexWSSOrderBookUpdate.java b/src/main/java/com/cf/client/poloniex/wss/model/PoloniexWSSOrderBookUpdate.java new file mode 100644 index 0000000..96db59b --- /dev/null +++ b/src/main/java/com/cf/client/poloniex/wss/model/PoloniexWSSOrderBookUpdate.java @@ -0,0 +1,27 @@ +package com.cf.client.poloniex.wss.model; + +import com.google.gson.Gson; + +/** + * + * @author David + */ +public class PoloniexWSSOrderBookUpdate { + + public final Double currencyPair; + public final Double orderNumber; + public final PoloniexOrderBookEntry previousEntry; + public final PoloniexWSSOrderBookUpdate replacementEntry; + + public PoloniexWSSOrderBookUpdate(Double currencyPair, Double orderNumber, PoloniexOrderBookEntry previousEntry, PoloniexWSSOrderBookUpdate replacementEntry) { + this.currencyPair = currencyPair; + this.orderNumber = orderNumber; + this.previousEntry = previousEntry; + this.replacementEntry = replacementEntry; + } + + @Override + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/com/cf/client/wss/handler/LoggerMessageHandler.java b/src/main/java/com/cf/client/wss/handler/LoggingMessageHandler.java similarity index 82% rename from src/main/java/com/cf/client/wss/handler/LoggerMessageHandler.java rename to src/main/java/com/cf/client/wss/handler/LoggingMessageHandler.java index e065018..5142f04 100644 --- a/src/main/java/com/cf/client/wss/handler/LoggerMessageHandler.java +++ b/src/main/java/com/cf/client/wss/handler/LoggingMessageHandler.java @@ -7,7 +7,7 @@ * * @author David */ -public class LoggerMessageHandler implements IMessageHandler { +public class LoggingMessageHandler implements IMessageHandler { private final static Logger LOG = LogManager.getLogger(); diff --git a/src/main/java/com/cf/client/wss/handler/NoOpMessageHandler.java b/src/main/java/com/cf/client/wss/handler/NoOpMessageHandler.java new file mode 100644 index 0000000..6ed0381 --- /dev/null +++ b/src/main/java/com/cf/client/wss/handler/NoOpMessageHandler.java @@ -0,0 +1,15 @@ + +package com.cf.client.wss.handler; + +/** + * + * @author David + */ +public class NoOpMessageHandler implements IMessageHandler { + + @Override + public void handle(String message) { + // do nothing + } + +} diff --git a/src/main/java/com/cf/client/wss/handler/TickerMessageHandler.java b/src/main/java/com/cf/client/wss/handler/TickerMessageHandler.java index 3acac47..603e669 100644 --- a/src/main/java/com/cf/client/wss/handler/TickerMessageHandler.java +++ b/src/main/java/com/cf/client/wss/handler/TickerMessageHandler.java @@ -18,9 +18,8 @@ public class TickerMessageHandler implements IMessageHandler { @Override public void handle(String message) { - LOG.trace(message); PoloniexWSSTicker ticker = this.mapMessageToPoloniexTicker(message); - LOG.trace(ticker); + LOG.debug(ticker); } 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 ada9748..f97312d 100644 --- a/src/main/java/com/cf/data/map/poloniex/PoloniexDataMapper.java +++ b/src/main/java/com/cf/data/map/poloniex/PoloniexDataMapper.java @@ -9,6 +9,7 @@ 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.deserialize.PoloniexChartDataDeserializer; @@ -89,7 +90,7 @@ public PoloniexFeeInfo mapFeeInfo(String feeInfoResult) { } public PoloniexActiveLoanTypes mapActiveLoans(String activeLoansResult) { - + PoloniexActiveLoanTypes activeLoanTypes = gson.fromJson(activeLoansResult, PoloniexActiveLoanTypes.class); return activeLoanTypes; @@ -147,6 +148,12 @@ public PoloniexOrderResult mapTradeOrder(String orderResult) { return tradeOrderResult; } + public List mapOrderTrades(String orderTradesResult) { + List orderTrades = gson.fromJson(orderTradesResult, new TypeToken>() { + }.getType()); + return orderTrades; + } + public List mapLendingHistory(String lendingHistoryResults) { List lendingHistory = gson.fromJson(lendingHistoryResults, new TypeToken>() { }.getType()); diff --git a/src/main/java/com/cf/data/model/poloniex/PoloniexOrderTrade.java b/src/main/java/com/cf/data/model/poloniex/PoloniexOrderTrade.java new file mode 100644 index 0000000..3e4c639 --- /dev/null +++ b/src/main/java/com/cf/data/model/poloniex/PoloniexOrderTrade.java @@ -0,0 +1,39 @@ +package com.cf.data.model.poloniex; + +import com.google.gson.Gson; +import java.math.BigDecimal; +import java.time.ZonedDateTime; + +/** + * + * @author David + */ +public class PoloniexOrderTrade { + + public final Long globalTradeID; + public final Long tradeID; + public final String currencyPair; + public final String type; + public final BigDecimal rate; + public final BigDecimal amount; + public final BigDecimal total; + public final BigDecimal fee; + public final ZonedDateTime date; + + public PoloniexOrderTrade(Long globalTradeID, Long tradeID, String currencyPair, String type, BigDecimal rate, BigDecimal amount, BigDecimal total, BigDecimal fee, ZonedDateTime date) { + this.globalTradeID = globalTradeID; + this.tradeID = tradeID; + this.currencyPair = currencyPair; + this.type = type; + this.rate = rate; + this.amount = amount; + this.total = total; + this.fee = fee; + this.date = date; + } + + @Override + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/src/main/java/com/cf/example/PoloniexWSSClientExample.java b/src/main/java/com/cf/example/PoloniexWSSClientExample.java index 9bc4667..d1a0af3 100644 --- a/src/main/java/com/cf/example/PoloniexWSSClientExample.java +++ b/src/main/java/com/cf/example/PoloniexWSSClientExample.java @@ -2,7 +2,6 @@ import com.cf.client.WSSClient; import com.cf.client.poloniex.wss.model.PoloniexWSSSubscription; -import com.cf.client.wss.handler.LoggerMessageHandler; import com.cf.client.wss.handler.TickerMessageHandler; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -11,36 +10,32 @@ * * @author David */ -public class PoloniexWSSClientExample -{ +public class PoloniexWSSClientExample { + private static final Logger LOG = LogManager.getLogger(PoloniexWSSClientExample.class); private static final String ENDPOINT_URL = "wss://api2.poloniex.com"; - public static void main(String[] args) - { - try - { - new PoloniexWSSClientExample().run(); - } - catch (InterruptedException ex) + public static void main(String[] args) { + try { + new PoloniexWSSClientExample().subscribe(); + } catch (InterruptedException ex) { + LOG.info(ex.getMessage()); + System.exit(0); + } catch (Exception ex) { { LOG.info(ex.getMessage()); System.exit(0); } - catch (Exception ex) - { LOG.fatal("An exception occurred when running PoloniexWSSClientExample - {}", ex.getMessage()); System.exit(-1); } } - public void run() throws Exception - { - try (WSSClient wssClient = new WSSClient(ENDPOINT_URL)) - { - wssClient.addSubscription(PoloniexWSSSubscription.USDT_ETH, new LoggerMessageHandler()); + public void subscribe() throws Exception { + try (WSSClient wssClient = new WSSClient(ENDPOINT_URL)) { wssClient.addSubscription(PoloniexWSSSubscription.TICKER, new TickerMessageHandler()); wssClient.run(60000); } + } } diff --git a/src/test/java/com/cf/data/map/poloniex/PoloniexDataMapperTest.java b/src/test/java/com/cf/data/map/poloniex/PoloniexDataMapperTest.java index 4443d7a..26e1f30 100644 --- a/src/test/java/com/cf/data/map/poloniex/PoloniexDataMapperTest.java +++ b/src/test/java/com/cf/data/map/poloniex/PoloniexDataMapperTest.java @@ -4,6 +4,7 @@ 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.PoloniexTradeHistory; import java.math.BigDecimal; import java.time.ZoneOffset; @@ -242,4 +243,20 @@ public void mapTradeHistory() { assertEquals("exchange", first.category); } + @Test + public void mapOrderTrades() { + String data = "[{\"globalTradeID\": 20825863, \"tradeID\": 147142, \"currencyPair\": \"BTC_XVC\", \"type\": \"buy\", \"rate\": \"0.00018500\", \"amount\": \"455.34206390\", \"total\": \"0.08423828\", \"fee\": \"0.00200000\", \"date\": \"2016-03-14 01:04:36\"}, {\"globalTradeID\": 20825864, \"tradeID\": 147143, \"currencyPair\": \"BTC_XVC\", \"type\": \"buy\", \"rate\": \"0.00018500\", \"amount\": \"455.34206390\", \"total\": \"0.08423828\", \"fee\": \"0.00200000\", \"date\": \"2016-03-14 01:04:36\"}]"; + List orderTrades = mapper.mapOrderTrades(data); + assertEquals(2, orderTrades.size()); + + PoloniexOrderTrade first = orderTrades.get(0); + assertEquals(20825863L, first.globalTradeID.longValue()); + assertEquals(147142L, first.tradeID.longValue()); + assertEquals("2016-03-14T01:04:36Z", first.date.toString()); + assertEquals("0.00018500", first.rate.toPlainString()); + assertEquals("0.00200000", first.fee.toPlainString()); + assertEquals("buy", first.type); + assertEquals("BTC_XVC", first.currencyPair); + } + }