Skip to content

Commit

Permalink
dragonex.io implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
andre77 committed Nov 15, 2018
1 parent 1668ae4 commit 72d1714
Show file tree
Hide file tree
Showing 39 changed files with 1,643 additions and 0 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@
<module>xchange-cryptopia</module>
<module>xchange-coinsuper</module>
<module>xchange-dsx</module>
<module>xchange-dragonex</module>
<module>xchange-exmo</module>
<module>xchange-exx</module>
<module>xchange-examples</module>
Expand Down
6 changes: 6 additions & 0 deletions xchange-dragonex/api-specification.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Dragonex Exchange API specification
================================

Documentation
-------------
https://github.com/Dragonexio/OpenApi/tree/master/docs
33 changes: 33 additions & 0 deletions xchange-dragonex/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.knowm.xchange</groupId>
<artifactId>xchange-parent</artifactId>
<version>4.3.13-SNAPSHOT</version>
</parent>

<artifactId>xchange-dragonex</artifactId>
<name>XChange Dragonex</name>
<description>XChange implementation for the Dragonex Exchange</description>

<url>http://knowm.org/open-source/xchange/</url>
<inceptionYear>2018</inceptionYear>

<organization>
<name>Knowm Inc.</name>
<url>http://knowm.org/open-source/xchange/</url>
</organization>

<dependencies>

<dependency>
<groupId>org.knowm.xchange</groupId>
<artifactId>xchange-core</artifactId>
<version>${project.version}</version>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.knowm.xchange.dragonex;

import java.io.IOException;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.knowm.xchange.dragonex.dto.DragonResult;
import org.knowm.xchange.dragonex.dto.DragonexException;
import org.knowm.xchange.dragonex.dto.marketdata.Coin;
import org.knowm.xchange.dragonex.dto.marketdata.Order;
import org.knowm.xchange.dragonex.dto.marketdata.Symbol;
import org.knowm.xchange.dragonex.dto.marketdata.Ticker;

@Path("api/v1")
@Produces(MediaType.APPLICATION_JSON)
public interface Dragonex {

/** Query all coins in DragonEx Platform */
@GET
@Path("coin/all/")
DragonResult<List<Coin>> coinAll() throws DragonexException, IOException;

/** Query all exchange pairs */
@GET
@Path("symbol/all/")
DragonResult<List<Symbol>> symbolAll() throws DragonexException, IOException;

/** Query K line @TODO */
/*@GET
@Path("market/kline/")
DragonResult<KLine> kLine() throws DragonexException, IOException;*/

/** Query buy orders quotes */
@GET
@Path("market/buy/")
DragonResult<List<Order>> marketBuyOrders(@QueryParam("symbol_id") long symbolId)
throws DragonexException, IOException;

/** Query sell orders quotes */
@GET
@Path("market/sell/")
DragonResult<List<Order>> marketSellOrders(@QueryParam("symbol_id") long symbolId)
throws DragonexException, IOException;

/** Query real time quotes */
@GET
@Path("market/real/")
DragonResult<List<Ticker>> ticker(@QueryParam("symbol_id") long symbolId)
throws DragonexException, IOException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.knowm.xchange.dragonex;

public class DragonexAdapters {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package org.knowm.xchange.dragonex;

import java.io.IOException;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import org.knowm.xchange.dragonex.dto.DragonResult;
import org.knowm.xchange.dragonex.dto.DragonexException;
import org.knowm.xchange.dragonex.dto.Token;
import org.knowm.xchange.dragonex.dto.TokenStatus;
import org.knowm.xchange.dragonex.dto.account.Balance;
import org.knowm.xchange.dragonex.dto.trade.DealHistory;
import org.knowm.xchange.dragonex.dto.trade.DealHistoryRequest;
import org.knowm.xchange.dragonex.dto.trade.OrderHistory;
import org.knowm.xchange.dragonex.dto.trade.OrderHistoryRequest;
import org.knowm.xchange.dragonex.dto.trade.OrderPlacement;
import org.knowm.xchange.dragonex.dto.trade.OrderReference;
import org.knowm.xchange.dragonex.dto.trade.UserOrder;
import si.mazi.rescu.ParamsDigest;

/** https://github.com/Dragonexio/OpenApi/blob/master/docs/English/1.interface_document_v1.md */
@Path("api/v1")
@Consumes(MediaType.APPLICATION_JSON)
public interface DragonexAuthenticated {

/** Create new token */
@POST
@Path("token/new/")
DragonResult<Token> tokenNew(
@HeaderParam("date") String date,
@HeaderParam("auth") ParamsDigest auth,
@HeaderParam("content-sha1") ParamsDigest contentSHA1)
throws DragonexException, IOException;

/** Token status */
@POST
@Path("token/status/")
DragonResult<TokenStatus> tokenStatus(
@HeaderParam("date") String date,
@HeaderParam("token") String token,
@HeaderParam("auth") ParamsDigest auth,
@HeaderParam("content-sha1") ParamsDigest contentSHA1)
throws DragonexException, IOException;

/** Query all coins you own */
@POST
@Path("user/own/")
DragonResult<List<Balance>> userCoins(
@HeaderParam("date") String date,
@HeaderParam("token") String token,
@HeaderParam("auth") ParamsDigest auth,
@HeaderParam("content-sha1") ParamsDigest contentSHA1)
throws DragonexException, IOException;

/** Add new buy order */
@POST
@Path("order/buy/")
DragonResult<UserOrder> orderBuy(
@HeaderParam("date") String date,
@HeaderParam("token") String token,
@HeaderParam("auth") ParamsDigest auth,
@HeaderParam("Content-Sha1") ParamsDigest contentSHA1,
OrderPlacement orderPlacement)
throws DragonexException, IOException;

/** Add new sell order */
@POST
@Path("order/sell/")
DragonResult<UserOrder> orderSell(
@HeaderParam("date") String date,
@HeaderParam("token") String token,
@HeaderParam("auth") ParamsDigest auth,
@HeaderParam("Content-Sha1") ParamsDigest contentSHA1,
OrderPlacement orderPlacement)
throws DragonexException, IOException;

/** Cancel Order */
@POST
@Path("order/cancel/")
DragonResult<UserOrder> orderCancel(
@HeaderParam("date") String date,
@HeaderParam("token") String token,
@HeaderParam("auth") ParamsDigest auth,
@HeaderParam("Content-Sha1") ParamsDigest contentSHA1,
OrderReference ref)
throws DragonexException, IOException;

/** Request details of user’s delegation records */
@POST
@Path("order/detail/")
DragonResult<UserOrder> orderDetail(
@HeaderParam("date") String date,
@HeaderParam("token") String token,
@HeaderParam("auth") ParamsDigest auth,
@HeaderParam("Content-Sha1") ParamsDigest contentSHA1,
OrderReference ref)
throws DragonexException, IOException;

/** Request user’s delegation records */
@POST
@Path("order/history/")
DragonResult<OrderHistory> orderHistory(
@HeaderParam("date") String date,
@HeaderParam("token") String token,
@HeaderParam("auth") ParamsDigest auth,
@HeaderParam("Content-Sha1") ParamsDigest contentSHA1,
OrderHistoryRequest orderHistory)
throws DragonexException, IOException;

/** Request user’s records of successful trade */
@POST
@Path("deal/history/")
DragonResult<DealHistory> dealHistory(
@HeaderParam("date") String date,
@HeaderParam("token") String token,
@HeaderParam("auth") ParamsDigest auth,
@HeaderParam("Content-Sha1") ParamsDigest contentSHA1,
DealHistoryRequest orderHistory)
throws DragonexException, IOException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.knowm.xchange.dragonex;

import org.apache.commons.lang3.StringUtils;
import org.knowm.xchange.dragonex.dto.DragonexException;
import org.knowm.xchange.exceptions.CurrencyPairNotValidException;
import org.knowm.xchange.exceptions.ExchangeException;
import org.knowm.xchange.exceptions.ExchangeSecurityException;

/** @author walec51 */
public class DragonexErrorAdapter {

private static final String INVALID_CURRENCY_MESSAGE_START = "Invalid currency pair";

public static ExchangeException adapt(DragonexException e) {
switch (e.getHttpStatusCode()) {
case 403:
return new ExchangeSecurityException(e);
default:
return adaptBasedOnErrorMessage(e);
}
}

private static ExchangeException adaptBasedOnErrorMessage(DragonexException e) {
String message = e.getError();
if (StringUtils.isEmpty(message)) {
return new ExchangeException("Operation failed without any error message");
}
if (message.startsWith(INVALID_CURRENCY_MESSAGE_START)) {
return new CurrencyPairNotValidException(message);
}
return new ExchangeException(message, e);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package org.knowm.xchange.dragonex;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.knowm.xchange.BaseExchange;
import org.knowm.xchange.Exchange;
import org.knowm.xchange.ExchangeSpecification;
import org.knowm.xchange.currency.CurrencyPair;
import org.knowm.xchange.dragonex.dto.DragonexException;
import org.knowm.xchange.dragonex.dto.Token;
import org.knowm.xchange.dragonex.dto.marketdata.Coin;
import org.knowm.xchange.dragonex.dto.marketdata.Symbol;
import org.knowm.xchange.dragonex.service.DragonDigest;
import org.knowm.xchange.dragonex.service.DragonexAccountService;
import org.knowm.xchange.dragonex.service.DragonexAccountServiceRaw;
import org.knowm.xchange.dragonex.service.DragonexMarketDataService;
import org.knowm.xchange.dragonex.service.DragonexTradeService;
import org.knowm.xchange.exceptions.ExchangeException;
import si.mazi.rescu.ClientConfig;
import si.mazi.rescu.ParamsDigest;
import si.mazi.rescu.RestProxyFactory;
import si.mazi.rescu.SynchronizedValueFactory;

public class DragonexExchange extends BaseExchange implements Exchange {

private Dragonex dragonexPublic;
private DragonexAuthenticated dragonexAuthenticated;
private ParamsDigest signatureCreator;
private final AtomicReference<Token> currentToken = new AtomicReference<>();
private final Map<Long, String> coins = new HashMap<>();
private Map<Long, CurrencyPair> symbols = new HashMap<>();
private Map<CurrencyPair, Long> pairs = new HashMap<>();

@Override
protected void initServices() {
this.marketDataService = new DragonexMarketDataService(this);
this.accountService = new DragonexAccountService(this);
this.tradeService = new DragonexTradeService(this);

ClientConfig rescuConfig =
((DragonexMarketDataService) this.marketDataService).getClientConfig();
ExchangeSpecification spec = this.getExchangeSpecification();
this.dragonexPublic =
RestProxyFactory.createProxy(Dragonex.class, spec.getSslUri(), rescuConfig);

if (spec.getApiKey() != null && spec.getSecretKey() != null) {
this.dragonexAuthenticated =
RestProxyFactory.createProxy(DragonexAuthenticated.class, spec.getSslUri(), rescuConfig);
this.signatureCreator = new DragonDigest(spec.getApiKey(), spec.getSecretKey());
}

Token token = (Token) spec.getExchangeSpecificParametersItem("dragonex.token");
currentToken.set(token);
}

public CurrencyPair pair(long symbolId) {
return symbols.get(symbolId);
}

public long symbolId(CurrencyPair pair) {
Long symbolId = pairs.get(pair);
if (symbolId == null) {
throw new ExchangeException("Not supported pair " + pair + " by Dragonex.");
}
return symbolId;
}

public Token getOrCreateToken() throws DragonexException, IOException {
Token token = currentToken.get();
if (token != null && token.valid()) {
return token;
}
synchronized (currentToken) {
token = currentToken.get();
if (token != null && token.valid()) {
return token;
}
token = ((DragonexAccountServiceRaw) accountService).tokenNew();
currentToken.set(token);
}
return token;
}

public Dragonex dragonexPublic() {
return dragonexPublic;
}

public DragonexAuthenticated dragonexAuthenticated() {
return dragonexAuthenticated;
}

public ParamsDigest signatureCreator() {
return signatureCreator;
}

@Override
public ExchangeSpecification getDefaultExchangeSpecification() {
ExchangeSpecification spec = new ExchangeSpecification(this.getClass().getCanonicalName());
spec.setSslUri("https://openapi.dragonex.io/");
spec.setHost("openapi.dragonex.io");
spec.setPort(80);
spec.setExchangeName("Dragonex");
spec.setExchangeDescription("Dragonex is a bitcoin and altcoin exchange.");
return spec;
}

@Override
public SynchronizedValueFactory<Long> getNonceFactory() {
throw new ExchangeException("Dragonex does not require a nonce factory.");
}

@Override
public void remoteInit() throws IOException, ExchangeException {
try {
List<Coin> coinAll = ((DragonexMarketDataService) marketDataService).coinAll();
coinAll.forEach(c -> coins.put(c.coinId, c.code));
List<Symbol> symbolAll = ((DragonexMarketDataService) marketDataService).symbolAll();
symbolAll.forEach(
c -> {
CurrencyPair pair = new CurrencyPair(c.symbol.toUpperCase().replace('_', '/'));
symbols.put(c.symbolId, pair);
pairs.put(pair, c.symbolId);
});
} catch (Throwable e) {
throw new RuntimeException("Could not initialize the Dragonex service.", e);
}
}
}
Loading

0 comments on commit 72d1714

Please sign in to comment.