From 0908438888870bfae7cc0e6db0c289079b72d865 Mon Sep 17 00:00:00 2001 From: "Nelson R. Perez" Date: Fri, 23 Dec 2016 00:16:20 -0500 Subject: [PATCH] Added support for 'get_market_history' API call --- .../de/bitsharesmunich/graphenej/Main.java | 3 +- .../de/bitsharesmunich/graphenej/RPC.java | 3 +- .../de/bitsharesmunich/graphenej/Test.java | 58 +++++++- .../graphenej/api/GetMarketHistory.java | 125 ++++++++++++++++++ .../api/GetRelativeAccountHistory.java | 1 - .../graphenej/api/GetTradeHistory.java | 4 +- .../graphenej/models/BucketObject.java | 84 ++++++++++++ 7 files changed, 269 insertions(+), 9 deletions(-) create mode 100644 src/main/java/de/bitsharesmunich/graphenej/api/GetMarketHistory.java create mode 100644 src/main/java/de/bitsharesmunich/graphenej/models/BucketObject.java diff --git a/src/main/java/de/bitsharesmunich/graphenej/Main.java b/src/main/java/de/bitsharesmunich/graphenej/Main.java index c8f65d7..b86b5c1 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/Main.java +++ b/src/main/java/de/bitsharesmunich/graphenej/Main.java @@ -42,7 +42,7 @@ public class Main { // test.testGetDynamicParams(); // test.testGetRequiredFeesSerialization(); // test.testRequiredFeesResponse(); - test.testTransactionBroadcastSequence(); +// test.testTransactionBroadcastSequence(); // test.testAccountLookupDeserialization(); // test.testPrivateKeyManipulations(); // test.testPublicKeyManipulations(); @@ -69,5 +69,6 @@ public class Main { //test.testGetLimitOrders(); // test.testGetTradeHistory(); // test.testAssetSerialization(); + test.testGetMarketHistory(); } } diff --git a/src/main/java/de/bitsharesmunich/graphenej/RPC.java b/src/main/java/de/bitsharesmunich/graphenej/RPC.java index 489fabb..e58a2a8 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/RPC.java +++ b/src/main/java/de/bitsharesmunich/graphenej/RPC.java @@ -20,5 +20,6 @@ public class RPC { public static final String CALL_LOOKUP_ASSET_SYMBOLS = "lookup_asset_symbols"; public static final String CALL_GET_BLOCK_HEADER = "get_block_header"; public static final String CALL_GET_LIMIT_ORDERS = "get_limit_orders"; - public static final String GET_TRADE_HISTORY = "get_trade_history"; + public static final String CALL_GET_TRADE_HISTORY = "get_trade_history"; + public static final String CALL_GET_MARKET_HISTORY = "get_market_history"; } diff --git a/src/main/java/de/bitsharesmunich/graphenej/Test.java b/src/main/java/de/bitsharesmunich/graphenej/Test.java index 5053a5e..c0d0308 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/Test.java +++ b/src/main/java/de/bitsharesmunich/graphenej/Test.java @@ -761,9 +761,9 @@ public class Test { ECKey from = new BrainKey(Main.BILTHON_83_BRAIN_KEY, 0).getPrivateKey(); PublicKey to = new PublicKey(ECKey.fromPublicOnly(new BrainKey(Main.BILTHON_5_BRAIN_KEY, 0).getPublicKey())); - + // Memo sendMemo = new MemoBuilder().setFromKey(from).setToKey(to).setMessage("test message").build(); - + // JsonElement memoJson = sendMemo.toJsonObject(); // System.out.println("generated Json : " + memoJson.toString()); // System.out.println("Decode Memo : " + Memo.decryptMessage(from, to, memoJson.getAsJsonObject().get("message").getAsString(), memoJson.getAsJsonObject().get("nonce").getAsString())); @@ -944,14 +944,14 @@ public class Test { // Set the custom SSL context. factory.setSSLContext(context); - WebSocket mWebSocket = factory.createSocket(BLOCK_PAY_DE); + WebSocket mWebSocket = factory.createSocket(BLOCK_PAY_FR); Calendar from = Calendar.getInstance(); from.roll(Calendar.DAY_OF_MONTH, false); from.roll(Calendar.DAY_OF_MONTH, false); Calendar to = Calendar.getInstance(); to.roll(Calendar.DAY_OF_MONTH, false); - + mWebSocket.addListener(new GetTradeHistory("BTS", "EUR", "20161215T0130000", "20161212T233000",100, new WitnessResponseListener() { @Override public void onSuccess(WitnessResponse response) { @@ -976,6 +976,56 @@ public class Test { } } + public void testGetMarketHistory(){ + SSLContext context = null; + + WitnessResponseListener listener = new WitnessResponseListener() { + @Override + public void onSuccess(WitnessResponse response) { + System.out.println("onSuccess"); + List bucketList = (List) response.result; + if(bucketList.size() > 0){ + BucketObject bucket = bucketList.get(0); + System.out.println(String.format("bucket. high_base: %d, high_quote: %d", bucket.high_base, bucket.high_quote)); + } + } + + @Override + public void onError(BaseResponse.Error error) { + System.out.println("onError"); + } + }; + + try { + context = NaiveSSLContext.getInstance("TLS"); + WebSocketFactory factory = new WebSocketFactory(); + + // Set the custom SSL context. + factory.setSSLContext(context); + + WebSocket mWebSocket = factory.createSocket(BLOCK_PAY_FR); + + long posixInstant = 1482436057000l; + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(posixInstant); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MINUTE, 0); + + Asset BTS = new Asset("1.3.0"); + Asset USD = new Asset("1.3.121"); + long bucket = 3600; + + mWebSocket.addListener(new GetMarketHistory(USD, BTS, bucket, cal.getTime(), cal.getTime(), listener)); + mWebSocket.connect(); + } catch (NoSuchAlgorithmException e) { + System.out.println("NoSuchAlgorithmException. Msg: " + e.getMessage()); + } catch (WebSocketException e) { + System.out.println("WebSocketException. Msg: " + e.getMessage()); + } catch (IOException e) { + System.out.println("IOException. Msg: " + e.getMessage()); + } + } + public void testAssetSerialization(){ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); DataOutput out = new DataOutputStream(byteArrayOutputStream); diff --git a/src/main/java/de/bitsharesmunich/graphenej/api/GetMarketHistory.java b/src/main/java/de/bitsharesmunich/graphenej/api/GetMarketHistory.java new file mode 100644 index 0000000..06a6a81 --- /dev/null +++ b/src/main/java/de/bitsharesmunich/graphenej/api/GetMarketHistory.java @@ -0,0 +1,125 @@ +package de.bitsharesmunich.graphenej.api; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import com.neovisionaries.ws.client.WebSocket; +import com.neovisionaries.ws.client.WebSocketAdapter; +import com.neovisionaries.ws.client.WebSocketException; +import com.neovisionaries.ws.client.WebSocketFrame; +import de.bitsharesmunich.graphenej.Asset; +import de.bitsharesmunich.graphenej.RPC; +import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener; +import de.bitsharesmunich.graphenej.models.*; + +import java.io.Serializable; +import java.lang.reflect.Type; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * Created by nelson on 12/22/16. + */ +public class GetMarketHistory extends WebSocketAdapter { + // Sequence of message ids + private final static int LOGIN_ID = 1; + private final static int GET_HISTORY_ID = 2; + private final static int GET_HISTORY_DATA = 3; + + // API call parameters + private Asset base; + private Asset quote; + private long bucket; + private Date start; + private Date end; + private WitnessResponseListener mListener; + + private int currentId = 1; + private int apiId = -1; + + public GetMarketHistory(Asset base, Asset quote, long bucket, Date start, Date end, WitnessResponseListener listener){ + this.base = base; + this.quote = quote; + this.bucket = bucket; + this.start = start; + this.end = end; + this.mListener = listener; + } + + @Override + public void onConnected(WebSocket websocket, Map> headers) throws Exception { + ArrayList loginParams = new ArrayList<>(); + loginParams.add(null); + loginParams.add(null); + ApiCall loginCall = new ApiCall(1, RPC.CALL_LOGIN, loginParams, RPC.VERSION, currentId); + websocket.sendText(loginCall.toJsonString()); + } + + @Override + public void onTextFrame(WebSocket websocket, WebSocketFrame frame) throws Exception { + String response = frame.getPayloadText(); + System.out.println("<<< "+response); + Gson gson = new Gson(); + BaseResponse baseResponse = gson.fromJson(response, BaseResponse.class); + if(baseResponse.error != null){ + mListener.onError(baseResponse.error); + websocket.disconnect(); + }else{ + currentId++; + ArrayList emptyParams = new ArrayList<>(); + if(baseResponse.id == LOGIN_ID){ + ApiCall getRelativeAccountHistoryId = new ApiCall(1, RPC.CALL_HISTORY, emptyParams, RPC.VERSION, currentId); + websocket.sendText(getRelativeAccountHistoryId.toJsonString()); + } else if(baseResponse.id == GET_HISTORY_ID){ + Type ApiIdResponse = new TypeToken>() {}.getType(); + WitnessResponse witnessResponse = gson.fromJson(response, ApiIdResponse); + apiId = witnessResponse.result.intValue(); + + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + + ArrayList params = new ArrayList<>(); + params.add(this.base.getObjectId()); + params.add(this.quote.getObjectId()); + params.add(this.bucket); + params.add(dateFormat.format(this.start)); + params.add(dateFormat.format(this.end)); + + ApiCall getRelativeAccountHistoryCall = new ApiCall(apiId, RPC.CALL_GET_MARKET_HISTORY, params, RPC.VERSION, currentId); + websocket.sendText(getRelativeAccountHistoryCall.toJsonString()); + }else if(baseResponse.id == GET_HISTORY_DATA){ + GsonBuilder builder = new GsonBuilder(); + Type MarketHistoryResponse = new TypeToken>>(){}.getType(); + builder.registerTypeAdapter(BucketObject.class, new BucketObject.BucketDeserializer()); + WitnessResponse> marketHistoryResponse = builder.create().fromJson(response, MarketHistoryResponse); + mListener.onSuccess(marketHistoryResponse); + websocket.disconnect(); + } + } + } + + @Override + public void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception { + if(frame.isTextFrame()) + System.out.println(">>> "+frame.getPayloadText()); + } + + @Override + public void onError(WebSocket websocket, WebSocketException cause) throws Exception { + System.out.println("onError. Msg: "+cause.getMessage()); + mListener.onError(new BaseResponse.Error(cause.getMessage())); + websocket.disconnect(); + } + + @Override + public void handleCallbackError(WebSocket websocket, Throwable cause) throws Exception { + System.out.println("handleCallbackError. cause: "+cause.getMessage()+", error: "+cause.getClass()); + for (StackTraceElement element : cause.getStackTrace()){ + System.out.println(element.getFileName()+"#"+element.getClassName()+":"+element.getLineNumber()); + } + mListener.onError(new BaseResponse.Error(cause.getMessage())); + websocket.disconnect(); + } +} diff --git a/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java b/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java index 4082993..548b133 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java +++ b/src/main/java/de/bitsharesmunich/graphenej/api/GetRelativeAccountHistory.java @@ -116,7 +116,6 @@ public class GetRelativeAccountHistory extends WebSocketAdapter { ApiCall getRelativeAccountHistoryCall = new ApiCall(apiId, RPC.CALL_GET_RELATIVE_ACCOUNT_HISTORY, params, RPC.VERSION, currentId); websocket.sendText(getRelativeAccountHistoryCall.toJsonString()); }else if(baseResponse.id == GET_HISTORY_DATA){ - System.out.println(frame.getPayloadText()); Type RelativeAccountHistoryResponse = new TypeToken>>(){}.getType(); GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(TransferOperation.class, new TransferOperation.TransferDeserializer()); diff --git a/src/main/java/de/bitsharesmunich/graphenej/api/GetTradeHistory.java b/src/main/java/de/bitsharesmunich/graphenej/api/GetTradeHistory.java index 04d807f..073ea25 100644 --- a/src/main/java/de/bitsharesmunich/graphenej/api/GetTradeHistory.java +++ b/src/main/java/de/bitsharesmunich/graphenej/api/GetTradeHistory.java @@ -20,7 +20,7 @@ import java.util.List; import java.util.Map; /** - * Created by nelson on 11/15/16. + * @author henry */ public class GetTradeHistory extends WebSocketAdapter { @@ -49,7 +49,7 @@ public class GetTradeHistory extends WebSocketAdapter { accountParams.add(this.fromTime); accountParams.add(this.limit); - ApiCall getAccountByName = new ApiCall(0, RPC.GET_TRADE_HISTORY, accountParams, RPC.VERSION, 1); + ApiCall getAccountByName = new ApiCall(0, RPC.CALL_GET_TRADE_HISTORY, accountParams, RPC.VERSION, 1); websocket.sendText(getAccountByName.toJsonString()); } diff --git a/src/main/java/de/bitsharesmunich/graphenej/models/BucketObject.java b/src/main/java/de/bitsharesmunich/graphenej/models/BucketObject.java new file mode 100644 index 0000000..56514b2 --- /dev/null +++ b/src/main/java/de/bitsharesmunich/graphenej/models/BucketObject.java @@ -0,0 +1,84 @@ +package de.bitsharesmunich.graphenej.models; + +import com.google.gson.*; +import de.bitsharesmunich.graphenej.Asset; + +import java.lang.reflect.Type; +import java.math.BigInteger; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Created by nelson on 12/22/16. + */ +public class BucketObject { + public static final String KEY_HIGH_BASE = "high_base"; + public static final String KEY_HIGH_QUOTE = "high_quote"; + public static final String KEY_LOW_BASE = "low_base"; + public static final String KEY_LOW_QUOTE = "low_quote"; + public static final String KEY_OPEN_BASE = "open_base"; + public static final String KEY_OPEN_QUOTE = "open_quote"; + public static final String KEY_CLOSE_BASE = "close_base"; + public static final String KEY_CLOSE_QUOTE = "close_quote"; + public static final String KEY_BASE_VOLUME = "base_volume"; + public static final String KEY_QUOTE_VOLUME = "quote_volume"; + public static final String KEY_BASE = "base"; + public static final String KEY_QUOTE = "quote"; + public static final String KEY_SECONDS = "seconds"; + public static final String KEY_OPEN = "open"; + public static final String KEY_KEY = "key"; + + public String id; + public Key key; + public BigInteger high_base; + public BigInteger high_quote; + public BigInteger low_base; + public BigInteger low_quote; + public BigInteger open_base; + public BigInteger open_quote; + public BigInteger close_base; + public BigInteger close_quote; + public BigInteger base_volume; + public BigInteger quote_volume; + + public static class Key { + public Asset base; + public Asset quote; + public long seconds; + public Date open; + } + + public static class BucketDeserializer implements JsonDeserializer { + + @Override + public BucketObject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + JsonObject jsonBucket = json.getAsJsonObject(); + BucketObject bucket = new BucketObject(); + bucket.high_base = jsonBucket.get(KEY_HIGH_BASE).getAsBigInteger(); + bucket.high_quote = jsonBucket.get(KEY_HIGH_QUOTE).getAsBigInteger(); + bucket.low_base = jsonBucket.get(KEY_LOW_BASE).getAsBigInteger(); + bucket.low_quote = jsonBucket.get(KEY_LOW_QUOTE).getAsBigInteger(); + bucket.open_base = jsonBucket.get(KEY_OPEN_BASE).getAsBigInteger(); + bucket.open_quote = jsonBucket.get(KEY_OPEN_QUOTE).getAsBigInteger(); + bucket.close_base = jsonBucket.get(KEY_CLOSE_BASE).getAsBigInteger(); + bucket.close_quote = jsonBucket.get(KEY_CLOSE_QUOTE).getAsBigInteger(); + bucket.base_volume = jsonBucket.get(KEY_BASE_VOLUME).getAsBigInteger(); + bucket.quote_volume = jsonBucket.get(KEY_QUOTE_VOLUME).getAsBigInteger(); + bucket.key = new Key(); + String baseId = jsonBucket.get(KEY_KEY).getAsJsonObject().get(KEY_BASE).getAsString(); + String quoteId = jsonBucket.get(KEY_KEY).getAsJsonObject().get(KEY_QUOTE).getAsString(); + bucket.key.base = new Asset(baseId); + bucket.key.quote = new Asset(quoteId); + bucket.key.seconds = jsonBucket.get(KEY_KEY).getAsJsonObject().get(KEY_SECONDS).getAsLong(); + + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + try { + bucket.key.open = dateFormat.parse(jsonBucket.get(KEY_KEY).getAsJsonObject().get(KEY_OPEN).getAsString()); + } catch (ParseException e) { + System.out.println("ParseException while deserializing BucketObject. Msg: "+e.getMessage()); + } + return bucket; + } + } +}