Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions example/java/example/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.4.2</version>
<version>4.8.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp-ws</artifactId>
<version>3.4.2</version>
<groupId>com.neovisionaries</groupId>
<artifactId>nv-websocket-client</artifactId>
<version>2.9</version>
</dependency>
</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
public class Authorization {

private String apiKey;
private String secretKey;
private Mac hmac;
private byte[] hmacKey;
private SecretKeySpec keySpec;
Expand All @@ -20,7 +19,6 @@ public class Authorization {
*/
public Authorization(String apiKey, String secretKey) {
this.apiKey = apiKey;
this.secretKey = secretKey;

hmacKey = Base64.getDecoder().decode(secretKey);
try {
Expand All @@ -35,23 +33,45 @@ public Authorization(String apiKey, String secretKey) {

/**
* @return authorization headers
* @param url path for generating specific signature
* @param path path for generating specific signature
* @param timestamp milliseconds since UNIX epoch in UTC
*/
public Map<String, String> getHeaderMap(String url, long timestamp) {
public Map<String, String> getHeaderMap(String path, long timestamp) {
Map<String, String> headers = new HashMap<>();
headers.put("x-auth-key", apiKey);
headers.put("x-auth-signature", generateSig(url, timestamp));
headers.put("x-auth-timestamp", timestamp + "");
headers.put("x-auth-signature", generateSig(path, timestamp));
headers.put("x-auth-timestamp", String.valueOf(timestamp));
return headers;
}

/**
* @return authorization headers
* @param path path for generating specific signature
* @param timestamp milliseconds since UNIX epoch in UTC
* @param coid generated unique orderId
*/
public Map<String, String> getHeaderMap(String path, long timestamp, String coid) {
Map<String, String> headers = new HashMap<>();
headers.put("x-auth-key", apiKey);
headers.put("x-auth-signature", generateSig(path, timestamp, coid));
headers.put("x-auth-timestamp", String.valueOf(timestamp));
headers.put("x-auth-coid", coid);
return headers;
}

/**
* @return signature, signed using sha256 using the base64-decoded secret key
*/
private String generateSig(String url, long timestamp) {
String prehash = timestamp + "+" + url;
byte[] encoded = Base64.getEncoder().encode(hmac.doFinal(prehash.getBytes(StandardCharsets.UTF_8)));
return new String(encoded);
String preHash = timestamp + "+" + url;
return new String(Base64.getEncoder().encode(hmac.doFinal(preHash.getBytes(StandardCharsets.UTF_8))));
}

/**
* @return signature, signed using sha256 using the base64-decoded secret key
*/
private String generateSig(String url, long timestamp, String coid) {
String preHash = timestamp + "+" + url + "+" + coid;
return new String(Base64.getEncoder().encode(hmac.doFinal(preHash.getBytes(StandardCharsets.UTF_8))));
}
}
4 changes: 2 additions & 2 deletions example/java/example/src/main/java/io/bitmax/api/Mapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
* Converts json to java object and vice versa
*/

public class Mapper {
public class Mapper {
private static ObjectMapper mapper = new ObjectMapper();

/**
* @param json string in json-format
* @param json string in json-format
* @param clazz class of object for converting from json to java object
* @return an object with type <T> and data from json
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package io.bitmax.api.rest.client;

import io.bitmax.api.Mapper;
import io.bitmax.api.rest.messages.responses.BarHist;
import io.bitmax.api.rest.messages.responses.Product;
import io.bitmax.api.rest.messages.responses.RestBarHist;
import io.bitmax.api.rest.messages.responses.RestProduct;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
Expand Down Expand Up @@ -33,7 +33,7 @@ public BitMaxRestApiClient() {
* @param interval bars interval
* @param limit max bars count
*/
public BarHist[] getCandlestickBars(String symbol, Interval interval, int limit) {
public RestBarHist[] getCandlestickBars(String symbol, Interval interval, int limit) {
long[] between = getFrom(interval, limit);
String params = "?symbol=" + symbol + "&interval="+interval+"&from=" + between[0] + "&to=" + between[1];

Expand All @@ -44,7 +44,7 @@ public BarHist[] getCandlestickBars(String symbol, Interval interval, int limit)
.build()
).execute();

return Mapper.asObject(result.body().string(), BarHist[].class);
return Mapper.asObject(result.body().string(), RestBarHist[].class);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
Expand All @@ -54,15 +54,15 @@ public BarHist[] getCandlestickBars(String symbol, Interval interval, int limit)
/**
* @return Each market summary data record contains current information about every product.
*/
public Product[] getProducts() {
public RestProduct[] getProducts() {
try {
Response result = client.newCall(new Request.Builder()
.url(URL + API + PATH_PRODUCTS)
.get()
.build()
).execute();

return Mapper.asObject(result.body().string(), Product[].class);
return Mapper.asObject(result.body().string(), RestProduct[].class);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import io.bitmax.api.Authorization;
import io.bitmax.api.Mapper;
import io.bitmax.api.rest.messages.responses.OpenOrdersList;
import io.bitmax.api.rest.messages.responses.OrderDetails;
import io.bitmax.api.rest.messages.responses.UserInfo;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import io.bitmax.api.rest.messages.requests.RestCancelOrderRequest;
import io.bitmax.api.rest.messages.responses.RestOpenOrdersList;
import io.bitmax.api.rest.messages.responses.RestOrderDetails;
import io.bitmax.api.rest.messages.responses.RestUserInfo;
import io.bitmax.api.rest.messages.requests.RestPlaceOrderRequest;
import okhttp3.*;

import java.util.Map;

Expand All @@ -31,8 +31,9 @@ public BitMaxRestApiClientAccount(String apiKey, String secret) {

/**
* @return 'UserInfo' object that contains 'userGroup' field
* @throws RuntimeException throws if something wrong (e.g. not correct response)
*/
public UserInfo getUserInfo() {
public RestUserInfo getUserInfo() {
Map<String, String> headers = authClient.getHeaderMap(PATH_INFO, System.currentTimeMillis());

Request.Builder builder = new Request.Builder()
Expand All @@ -43,20 +44,14 @@ public UserInfo getUserInfo() {
builder.header(entry.getKey(), entry.getValue());
}

try {
Response response = client.newCall(builder.build()).execute();

return Mapper.asObject(response.body().string(), UserInfo.class);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return executeRequest(builder.build(), RestUserInfo.class);
}

/**
* @return list of open orders
* @throws RuntimeException throws if something wrong (e.g. not correct response)
*/
public OpenOrdersList getOpenOrders() {
public RestOpenOrdersList getOpenOrders() {
Map<String, String> headers = authClient.getHeaderMap(PATH_ORDERS, System.currentTimeMillis());

Request.Builder builder = new Request.Builder()
Expand All @@ -67,35 +62,85 @@ public OpenOrdersList getOpenOrders() {
builder.header(entry.getKey(), entry.getValue());
}

try {
Response response = client.newCall(builder.build()).execute();
return executeRequest(builder.build(), RestOpenOrdersList.class);
}

/**
* @param coid id of expected order
* @return detailed info about specific order
* @throws RuntimeException throws if something wrong (e.g. not correct response)
*/
public RestOrderDetails getOrder(String coid) {
Map<String, String> headers = authClient.getHeaderMap(PATH_ORDER, System.currentTimeMillis());

Request.Builder builder = new Request.Builder()
.url(URL + accountGroup + '/' + API + PATH_ORDER + '/' + coid)
.get();

for (Map.Entry<String, String> entry : headers.entrySet()) {
builder.header(entry.getKey(), entry.getValue());
}

return executeRequest(builder.build(), RestOrderDetails.class);
}

return Mapper.asObject(response.body().string(), OpenOrdersList.class);
/**
* @param order is object which contains information about order
* @return Response - object which contains information about result place order request
* @throws RuntimeException throws if something wrong (order was not published)
*/
public Response placeOrder(RestPlaceOrderRequest order) {
long timestamp = System.currentTimeMillis();
Map<String, String> headers = authClient.getHeaderMap(PATH_ORDER, timestamp, order.getCoid());

RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), Mapper.asString(order));

Request.Builder builder = new Request.Builder()
.url(URL + accountGroup + '/' + API + PATH_ORDER)
.post(body);

for (Map.Entry<String, String> entry : headers.entrySet()) {
builder.header(entry.getKey(), entry.getValue());
}

try {
return client.newCall(builder.build()).execute();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}

/**
* @return detailed info about specific order
* @param coid id of expected order
* @param order is object which contains information about order
* @return Response - object which contains information about result cancel order request
* @throws RuntimeException throws if something wrong (order was not cancelled)
*/
public OrderDetails getOrder(String coid) {
Map<String, String> headers = authClient.getHeaderMap(PATH_ORDER, System.currentTimeMillis());
public Response cancelOrder(RestCancelOrderRequest order) {
long timestamp = System.currentTimeMillis();
Map<String, String> headers = authClient.getHeaderMap(PATH_ORDER, timestamp, order.getCoid());

RequestBody body = RequestBody.create(MediaType.parse("application/json"), Mapper.asString(order));

Request.Builder builder = new Request.Builder()
.url(URL + accountGroup + '/' + API + PATH_ORDER + '/' + coid)
.get();
.url(URL + accountGroup + '/' + API + PATH_ORDER)
.delete(body);

for (Map.Entry<String, String> entry : headers.entrySet()) {
builder.header(entry.getKey(), entry.getValue());
}

try {
Response response = client.newCall(builder.build()).execute();
return client.newCall(builder.build()).execute();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}

return Mapper.asObject(response.body().string(), OrderDetails.class);
private <T> T executeRequest(Request request, Class<T> clazz) {
try {
return Mapper.asObject(client.newCall(request).execute().body().string(), clazz);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package io.bitmax.api.rest.messages.requests;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
* Cancel an Order with Rest
* */
public class RestCancelOrderRequest {

/**
* milliseconds since UNIX epoch in UTC
*/
@JsonProperty("time")
private long time;

/**
* a 32-character unique client order Id
*/
@JsonProperty("coid")
private String coid;

/**
* a 32-character unique client cancel order Id
*/
@JsonProperty("origCoid")
private String origCoid;

/**
* symbol
*/
@JsonProperty("symbol")
private String symbol;

public long getTime() {
return time;
}

public void setTime(long time) {
this.time = time;
}

public String getCoid() {
return coid;
}

public void setCoid(String coid) {
this.coid = coid;
}

public String getSymbol() {
return symbol;
}

public void setSymbol(String symbol) {
this.symbol = symbol;
}

public String getOrigCoid() {
return origCoid;
}

public void setOrigCoid(String origCoid) {
this.origCoid = origCoid;
}

@Override
public String toString() {
return "RestCancelOrderRequest:\n\ttime: " + time +
"\n\tcoid: " + coid +
"\n\tsymbol: " + symbol +
"\n\torigCoid: " + origCoid;
}
}
Loading