Implemented deserialization of custom operation
This commit is contained in:
parent
be9a16a48b
commit
d0629eab85
4 changed files with 74 additions and 6 deletions
|
@ -11,6 +11,7 @@ import com.google.gson.JsonParseException;
|
||||||
import com.google.gson.JsonSerializationContext;
|
import com.google.gson.JsonSerializationContext;
|
||||||
import com.google.gson.JsonSerializer;
|
import com.google.gson.JsonSerializer;
|
||||||
|
|
||||||
|
import cy.agorise.graphenej.operations.CustomOperation;
|
||||||
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;
|
||||||
|
@ -343,7 +344,7 @@ public class Transaction implements ByteSerializable, JsonSerializable {
|
||||||
} else if (operationId == OperationType.WORKER_CREATE_OPERATION.ordinal()) {
|
} else if (operationId == OperationType.WORKER_CREATE_OPERATION.ordinal()) {
|
||||||
//TODO: Add operation deserialization support
|
//TODO: Add operation deserialization support
|
||||||
} else if (operationId == OperationType.CUSTOM_OPERATION.ordinal()) {
|
} else if (operationId == OperationType.CUSTOM_OPERATION.ordinal()) {
|
||||||
//TODO: Add operation deserialization support
|
operation = context.deserialize(jsonOperation, CustomOperation.class);
|
||||||
} else if (operationId == OperationType.ASSERT_OPERATION.ordinal()) {
|
} else if (operationId == OperationType.ASSERT_OPERATION.ordinal()) {
|
||||||
//TODO: Add operation deserialization support
|
//TODO: Add operation deserialization support
|
||||||
} else if (operationId == OperationType.BALANCE_CLAIM_OPERATION.ordinal()) {
|
} else if (operationId == OperationType.BALANCE_CLAIM_OPERATION.ordinal()) {
|
||||||
|
|
|
@ -13,6 +13,8 @@ import cy.agorise.graphenej.models.ApiCall;
|
||||||
import cy.agorise.graphenej.models.BaseResponse;
|
import cy.agorise.graphenej.models.BaseResponse;
|
||||||
import cy.agorise.graphenej.models.Block;
|
import cy.agorise.graphenej.models.Block;
|
||||||
import cy.agorise.graphenej.models.WitnessResponse;
|
import cy.agorise.graphenej.models.WitnessResponse;
|
||||||
|
import cy.agorise.graphenej.operations.CustomOperation;
|
||||||
|
import cy.agorise.graphenej.operations.LimitOrderCreateOperation;
|
||||||
import cy.agorise.graphenej.operations.TransferOperation;
|
import cy.agorise.graphenej.operations.TransferOperation;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -88,6 +90,8 @@ public class GetBlock extends BaseGrapheneHandler {
|
||||||
gson = new GsonBuilder()
|
gson = new GsonBuilder()
|
||||||
.registerTypeAdapter(Transaction.class, new Transaction.TransactionDeserializer())
|
.registerTypeAdapter(Transaction.class, new Transaction.TransactionDeserializer())
|
||||||
.registerTypeAdapter(TransferOperation.class, new TransferOperation.TransferDeserializer())
|
.registerTypeAdapter(TransferOperation.class, new TransferOperation.TransferDeserializer())
|
||||||
|
.registerTypeAdapter(LimitOrderCreateOperation.class, new LimitOrderCreateOperation.LimitOrderCreateDeserializer())
|
||||||
|
.registerTypeAdapter(CustomOperation.class, new CustomOperation.CustomOperationDeserializer())
|
||||||
.registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer())
|
.registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer())
|
||||||
.create();
|
.create();
|
||||||
WitnessResponse<Block> blockResponse = gson.fromJson(response, BlockResponse);
|
WitnessResponse<Block> blockResponse = gson.fromJson(response, BlockResponse);
|
||||||
|
|
|
@ -26,6 +26,7 @@ import cy.agorise.graphenej.models.DynamicGlobalProperties;
|
||||||
import cy.agorise.graphenej.models.SubscriptionResponse;
|
import cy.agorise.graphenej.models.SubscriptionResponse;
|
||||||
import cy.agorise.graphenej.models.WitnessResponse;
|
import cy.agorise.graphenej.models.WitnessResponse;
|
||||||
import cy.agorise.graphenej.objects.Memo;
|
import cy.agorise.graphenej.objects.Memo;
|
||||||
|
import cy.agorise.graphenej.operations.CustomOperation;
|
||||||
import cy.agorise.graphenej.operations.LimitOrderCreateOperation;
|
import cy.agorise.graphenej.operations.LimitOrderCreateOperation;
|
||||||
import cy.agorise.graphenej.operations.TransferOperation;
|
import cy.agorise.graphenej.operations.TransferOperation;
|
||||||
|
|
||||||
|
@ -89,6 +90,7 @@ public class SubscriptionMessagesHub extends BaseGrapheneHandler implements Subs
|
||||||
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(LimitOrderCreateOperation.class, new LimitOrderCreateOperation.LimitOrderCreateDeserializer());
|
||||||
|
builder.registerTypeAdapter(CustomOperation.class, new CustomOperation.CustomOperationDeserializer());
|
||||||
builder.registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer());
|
builder.registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer());
|
||||||
builder.registerTypeAdapter(UserAccount.class, new UserAccount.UserAccountSimpleDeserializer());
|
builder.registerTypeAdapter(UserAccount.class, new UserAccount.UserAccountSimpleDeserializer());
|
||||||
builder.registerTypeAdapter(DynamicGlobalProperties.class, new DynamicGlobalProperties.DynamicGlobalPropertiesDeserializer());
|
builder.registerTypeAdapter(DynamicGlobalProperties.class, new DynamicGlobalProperties.DynamicGlobalPropertiesDeserializer());
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
package cy.agorise.graphenej.operations;
|
package cy.agorise.graphenej.operations;
|
||||||
|
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.*;
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import cy.agorise.graphenej.*;
|
import cy.agorise.graphenej.*;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class CustomOperation extends BaseOperation {
|
public class CustomOperation extends BaseOperation {
|
||||||
private static final String KEY_FEE = "fee";
|
private static final String KEY_FEE = "fee";
|
||||||
private static final String KEY_PAYER = "payer";
|
private static final String KEY_PAYER = "payer";
|
||||||
private static final String KEY_REQUIRED_AUTH = "required_auths";
|
private static final String KEY_REQUIRED_AUTHS = "required_auths";
|
||||||
private static final String KEY_ID = "id";
|
private static final String KEY_ID = "id";
|
||||||
private static final String KEY_DATA = "data";
|
private static final String KEY_DATA = "data";
|
||||||
|
|
||||||
|
@ -113,7 +112,7 @@ public class CustomOperation extends BaseOperation {
|
||||||
requiredAuthArray.add(userAccount.getObjectId());
|
requiredAuthArray.add(userAccount.getObjectId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jsonObject.add(KEY_REQUIRED_AUTH, requiredAuthArray);
|
jsonObject.add(KEY_REQUIRED_AUTHS, requiredAuthArray);
|
||||||
jsonObject.addProperty(KEY_ID, operationId);
|
jsonObject.addProperty(KEY_ID, operationId);
|
||||||
jsonObject.addProperty(KEY_DATA, Util.bytesToHex(Util.hexlify(data)));
|
jsonObject.addProperty(KEY_DATA, Util.bytesToHex(Util.hexlify(data)));
|
||||||
|
|
||||||
|
@ -121,4 +120,66 @@ public class CustomOperation extends BaseOperation {
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializer used to convert the JSON-formatted representation of a custom_operation
|
||||||
|
* into its java object version.
|
||||||
|
*
|
||||||
|
* The following is an example of the serialized form of this operation:
|
||||||
|
*
|
||||||
|
* [
|
||||||
|
* 35,
|
||||||
|
* {
|
||||||
|
* "fee": {
|
||||||
|
* "amount": 100000,
|
||||||
|
* "asset_id": "1.3.0"
|
||||||
|
* },
|
||||||
|
* "payer": "1.2.20",
|
||||||
|
* "required_auths": [
|
||||||
|
* "1.2.20"
|
||||||
|
* ],
|
||||||
|
* "id": 61166,
|
||||||
|
* "data": "736f6d652064617461"
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
*/
|
||||||
|
public static class CustomOperationDeserializer implements JsonDeserializer<CustomOperation> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CustomOperation 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 serializedCustomOperation = json.getAsJsonArray();
|
||||||
|
if (serializedCustomOperation.get(0).getAsInt() != OperationType.CUSTOM_OPERATION.ordinal()){
|
||||||
|
// If the operation type does not correspond to a custom operation, we return null
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
// Calling itself recursively, this is only done once, so there will be no problems.
|
||||||
|
return context.deserialize(serializedCustomOperation.get(1), CustomOperation.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);
|
||||||
|
String payerId = jsonObject.get(KEY_PAYER) .getAsString();
|
||||||
|
UserAccount payer = new UserAccount(payerId);
|
||||||
|
List<UserAccount> requiredAuths = new LinkedList<>();
|
||||||
|
JsonElement requiredAuthsElement = jsonObject.get(KEY_REQUIRED_AUTHS);
|
||||||
|
if ((requiredAuthsElement != null) && (requiredAuthsElement.isJsonArray())) {
|
||||||
|
JsonArray requiredAuthsArray = requiredAuthsElement.getAsJsonArray();
|
||||||
|
for (JsonElement jsonElement : requiredAuthsArray) {
|
||||||
|
String userAccountId = jsonElement.getAsString();
|
||||||
|
requiredAuths.add(new UserAccount(userAccountId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int operationId = jsonObject.get(KEY_ID).getAsInt();
|
||||||
|
String data = new String(Util.hexToBytes(jsonObject.get(KEY_DATA).getAsString()));
|
||||||
|
|
||||||
|
return new CustomOperation(fee, payer, operationId, requiredAuths, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue