From 6410c85fd81b2a1de6f71192d97c1502f5600fa3 Mon Sep 17 00:00:00 2001 From: "Nelson R. Perez" Date: Fri, 27 Apr 2018 00:09:37 -0500 Subject: [PATCH] Detecting and deserializing operation history objects --- .../api/SubscriptionMessagesHub.java | 2 + .../graphenej/models/OperationHistory.java | 84 +++++++++++++++++-- .../models/SubscriptionResponse.java | 9 +- .../api/SubscriptionMessagesHubTest.java | 27 +++++- 4 files changed, 112 insertions(+), 10 deletions(-) diff --git a/graphenej/src/main/java/cy/agorise/graphenej/api/SubscriptionMessagesHub.java b/graphenej/src/main/java/cy/agorise/graphenej/api/SubscriptionMessagesHub.java index 5364314..a0c533e 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/api/SubscriptionMessagesHub.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/api/SubscriptionMessagesHub.java @@ -23,6 +23,7 @@ import cy.agorise.graphenej.interfaces.SubscriptionHub; import cy.agorise.graphenej.interfaces.SubscriptionListener; import cy.agorise.graphenej.models.ApiCall; import cy.agorise.graphenej.models.DynamicGlobalProperties; +import cy.agorise.graphenej.models.OperationHistory; import cy.agorise.graphenej.models.SubscriptionResponse; import cy.agorise.graphenej.models.WitnessResponse; import cy.agorise.graphenej.objects.Memo; @@ -96,6 +97,7 @@ public class SubscriptionMessagesHub extends BaseGrapheneHandler implements Subs builder.registerTypeAdapter(UserAccount.class, new UserAccount.UserAccountSimpleDeserializer()); builder.registerTypeAdapter(DynamicGlobalProperties.class, new DynamicGlobalProperties.DynamicGlobalPropertiesDeserializer()); builder.registerTypeAdapter(Memo.class, new Memo.MemoDeserializer()); + builder.registerTypeAdapter(OperationHistory.class, new OperationHistory.OperationHistoryDeserializer()); this.gson = builder.create(); } diff --git a/graphenej/src/main/java/cy/agorise/graphenej/models/OperationHistory.java b/graphenej/src/main/java/cy/agorise/graphenej/models/OperationHistory.java index 8780a89..059caf2 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/models/OperationHistory.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/models/OperationHistory.java @@ -1,5 +1,15 @@ package cy.agorise.graphenej.models; +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 java.io.Serializable; +import java.lang.reflect.Type; + +import cy.agorise.graphenej.GrapheneObject; import cy.agorise.graphenej.operations.TransferOperation; @@ -10,8 +20,13 @@ import cy.agorise.graphenej.operations.TransferOperation; * More operations types might be listed in the response of that method, but by using this class * those will be filtered out of the parsed result. */ -public class OperationHistory { - private String id; +public class OperationHistory extends GrapheneObject implements Serializable { + public static final String KEY_OP = "op"; + public static final String KEY_BLOCK_NUM = "block_num"; + public static final String KEY_TRX_IN_BLOCK = "trx_in_block"; + public static final String KEY_OP_IN_TRX = "op_in_trx"; + public static final String KEY_VIRTUAL_OP = "virtual_op"; + private TransferOperation op; public Object[] result; private long block_num; @@ -19,12 +34,8 @@ public class OperationHistory { private long op_in_trx; private long virtual_op; - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; + public OperationHistory(String id) { + super(id); } public TransferOperation getOperation() { @@ -66,4 +77,61 @@ public class OperationHistory { public void setVirtualOp(long virtual_op) { this.virtual_op = virtual_op; } + + /** + * Deserializer used to transform a an operation history object from its serialized form to an + * OperationHistory instance. + * + * The serialized form of this object is the following: + * + * { + "id": "1.11.178205535", + "op": [ + 14, + { + "fee": { + "amount": 10425, + "asset_id": "1.3.0" + }, + "issuer": "1.2.374566", + "asset_to_issue": { + "amount": 8387660, + "asset_id": "1.3.3271" + }, + "issue_to_account": "1.2.797835", + "extensions": [] + } + ], + "result": [ + 0, + {} + ], + "block_num": 26473240, + "trx_in_block": 11, + "op_in_trx": 0, + "virtual_op": 660 + } + * //TODO: Expand this deserializer for operation history objects that have an operation other than the transfer operation + */ + public static class OperationHistoryDeserializer implements JsonDeserializer { + + @Override + public OperationHistory deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + String id = jsonObject.get(KEY_ID).getAsString(); + long blockNum = jsonObject.get(KEY_BLOCK_NUM).getAsLong(); + long trxInBlock = jsonObject.get(KEY_TRX_IN_BLOCK).getAsLong(); + long opInTrx = jsonObject.get(KEY_OP_IN_TRX).getAsLong(); + TransferOperation transferOperation = context.deserialize(jsonObject.get(KEY_OP), TransferOperation.class); + long virtualOp = jsonObject.get(KEY_VIRTUAL_OP).getAsLong(); + + OperationHistory operationHistory = new OperationHistory(id); + operationHistory.setBlockNum(blockNum); + operationHistory.setTransactionsInBlock(trxInBlock); + operationHistory.setOperationsInTrx(opInTrx); + operationHistory.setOperation(transferOperation); + operationHistory.setVirtualOp(virtualOp); + return operationHistory; + } + } } \ No newline at end of file diff --git a/graphenej/src/main/java/cy/agorise/graphenej/models/SubscriptionResponse.java b/graphenej/src/main/java/cy/agorise/graphenej/models/SubscriptionResponse.java index 2468a15..cf048b0 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/models/SubscriptionResponse.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/models/SubscriptionResponse.java @@ -16,6 +16,7 @@ import java.util.List; import cy.agorise.graphenej.GrapheneObject; import cy.agorise.graphenej.ObjectType; +import cy.agorise.graphenej.OperationType; import cy.agorise.graphenej.Transaction; import cy.agorise.graphenej.interfaces.SubscriptionListener; @@ -183,7 +184,13 @@ public class SubscriptionResponse { objectMap.put(ObjectType.TRANSACTION_OBJECT, true); secondArgument.add(broadcastedTransaction); }else if(grapheneObject.getObjectType() == ObjectType.OPERATION_HISTORY_OBJECT){ - //TODO: Add support for other types of objects + if(jsonObject.get(OperationHistory.KEY_OP).getAsJsonArray().get(0).getAsLong() == OperationType.TRANSFER_OPERATION.ordinal()){ + OperationHistory operationHistory = context.deserialize(jsonObject, OperationHistory.class); + objectMap.put(ObjectType.OPERATION_HISTORY_OBJECT, true); + secondArgument.add(operationHistory); + }else{ + //TODO: Add support for other operations + } }else{ //TODO: Add support for other types of objects } diff --git a/graphenej/src/test/java/cy/agorise/graphenej/api/SubscriptionMessagesHubTest.java b/graphenej/src/test/java/cy/agorise/graphenej/api/SubscriptionMessagesHubTest.java index 3e1cbe1..be510be 100644 --- a/graphenej/src/test/java/cy/agorise/graphenej/api/SubscriptionMessagesHubTest.java +++ b/graphenej/src/test/java/cy/agorise/graphenej/api/SubscriptionMessagesHubTest.java @@ -15,6 +15,7 @@ import cy.agorise.graphenej.interfaces.SubscriptionListener; import cy.agorise.graphenej.models.BaseResponse; import cy.agorise.graphenej.models.BroadcastedTransaction; import cy.agorise.graphenej.models.DynamicGlobalProperties; +import cy.agorise.graphenej.models.OperationHistory; import cy.agorise.graphenej.models.SubscriptionResponse; import cy.agorise.graphenej.Transaction; @@ -197,7 +198,7 @@ public class SubscriptionMessagesHubTest extends BaseApiTest { if(item instanceof BroadcastedTransaction){ BroadcastedTransaction broadcastedTransaction = (BroadcastedTransaction) item; Transaction tx = broadcastedTransaction.getTransaction(); - System.out.println(String.format("Got %d operations", tx.getOperations().size())); +// System.out.println(String.format("Got %d operations", tx.getOperations().size())); } } } @@ -213,6 +214,30 @@ public class SubscriptionMessagesHubTest extends BaseApiTest { } }); + mMessagesHub.addSubscriptionListener(new SubscriptionListener() { + + @Override + public ObjectType getInterestObjectType() { + return ObjectType.OPERATION_HISTORY_OBJECT; + } + + @Override + public void onSubscriptionUpdate(SubscriptionResponse response) { + System.out.println("onSubscriptionUpdate. response.params.size: "+response.params.size()); + if(response.params.size() == 2){ + List payload = (List) response.params.get(1); + if(payload.size() > 0){ + for(Serializable item : payload){ + if(item instanceof OperationHistory){ + OperationHistory operationHistory = (OperationHistory) item; + System.out.println("Operation history: "); + } + } + } + } + } + }); + mWebSocket.addListener(mMessagesHub); mWebSocket.connect();