package org.knowm.xchange.ripple.service;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import org.knowm.xchange.dto.Order;
import org.knowm.xchange.dto.trade.LimitOrder;
import org.knowm.xchange.dto.trade.MarketOrder;
import org.knowm.xchange.dto.trade.OpenOrders;
import org.knowm.xchange.dto.trade.UserTrades;
import org.knowm.xchange.exceptions.ExchangeException;
import org.knowm.xchange.exceptions.NotAvailableFromExchangeException;
import org.knowm.xchange.exceptions.NotYetImplementedForExchangeException;
import org.knowm.xchange.ripple.RippleAdapters;
import org.knowm.xchange.ripple.RippleExchange;
import org.knowm.xchange.ripple.dto.trade.IRippleTradeTransaction;
import org.knowm.xchange.ripple.dto.trade.RippleLimitOrder;
import org.knowm.xchange.ripple.service.params.RippleTradeHistoryAccount;
import org.knowm.xchange.ripple.service.params.RippleTradeHistoryCount;
import org.knowm.xchange.ripple.service.params.RippleTradeHistoryHashLimit;
import org.knowm.xchange.ripple.service.params.RippleTradeHistoryParams;
import org.knowm.xchange.service.trade.TradeService;
import org.knowm.xchange.service.trade.params.TradeHistoryParamPaging;
import org.knowm.xchange.service.trade.params.TradeHistoryParams;
import org.knowm.xchange.service.trade.params.TradeHistoryParamsTimeSpan;
import org.knowm.xchange.service.trade.params.orders.OpenOrdersParams;
public class RippleTradeService extends RippleTradeServiceRaw implements TradeService {
private final RippleExchange ripple;
/**
* Empty placeholder trade history parameter object.
*/
private final RippleTradeHistoryParams defaultTradeHistoryParams = createTradeHistoryParams();
public RippleTradeService(final RippleExchange exchange) {
super(exchange);
ripple = exchange;
}
/**
* The additional data map of an order will be populated with {@link RippleExchange.DATA_BASE_COUNTERPARTY} if the base currency is not XRP,
* similarly if the counter currency is not XRP then {@link RippleExchange.DATA_COUNTER_COUNTERPARTY} will be populated.
*/
@Override
public OpenOrders getOpenOrders() throws ExchangeException, NotAvailableFromExchangeException, NotYetImplementedForExchangeException, IOException {
return getOpenOrders(createOpenOrdersParams());
}
@Override
public OpenOrders getOpenOrders(OpenOrdersParams params) throws ExchangeException, NotAvailableFromExchangeException, NotYetImplementedForExchangeException, IOException {
return RippleAdapters.adaptOpenOrders(getOpenAccountOrders(), ripple.getRoundingScale());
}
@Override
public String placeMarketOrder(final MarketOrder order)
throws ExchangeException, NotAvailableFromExchangeException, NotYetImplementedForExchangeException, IOException {
throw new NotYetImplementedForExchangeException();
}
/**
* @param order this should be a RippleLimitOrder object with the base and counter counterparties populated for any currency other than XRP.
*/
@Override
public String placeLimitOrder(final LimitOrder order)
throws ExchangeException, NotAvailableFromExchangeException, NotYetImplementedForExchangeException, IOException {
if (order instanceof RippleLimitOrder) {
return placeOrder((RippleLimitOrder) order, ripple.validateOrderRequests());
} else {
throw new IllegalArgumentException("order must be of type: " + RippleLimitOrder.class.getName());
}
}
@Override
public boolean cancelOrder(final String orderId)
throws ExchangeException, NotAvailableFromExchangeException, NotYetImplementedForExchangeException, IOException {
return cancelOrder(orderId, ripple.validateOrderRequests());
}
/**
* Ripple trade history is a request intensive process. The REST API does not provide a simple single trade history query. Trades are retrieved by
* querying account notifications and for those of type order details of the hash are then queried. These order detail queries could be order entry,
* cancel or execution, it is not possible to tell from the notification. Therefore if an account is entering many orders but executing few of them,
* this trade history query will result in many API calls without returning any trade history. In order to reduce the time and resources used in
* these repeated calls In order to reduce the number of API calls a number of different methods can be used:
* <ul>
* <li><b>RippleTradeHistoryHashLimit</b> set the {@link RippleTradeHistoryHashLimit#setHashLimit(String)} to the last known trade, this query will
* then terminate once it has been found.</li>
* <li><b>RippleTradeHistoryCount</b> set the {@link RippleTradeHistoryCount#setTradeCountLimit(int)} to restrict the number of trades to return,
* the default is {@link RippleTradeHistoryCount#DEFAULT_TRADE_COUNT_LIMIT}.</li>
* <li><b>RippleTradeHistoryCount</b> set the {@link RippleTradeHistoryCount#setApiCallCountLimit(int)} to restrict the number of API calls that
* will be made during a single trade history query, the default is {@link RippleTradeHistoryCount#DEFAULT_API_CALL_COUNT}.</li>
* <li><b>TradeHistoryParamsTimeSpan</b> set the {@link TradeHistoryParamsTimeSpan#setStartTime(java.util.Date)} to limit the number of trades
* searched for to those done since the given start time.</li> TradeHistoryParamsTimeSpan
* </ul>
*
* @param params Can optionally implement {@RippleTradeHistoryAccount}, {@RippleTradeHistoryCount}, {@RippleTradeHistoryHashLimit},
* {@RippleTradeHistoryPreferredCurrencies}, {@link TradeHistoryParamPaging}, {@TradeHistoryParamCurrencyPair},
* {@link TradeHistoryParamsTimeSpan}. All other TradeHistoryParams types will be ignored.
*/
@Override
public UserTrades getTradeHistory(final TradeHistoryParams params) throws IOException {
if (params instanceof RippleTradeHistoryCount) {
final RippleTradeHistoryCount rippleParams = (RippleTradeHistoryCount) params;
rippleParams.resetApiCallCount();
rippleParams.resetTradeCount();
}
final String account;
if (params instanceof RippleTradeHistoryAccount) {
final RippleTradeHistoryAccount rippleAccount = (RippleTradeHistoryAccount) params;
if (rippleAccount.getAccount() != null) {
account = rippleAccount.getAccount();
} else {
account = exchange.getExchangeSpecification().getApiKey();
}
} else {
account = defaultTradeHistoryParams.getAccount();
}
final List<IRippleTradeTransaction> trades = getTradesForAccount(params, account);
return RippleAdapters.adaptTrades(trades, params, (RippleAccountService) exchange.getAccountService(), ripple.getRoundingScale());
}
@Override
public Collection<Order> getOrder(String... orderIds)
throws ExchangeException, NotAvailableFromExchangeException, NotYetImplementedForExchangeException, IOException {
throw new NotYetImplementedForExchangeException();
}
@Override
public RippleTradeHistoryParams createTradeHistoryParams() {
final RippleTradeHistoryParams params = new RippleTradeHistoryParams();
params.setAccount(exchange.getExchangeSpecification().getApiKey());
return params;
}
@Override
public OpenOrdersParams createOpenOrdersParams() {
return null;
}
}