Telling the Deserializing LimitOrderCreateOperation objects in the stream coming in the SubscriptionMessagesHub
This commit is contained in:
parent
37f52283a9
commit
457164b002
6 changed files with 162 additions and 13 deletions
|
@ -1,11 +1,16 @@
|
||||||
package de.bitsharesmunich.graphenej;
|
package de.bitsharesmunich.graphenej;
|
||||||
|
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
import com.google.gson.*;
|
import com.google.gson.GsonBuilder;
|
||||||
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
|
import com.google.gson.JsonArray;
|
||||||
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonDeserializer;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.JsonSerializationContext;
|
||||||
|
import com.google.gson.JsonSerializer;
|
||||||
|
|
||||||
import de.bitsharesmunich.graphenej.operations.TransferOperation;
|
|
||||||
import org.bitcoinj.core.DumpedPrivateKey;
|
import org.bitcoinj.core.DumpedPrivateKey;
|
||||||
import org.bitcoinj.core.ECKey;
|
import org.bitcoinj.core.ECKey;
|
||||||
import org.bitcoinj.core.Sha256Hash;
|
import org.bitcoinj.core.Sha256Hash;
|
||||||
|
@ -19,6 +24,11 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import de.bitsharesmunich.graphenej.interfaces.ByteSerializable;
|
||||||
|
import de.bitsharesmunich.graphenej.interfaces.JsonSerializable;
|
||||||
|
import de.bitsharesmunich.graphenej.operations.LimitOrderCreateOperation;
|
||||||
|
import de.bitsharesmunich.graphenej.operations.TransferOperation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to represent a generic Graphene transaction.
|
* Class used to represent a generic Graphene transaction.
|
||||||
*/
|
*/
|
||||||
|
@ -263,10 +273,9 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
for (JsonElement jsonOperation : jsonObject.get(KEY_OPERATIONS).getAsJsonArray()) {
|
for (JsonElement jsonOperation : jsonObject.get(KEY_OPERATIONS).getAsJsonArray()) {
|
||||||
int operationId = jsonOperation.getAsJsonArray().get(0).getAsInt();
|
int operationId = jsonOperation.getAsJsonArray().get(0).getAsInt();
|
||||||
if (operationId == OperationType.TRANSFER_OPERATION.ordinal()) {
|
if (operationId == OperationType.TRANSFER_OPERATION.ordinal()) {
|
||||||
System.out.println("Transfer operation detected!");
|
|
||||||
operation = context.deserialize(jsonOperation, TransferOperation.class);
|
operation = context.deserialize(jsonOperation, TransferOperation.class);
|
||||||
} else if (operationId == OperationType.LIMIT_ORDER_CREATE_OPERATION.ordinal()) {
|
} else if (operationId == OperationType.LIMIT_ORDER_CREATE_OPERATION.ordinal()) {
|
||||||
//TODO: Add operation deserialization support
|
operation = context.deserialize(jsonOperation, LimitOrderCreateOperation.class);
|
||||||
} else if (operationId == OperationType.LIMIT_ORDER_CANCEL_OPERATION.ordinal()) {
|
} else if (operationId == OperationType.LIMIT_ORDER_CANCEL_OPERATION.ordinal()) {
|
||||||
//TODO: Add operation deserialization support
|
//TODO: Add operation deserialization support
|
||||||
} else if (operationId == OperationType.CALL_ORDER_UPDATE_OPERATION.ordinal()) {
|
} else if (operationId == OperationType.CALL_ORDER_UPDATE_OPERATION.ordinal()) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import java.util.Map;
|
||||||
import de.bitsharesmunich.graphenej.AssetAmount;
|
import de.bitsharesmunich.graphenej.AssetAmount;
|
||||||
import de.bitsharesmunich.graphenej.RPC;
|
import de.bitsharesmunich.graphenej.RPC;
|
||||||
import de.bitsharesmunich.graphenej.Transaction;
|
import de.bitsharesmunich.graphenej.Transaction;
|
||||||
|
import de.bitsharesmunich.graphenej.UserAccount;
|
||||||
import de.bitsharesmunich.graphenej.interfaces.SubscriptionHub;
|
import de.bitsharesmunich.graphenej.interfaces.SubscriptionHub;
|
||||||
import de.bitsharesmunich.graphenej.interfaces.SubscriptionListener;
|
import de.bitsharesmunich.graphenej.interfaces.SubscriptionListener;
|
||||||
import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener;
|
import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener;
|
||||||
|
@ -22,6 +23,7 @@ import de.bitsharesmunich.graphenej.models.ApiCall;
|
||||||
import de.bitsharesmunich.graphenej.models.DynamicGlobalProperties;
|
import de.bitsharesmunich.graphenej.models.DynamicGlobalProperties;
|
||||||
import de.bitsharesmunich.graphenej.models.SubscriptionResponse;
|
import de.bitsharesmunich.graphenej.models.SubscriptionResponse;
|
||||||
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
||||||
|
import de.bitsharesmunich.graphenej.operations.LimitOrderCreateOperation;
|
||||||
import de.bitsharesmunich.graphenej.operations.TransferOperation;
|
import de.bitsharesmunich.graphenej.operations.TransferOperation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,7 +56,9 @@ public class SubscriptionMessagesHub extends BaseGrapheneHandler implements Subs
|
||||||
builder.registerTypeAdapter(SubscriptionResponse.class, mSubscriptionDeserializer);
|
builder.registerTypeAdapter(SubscriptionResponse.class, mSubscriptionDeserializer);
|
||||||
builder.registerTypeAdapter(Transaction.class, new Transaction.TransactionDeserializer());
|
builder.registerTypeAdapter(Transaction.class, new Transaction.TransactionDeserializer());
|
||||||
builder.registerTypeAdapter(TransferOperation.class, new TransferOperation.TransferDeserializer());
|
builder.registerTypeAdapter(TransferOperation.class, new TransferOperation.TransferDeserializer());
|
||||||
|
builder.registerTypeAdapter(LimitOrderCreateOperation.class, new LimitOrderCreateOperation.LimitOrderCreateDeserializer());
|
||||||
builder.registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer());
|
builder.registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer());
|
||||||
|
builder.registerTypeAdapter(UserAccount.class, new UserAccount.UserAccountSimpleDeserializer());
|
||||||
builder.registerTypeAdapter(DynamicGlobalProperties.class, new DynamicGlobalProperties.DynamicGlobalPropertiesDeserializer());
|
builder.registerTypeAdapter(DynamicGlobalProperties.class, new DynamicGlobalProperties.DynamicGlobalPropertiesDeserializer());
|
||||||
this.gson = builder.create();
|
this.gson = builder.create();
|
||||||
}
|
}
|
||||||
|
@ -104,7 +108,7 @@ public class SubscriptionMessagesHub extends BaseGrapheneHandler implements Subs
|
||||||
}else if(currentId == SUBCRIPTION_REQUEST){
|
}else if(currentId == SUBCRIPTION_REQUEST){
|
||||||
// There's nothing to handle here.
|
// There's nothing to handle here.
|
||||||
}else{
|
}else{
|
||||||
SubscriptionResponse subscriptionResponse = gson.fromJson(message, SubscriptionResponse.class);
|
gson.fromJson(message, SubscriptionResponse.class);
|
||||||
}
|
}
|
||||||
currentId++;
|
currentId++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,8 +120,8 @@ public class SubscriptionResponse {
|
||||||
JsonArray subArray = paramsArray.get(1).getAsJsonArray().get(0).getAsJsonArray();
|
JsonArray subArray = paramsArray.get(1).getAsJsonArray().get(0).getAsJsonArray();
|
||||||
for(JsonElement object : subArray){
|
for(JsonElement object : subArray){
|
||||||
if(object.isJsonObject()){
|
if(object.isJsonObject()){
|
||||||
|
|
||||||
GrapheneObject grapheneObject = new GrapheneObject(object.getAsJsonObject().get(KEY_ID).getAsString());
|
GrapheneObject grapheneObject = new GrapheneObject(object.getAsJsonObject().get(KEY_ID).getAsString());
|
||||||
|
|
||||||
int listenerTypeCount = 0;
|
int listenerTypeCount = 0;
|
||||||
if(this.listenerTypeCount.containsKey(grapheneObject.getObjectType())){
|
if(this.listenerTypeCount.containsKey(grapheneObject.getObjectType())){
|
||||||
listenerTypeCount = this.listenerTypeCount.get(grapheneObject.getObjectType());
|
listenerTypeCount = this.listenerTypeCount.get(grapheneObject.getObjectType());
|
||||||
|
|
|
@ -2,10 +2,15 @@ package de.bitsharesmunich.graphenej.operations;
|
||||||
|
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonDeserializer;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
@ -151,4 +156,78 @@ public class LimitOrderCreateOperation extends BaseOperation {
|
||||||
|
|
||||||
return Bytes.concat(feeBytes, sellerBytes, amountBytes, minAmountBytes, expirationBytes, fillOrKill, extensions);
|
return Bytes.concat(feeBytes, sellerBytes, amountBytes, minAmountBytes, expirationBytes, fillOrKill, extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializer used to convert the JSON-formatted representation of a limit_order_create_operation
|
||||||
|
* into its java object version.
|
||||||
|
*
|
||||||
|
* The following is an example of the serialized form of this operation:
|
||||||
|
*
|
||||||
|
* [
|
||||||
|
* 1,
|
||||||
|
* {
|
||||||
|
* "fee": {
|
||||||
|
* "amount": 14676,
|
||||||
|
* "asset_id": "1.3.0"
|
||||||
|
* },
|
||||||
|
* "seller": "1.2.36449",
|
||||||
|
* "amount_to_sell": {
|
||||||
|
* "amount": 945472,
|
||||||
|
* "asset_id": "1.3.850"
|
||||||
|
* },
|
||||||
|
* "min_to_receive": {
|
||||||
|
* "amount": 4354658,
|
||||||
|
* "asset_id": "1.3.861"
|
||||||
|
* },
|
||||||
|
* "expiration": "1963-11-25T06:31:44",
|
||||||
|
* "fill_or_kill": false,
|
||||||
|
* "extensions": []
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static class LimitOrderCreateDeserializer implements JsonDeserializer<LimitOrderCreateOperation> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LimitOrderCreateOperation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
if(json.isJsonArray()){
|
||||||
|
// This block is used just to check if we are in the first step of the deserialization
|
||||||
|
// when we are dealing with an array.
|
||||||
|
JsonArray serializedTransfer = json.getAsJsonArray();
|
||||||
|
if(serializedTransfer.get(0).getAsInt() != OperationType.LIMIT_ORDER_CREATE_OPERATION.ordinal()){
|
||||||
|
// If the operation type does not correspond to a transfer operation, we return null
|
||||||
|
return null;
|
||||||
|
}else{
|
||||||
|
// Calling itself recursively, this is only done once, so there will be no problems.
|
||||||
|
return context.deserialize(serializedTransfer.get(1), LimitOrderCreateOperation.class);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
// This block is called in the second recursion and takes care of deserializing the
|
||||||
|
// limit order data itself.
|
||||||
|
JsonObject jsonObject = json.getAsJsonObject();
|
||||||
|
|
||||||
|
AssetAmount fee = context.deserialize(jsonObject.get(KEY_FEE), AssetAmount.class);
|
||||||
|
UserAccount seller = context.deserialize(jsonObject.get(KEY_SELLER), UserAccount.class);
|
||||||
|
AssetAmount amountToSell = context.deserialize(jsonObject.get(KEY_AMOUNT_TO_SELL), AssetAmount.class);
|
||||||
|
AssetAmount minToReceive = context.deserialize(jsonObject.get(KEY_MIN_TO_RECEIVE), AssetAmount.class);
|
||||||
|
String expiration = jsonObject.get(KEY_EXPIRATION).getAsString();
|
||||||
|
boolean fillOrKill = jsonObject.get(KEY_FILL_OR_KILL).getAsBoolean();
|
||||||
|
|
||||||
|
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(Util.TIME_DATE_FORMAT);
|
||||||
|
int expirationPosix = 0;
|
||||||
|
try {
|
||||||
|
Date expirationDate = simpleDateFormat.parse(expiration);
|
||||||
|
expirationPosix = (int) (expirationDate.getTime() / 1000);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating an instance of the LimitOrderCreateOperation and setting the fee
|
||||||
|
LimitOrderCreateOperation operation = new LimitOrderCreateOperation(seller, amountToSell, minToReceive, expirationPosix, fillOrKill);
|
||||||
|
operation.setFee(fee);
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package de.bitsharesmunich.graphenej;
|
package de.bitsharesmunich.graphenej;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import junit.framework.Assert;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -8,7 +9,6 @@ import org.junit.Test;
|
||||||
* Created by nelson on 4/18/17.
|
* Created by nelson on 4/18/17.
|
||||||
*/
|
*/
|
||||||
public class BrainKeyTest {
|
public class BrainKeyTest {
|
||||||
// public final String TEST_BRAINKEY = "SOAPILY GASSING FIFIE OZONATE WHYO TOPLINE PRISMY ZEUGMA GLOTTIC DAVEN CORODY PFUI";
|
|
||||||
public final String TEST_BRAINKEY = "BARIC BICKERN LITZ TIPFUL JINGLED POOL TUMBAK PURIST APOPYLE DURAIN SATLIJK FAUCAL";
|
public final String TEST_BRAINKEY = "BARIC BICKERN LITZ TIPFUL JINGLED POOL TUMBAK PURIST APOPYLE DURAIN SATLIJK FAUCAL";
|
||||||
private BrainKey mBrainKey;
|
private BrainKey mBrainKey;
|
||||||
|
|
||||||
|
@ -20,9 +20,6 @@ public class BrainKeyTest {
|
||||||
@Test
|
@Test
|
||||||
public void testAddress(){
|
public void testAddress(){
|
||||||
Address address = mBrainKey.getPublicAddress(Address.BITSHARES_PREFIX);
|
Address address = mBrainKey.getPublicAddress(Address.BITSHARES_PREFIX);
|
||||||
// Assert.assertEquals("Assert that the address created is the expected one",
|
|
||||||
// "BTS7yT2vnjGAxPocqsnDfoJv3DHUtCNGWwqvc7mWRikkqwuhKtT5s",
|
|
||||||
// address.toString());
|
|
||||||
Assert.assertEquals("Assert that the address created is the expected one",
|
Assert.assertEquals("Assert that the address created is the expected one",
|
||||||
"BTS61UqqgE3ARuTGcckzARsdQm4EMFdBEwYyi1pbwyHrZZWrCDhT2",
|
"BTS61UqqgE3ARuTGcckzARsdQm4EMFdBEwYyi1pbwyHrZZWrCDhT2",
|
||||||
address.toString());
|
address.toString());
|
||||||
|
|
|
@ -3,11 +3,16 @@ package de.bitsharesmunich.graphenej.api;
|
||||||
import com.neovisionaries.ws.client.WebSocketException;
|
import com.neovisionaries.ws.client.WebSocketException;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.bitsharesmunich.graphenej.ObjectType;
|
import de.bitsharesmunich.graphenej.ObjectType;
|
||||||
|
import de.bitsharesmunich.graphenej.Transaction;
|
||||||
import de.bitsharesmunich.graphenej.interfaces.SubscriptionListener;
|
import de.bitsharesmunich.graphenej.interfaces.SubscriptionListener;
|
||||||
import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener;
|
import de.bitsharesmunich.graphenej.interfaces.WitnessResponseListener;
|
||||||
import de.bitsharesmunich.graphenej.models.BaseResponse;
|
import de.bitsharesmunich.graphenej.models.BaseResponse;
|
||||||
|
import de.bitsharesmunich.graphenej.models.BroadcastedTransaction;
|
||||||
import de.bitsharesmunich.graphenej.models.DynamicGlobalProperties;
|
import de.bitsharesmunich.graphenej.models.DynamicGlobalProperties;
|
||||||
import de.bitsharesmunich.graphenej.models.SubscriptionResponse;
|
import de.bitsharesmunich.graphenej.models.SubscriptionResponse;
|
||||||
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
import de.bitsharesmunich.graphenej.models.WitnessResponse;
|
||||||
|
@ -82,4 +87,59 @@ public class SubscriptionMessagesHubTest extends BaseApiTest {
|
||||||
System.out.println("InterruptedException. Msg: "+e.getMessage());
|
System.out.println("InterruptedException. Msg: "+e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a basic test that will only display a count of operations per received broadcasted transactions.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testBroadcastedTransactionDeserializer(){
|
||||||
|
try{
|
||||||
|
mMessagesHub = new SubscriptionMessagesHub("", "", mErrorListener);
|
||||||
|
mMessagesHub.addSubscriptionListener(new SubscriptionListener() {
|
||||||
|
private int MAX_MESSAGES = 15;
|
||||||
|
private int messageCounter = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ObjectType getInterestObjectType() {
|
||||||
|
return ObjectType.TRANSACTION_OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSubscriptionUpdate(SubscriptionResponse response) {
|
||||||
|
if(response.params.size() == 2){
|
||||||
|
List<Serializable> payload = (List) response.params.get(1);
|
||||||
|
if(payload.size() > 0){
|
||||||
|
for(Serializable item : payload){
|
||||||
|
if(item instanceof BroadcastedTransaction){
|
||||||
|
BroadcastedTransaction broadcastedTransaction = (BroadcastedTransaction) item;
|
||||||
|
Transaction tx = broadcastedTransaction.getTransaction();
|
||||||
|
System.out.println(String.format("Got %d operations", tx.getOperations().size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Waiting for MAX_MESSAGES messages before releasing the wait lock
|
||||||
|
messageCounter++;
|
||||||
|
if(messageCounter > MAX_MESSAGES){
|
||||||
|
synchronized (SubscriptionMessagesHubTest.this){
|
||||||
|
SubscriptionMessagesHubTest.this.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mWebSocket.addListener(mMessagesHub);
|
||||||
|
mWebSocket.connect();
|
||||||
|
|
||||||
|
// Holding this thread while we get update notifications
|
||||||
|
synchronized (this){
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
} catch (WebSocketException e) {
|
||||||
|
System.out.println("WebSocketException. Msg: " + e.getMessage());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
System.out.println("InterruptedException. Msg: "+e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue