From 229590457b745359708264171a20240dbf3bc6ee Mon Sep 17 00:00:00 2001 From: "Nelson R. Perez" Date: Wed, 5 Sep 2018 21:04:46 -0500 Subject: [PATCH] - Added support for the 'get_account_history_by_operations' API call - Introduced a test case for the de-serialization of the HistoryOperationDetail object instance - Making the sample app use the newly introduced 'get_account_history_by_operations' API call --- .../cy/agorise/graphenej/BaseOperation.java | 59 +++++++++++++++- .../java/cy/agorise/graphenej/Extensions.java | 20 +++++- .../main/java/cy/agorise/graphenej/RPC.java | 1 + .../api/android/DeserializationMap.java | 17 +++++ .../graphenej/api/android/NetworkService.java | 7 +- .../calls/GetAccountHistoryByOperations.java | 69 +++++++++++++++++++ .../models/HistoryOperationDetail.java | 28 ++++++++ .../graphenej/models/OperationHistory.java | 13 ++-- .../api/GetRelativeAccountHistoryTest.java | 2 +- .../models/HistoryOperationDetailsTest.java | 40 +++++++++++ .../cy/agorise/labs/sample/CallsActivity.java | 1 + .../labs/sample/PerformCallActivity.java | 61 ++++++++++------ sample/src/main/res/values/strings.xml | 6 ++ 13 files changed, 290 insertions(+), 34 deletions(-) create mode 100644 graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetAccountHistoryByOperations.java create mode 100644 graphenej/src/main/java/cy/agorise/graphenej/models/HistoryOperationDetail.java create mode 100644 graphenej/src/test/java/cy/agorise/graphenej/models/HistoryOperationDetailsTest.java diff --git a/graphenej/src/main/java/cy/agorise/graphenej/BaseOperation.java b/graphenej/src/main/java/cy/agorise/graphenej/BaseOperation.java index bafbea9..3d5666c 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/BaseOperation.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/BaseOperation.java @@ -1,12 +1,19 @@ package cy.agorise.graphenej; import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; + +import java.lang.reflect.Type; + import cy.agorise.graphenej.interfaces.ByteSerializable; import cy.agorise.graphenej.interfaces.JsonSerializable; +import cy.agorise.graphenej.operations.TransferOperation; /** - * Created by nelson on 11/5/16. + * Base class that represents a generic operation */ public abstract class BaseOperation implements ByteSerializable, JsonSerializable { @@ -32,4 +39,54 @@ public abstract class BaseOperation implements ByteSerializable, JsonSerializabl array.add(this.getId()); return array; } + + /** + *

+ * De-serializer used to unpack data from a generic operation. The general format used in the + * JSON-RPC blockchain API is the following: + *

+ * + * [OPERATION_ID, OPERATION_OBJECT]
+ * + *

+ * Where OPERATION_ID is one of the operations defined in {@link cy.agorise.graphenej.OperationType} + * and OPERATION_OBJECT is the actual operation serialized in the JSON format. + *

+ * Here's an example of this serialized form for a transfer operation:

+ *
+     *[
+     *   0,
+     *   {
+     *       "fee": {
+     *           "amount": 264174,
+     *           "asset_id": "1.3.0"
+     *       },
+     *       "from": "1.2.138632",
+     *       "to": "1.2.129848",
+     *       "amount": {
+     *           "amount": 100,
+     *           "asset_id": "1.3.0"
+     *       },
+     *       "extensions": []
+     *   }
+     *]
+     *

+ * If this class is used, this serialized data will be translated to a TransferOperation object instance.
+ * + * TODO: Add support for operations other than the 'transfer' + */ + public static class OperationDeserializer implements JsonDeserializer { + + @Override + public BaseOperation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + BaseOperation operation = null; + if(json.isJsonArray()){ + JsonArray array = json.getAsJsonArray(); + if(array.get(0).getAsLong() == OperationType.TRANSFER_OPERATION.ordinal()){ + operation = context.deserialize(array.get(1), TransferOperation.class); + } + } + return operation; + } + } } diff --git a/graphenej/src/main/java/cy/agorise/graphenej/Extensions.java b/graphenej/src/main/java/cy/agorise/graphenej/Extensions.java index ada71a3..9e6bc66 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/Extensions.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/Extensions.java @@ -1,12 +1,17 @@ package cy.agorise.graphenej; import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; + +import java.lang.reflect.Type; +import java.util.ArrayList; + import cy.agorise.graphenej.interfaces.ByteSerializable; import cy.agorise.graphenej.interfaces.JsonSerializable; -import java.util.ArrayList; - /** * Created by nelson on 11/9/16. */ @@ -40,4 +45,15 @@ public class Extensions implements JsonSerializable, ByteSerializable { public int size(){ return extensions.size(); } + + /** + * Custom de-serializer used to avoid problems when de-serializing an object that contains + * an extension array. + */ + public static class ExtensionsDeserializer implements JsonDeserializer { + @Override + public Extensions deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + return null; + } + } } diff --git a/graphenej/src/main/java/cy/agorise/graphenej/RPC.java b/graphenej/src/main/java/cy/agorise/graphenej/RPC.java index d16660f..c0afa8c 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/RPC.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/RPC.java @@ -20,6 +20,7 @@ public class RPC { public static final String CALL_GET_KEY_REFERENCES = "get_key_references"; public static final String CALL_GET_RELATIVE_ACCOUNT_HISTORY = "get_relative_account_history"; public static final String CALL_GET_ACCOUNT_HISTORY = "get_account_history"; + public static final String CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS = "get_account_history_by_operations"; public static final String CALL_LOOKUP_ACCOUNTS = "lookup_accounts"; public static final String CALL_LIST_ASSETS = "list_assets"; public static final String CALL_GET_OBJECTS = "get_objects"; diff --git a/graphenej/src/main/java/cy/agorise/graphenej/api/android/DeserializationMap.java b/graphenej/src/main/java/cy/agorise/graphenej/api/android/DeserializationMap.java index 3fedb42..fa4ea68 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/api/android/DeserializationMap.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/api/android/DeserializationMap.java @@ -13,10 +13,13 @@ import cy.agorise.graphenej.Asset; import cy.agorise.graphenej.AssetAmount; import cy.agorise.graphenej.AssetOptions; import cy.agorise.graphenej.Authority; +import cy.agorise.graphenej.BaseOperation; +import cy.agorise.graphenej.Extensions; import cy.agorise.graphenej.LimitOrder; import cy.agorise.graphenej.Transaction; import cy.agorise.graphenej.UserAccount; import cy.agorise.graphenej.api.calls.GetAccountByName; +import cy.agorise.graphenej.api.calls.GetAccountHistoryByOperations; import cy.agorise.graphenej.api.calls.GetAccounts; import cy.agorise.graphenej.api.calls.GetBlock; import cy.agorise.graphenej.api.calls.GetBlockHeader; @@ -31,6 +34,7 @@ import cy.agorise.graphenej.models.AccountProperties; import cy.agorise.graphenej.models.Block; import cy.agorise.graphenej.models.BlockHeader; import cy.agorise.graphenej.models.BucketObject; +import cy.agorise.graphenej.models.HistoryOperationDetail; import cy.agorise.graphenej.models.OperationHistory; import cy.agorise.graphenej.objects.Memo; import cy.agorise.graphenej.operations.CustomOperation; @@ -139,6 +143,19 @@ public class DeserializationMap { .registerTypeAdapter(LimitOrder.class, new LimitOrder.LimitOrderDeserializer()) .create(); mGsonMap.put(GetLimitOrders.class, getLimitOrdersGson); + + // GetAccountHistoryByOperations + mClassMap.put(GetAccountHistoryByOperations.class, HistoryOperationDetail.class); + Gson getAccountHistoryByOperationsGson = new GsonBuilder() + .setExclusionStrategies(new DeserializationMap.SkipAccountOptionsStrategy(), new DeserializationMap.SkipAssetOptionsStrategy()) + .registerTypeAdapter(BaseOperation.class, new BaseOperation.OperationDeserializer()) + .registerTypeAdapter(OperationHistory.class, new OperationHistory.OperationHistoryDeserializer()) + .registerTypeAdapter(Extensions.class, new Extensions.ExtensionsDeserializer()) + .registerTypeAdapter(Memo.class, new Memo.MemoDeserializer()) + .registerTypeAdapter(UserAccount.class, new UserAccount.UserAccountSimpleDeserializer()) + .registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer()) + .create(); + mGsonMap.put(GetAccountHistoryByOperations.class, getAccountHistoryByOperationsGson); } public Class getReceivedClass(Class _class){ diff --git a/graphenej/src/main/java/cy/agorise/graphenej/api/android/NetworkService.java b/graphenej/src/main/java/cy/agorise/graphenej/api/android/NetworkService.java index d12b2c5..6b29e66 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/api/android/NetworkService.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/api/android/NetworkService.java @@ -42,6 +42,7 @@ import cy.agorise.graphenej.models.Block; import cy.agorise.graphenej.models.BlockHeader; import cy.agorise.graphenej.models.BucketObject; import cy.agorise.graphenej.models.DynamicGlobalProperties; +import cy.agorise.graphenej.models.HistoryOperationDetail; import cy.agorise.graphenej.models.JsonRpcNotification; import cy.agorise.graphenej.models.JsonRpcResponse; import cy.agorise.graphenej.models.OperationHistory; @@ -359,7 +360,11 @@ public class NetworkService extends Service { } else if(responsePayloadClass == AccountProperties.class){ Type GetAccountByNameResponse = new TypeToken>(){}.getType(); parsedResponse = gson.fromJson(text, GetAccountByNameResponse); - } else if(responsePayloadClass == List.class){ + } else if(responsePayloadClass == HistoryOperationDetail.class){ + Type GetAccountHistoryByOperationsResponse = new TypeToken>(){}.getType(); + Log.d(TAG,"*> "+text); + parsedResponse = gson.fromJson(text, GetAccountHistoryByOperationsResponse); + }else if(responsePayloadClass == List.class){ // If the response payload is a List, further inquiry is required in order to // determine a list of what is expected here if(requestClass == GetAccounts.class){ diff --git a/graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetAccountHistoryByOperations.java b/graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetAccountHistoryByOperations.java new file mode 100644 index 0000000..4a94783 --- /dev/null +++ b/graphenej/src/main/java/cy/agorise/graphenej/api/calls/GetAccountHistoryByOperations.java @@ -0,0 +1,69 @@ +package cy.agorise.graphenej.api.calls; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import cy.agorise.graphenej.OperationType; +import cy.agorise.graphenej.RPC; +import cy.agorise.graphenej.UserAccount; +import cy.agorise.graphenej.api.ApiAccess; +import cy.agorise.graphenej.models.ApiCall; + +public class GetAccountHistoryByOperations implements ApiCallable { + + public static final int REQUIRED_API = ApiAccess.API_HISTORY; + + private UserAccount mUserAccount; + private List mOperationTypes; + private long mStart; + private long mLimit; + + /** + * @param userAccount The user account that should be queried + * @param operationsTypes The IDs of the operation we want to get operations in the account( 0 = transfer , 1 = limit order create, ...) + * @param start The sequence number where to start listing operations + * @param limit The max number of entries to return (from start number) + */ + public GetAccountHistoryByOperations(UserAccount userAccount, List operationsTypes, long start, long limit){ + this.mUserAccount = userAccount; + this.mOperationTypes = operationsTypes; + this.mStart = start; + this.mLimit = limit; + } + + /** + * @param userAccount The user account that should be queried + * @param operationsTypes The IDs of the operation we want to get operations in the account( 0 = transfer , 1 = limit order create, ...) + * @param start The sequence number where to start listing operations + * @param limit The max number of entries to return (from start number) + */ + public GetAccountHistoryByOperations(String userAccount, List operationsTypes, long start, long limit){ + if(userAccount.matches("^1\\.2\\.\\d*$")){ + this.mUserAccount = new UserAccount(userAccount); + }else{ + this.mUserAccount = new UserAccount("", userAccount); + } + this.mOperationTypes = operationsTypes; + this.mStart = start; + this.mLimit = limit; + } + + @Override + public ApiCall toApiCall(int apiId, long sequenceId) { + ArrayList params = new ArrayList<>(); + if(mUserAccount.getName() != null){ + params.add(mUserAccount.getName()); + }else{ + params.add(mUserAccount.getObjectId()); + } + ArrayList operationTypes = new ArrayList<>(); + for(OperationType operationType : mOperationTypes){ + operationTypes.add(operationType.ordinal()); + } + params.add(operationTypes); + params.add(mStart); + params.add(mLimit); + return new ApiCall(apiId, RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS, params, RPC.VERSION, sequenceId); + } +} diff --git a/graphenej/src/main/java/cy/agorise/graphenej/models/HistoryOperationDetail.java b/graphenej/src/main/java/cy/agorise/graphenej/models/HistoryOperationDetail.java new file mode 100644 index 0000000..096df22 --- /dev/null +++ b/graphenej/src/main/java/cy/agorise/graphenej/models/HistoryOperationDetail.java @@ -0,0 +1,28 @@ +package cy.agorise.graphenej.models; + +import java.util.List; + +/** + * Model class used to represent the struct defined in graphene::app::history_operation_detail and + * returned as response to the 'get_account_history_by_operations' API call. + */ +public class HistoryOperationDetail { + private long total_count; + List operation_history_objs; + + public long getTotalCount() { + return total_count; + } + + public void setTotalCount(long total_count) { + this.total_count = total_count; + } + + public List getOperationHistoryObjs() { + return operation_history_objs; + } + + public void setOperationHistoryObjs(List operation_history_objs) { + this.operation_history_objs = operation_history_objs; + } +} 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 059caf2..09f5561 100644 --- a/graphenej/src/main/java/cy/agorise/graphenej/models/OperationHistory.java +++ b/graphenej/src/main/java/cy/agorise/graphenej/models/OperationHistory.java @@ -9,8 +9,8 @@ import com.google.gson.JsonParseException; import java.io.Serializable; import java.lang.reflect.Type; +import cy.agorise.graphenej.BaseOperation; import cy.agorise.graphenej.GrapheneObject; -import cy.agorise.graphenej.operations.TransferOperation; /** @@ -27,7 +27,7 @@ public class OperationHistory extends GrapheneObject implements Serializable { public static final String KEY_OP_IN_TRX = "op_in_trx"; public static final String KEY_VIRTUAL_OP = "virtual_op"; - private TransferOperation op; + private BaseOperation op; public Object[] result; private long block_num; private long trx_in_block; @@ -38,11 +38,11 @@ public class OperationHistory extends GrapheneObject implements Serializable { super(id); } - public TransferOperation getOperation() { + public BaseOperation getOperation() { return op; } - public void setOperation(TransferOperation op) { + public void setOperation(BaseOperation op) { this.op = op; } @@ -122,14 +122,13 @@ public class OperationHistory extends GrapheneObject implements Serializable { 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); + BaseOperation operation = context.deserialize(jsonObject.get(KEY_OP), BaseOperation.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.setOperation(operation); operationHistory.setVirtualOp(virtualOp); return operationHistory; } diff --git a/graphenej/src/test/java/cy/agorise/graphenej/api/GetRelativeAccountHistoryTest.java b/graphenej/src/test/java/cy/agorise/graphenej/api/GetRelativeAccountHistoryTest.java index e937191..8b2a4e5 100644 --- a/graphenej/src/test/java/cy/agorise/graphenej/api/GetRelativeAccountHistoryTest.java +++ b/graphenej/src/test/java/cy/agorise/graphenej/api/GetRelativeAccountHistoryTest.java @@ -55,7 +55,7 @@ public class GetRelativeAccountHistoryTest extends BaseApiTest { for(OperationHistory historicalTransfer : resp.result){ if(historicalTransfer.getOperation() != null){ System.out.println("Got transfer operation!"); - TransferOperation transferOperation = historicalTransfer.getOperation(); + TransferOperation transferOperation = (TransferOperation) historicalTransfer.getOperation(); System.out.println(String.format("%s - > %s, memo: %s", transferOperation.getFrom().getObjectId(), transferOperation.getTo().getObjectId(), diff --git a/graphenej/src/test/java/cy/agorise/graphenej/models/HistoryOperationDetailsTest.java b/graphenej/src/test/java/cy/agorise/graphenej/models/HistoryOperationDetailsTest.java new file mode 100644 index 0000000..7bc9576 --- /dev/null +++ b/graphenej/src/test/java/cy/agorise/graphenej/models/HistoryOperationDetailsTest.java @@ -0,0 +1,40 @@ +package cy.agorise.graphenej.models; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; + +import junit.framework.Assert; + +import org.junit.Test; + +import java.lang.reflect.Type; + +import cy.agorise.graphenej.AssetAmount; +import cy.agorise.graphenej.BaseOperation; +import cy.agorise.graphenej.Extensions; +import cy.agorise.graphenej.UserAccount; +import cy.agorise.graphenej.api.android.DeserializationMap; +import cy.agorise.graphenej.objects.Memo; + +public class HistoryOperationDetailsTest { + + @Test + public void testDeserialization(){ + String text = "{\"id\":5,\"jsonrpc\":\"2.0\",\"result\":{\"total_count\":2,\"operation_history_objs\":[{\"id\":\"1.11.5701809\",\"op\":[0,{\"fee\":{\"amount\":264174,\"asset_id\":\"1.3.0\"},\"from\":\"1.2.99700\",\"to\":\"1.2.138632\",\"amount\":{\"amount\":20000,\"asset_id\":\"1.3.120\"},\"extensions\":[]}],\"result\":[0,{}],\"block_num\":11094607,\"trx_in_block\":0,\"op_in_trx\":0,\"virtual_op\":31767},{\"id\":\"1.11.5701759\",\"op\":[0,{\"fee\":{\"amount\":264174,\"asset_id\":\"1.3.0\"},\"from\":\"1.2.99700\",\"to\":\"1.2.138632\",\"amount\":{\"amount\":10000000,\"asset_id\":\"1.3.0\"},\"extensions\":[]}],\"result\":[0,{}],\"block_num\":11094501,\"trx_in_block\":0,\"op_in_trx\":0,\"virtual_op\":31717}]}}\n"; + Gson gson = new GsonBuilder() + .setExclusionStrategies(new DeserializationMap.SkipAccountOptionsStrategy(), new DeserializationMap.SkipAssetOptionsStrategy()) + .registerTypeAdapter(BaseOperation.class, new BaseOperation.OperationDeserializer()) + .registerTypeAdapter(OperationHistory.class, new OperationHistory.OperationHistoryDeserializer()) + .registerTypeAdapter(Memo.class, new Memo.MemoSerializer()) + .registerTypeAdapter(Extensions.class, new Extensions.ExtensionsDeserializer()) + .registerTypeAdapter(UserAccount.class, new UserAccount.UserAccountSimpleDeserializer()) + .registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer()) + .create(); + + Type GetAccountHistoryByOperationsResponse = new TypeToken>(){}.getType(); + JsonRpcResponse response = gson.fromJson(text, GetAccountHistoryByOperationsResponse); + Assert.assertNotNull(response.result); + Assert.assertNotNull(response.result.operation_history_objs); + } +} diff --git a/sample/src/main/java/cy/agorise/labs/sample/CallsActivity.java b/sample/src/main/java/cy/agorise/labs/sample/CallsActivity.java index 6ccf3ef..19b677e 100644 --- a/sample/src/main/java/cy/agorise/labs/sample/CallsActivity.java +++ b/sample/src/main/java/cy/agorise/labs/sample/CallsActivity.java @@ -47,6 +47,7 @@ public class CallsActivity extends AppCompatActivity { RPC.CALL_LIST_ASSETS, RPC.CALL_GET_ACCOUNT_BY_NAME, RPC.CALL_GET_LIMIT_ORDERS, + RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS, RPC.CALL_SET_SUBSCRIBE_CALLBACK }; diff --git a/sample/src/main/java/cy/agorise/labs/sample/PerformCallActivity.java b/sample/src/main/java/cy/agorise/labs/sample/PerformCallActivity.java index 8df6dd1..289dcfc 100644 --- a/sample/src/main/java/cy/agorise/labs/sample/PerformCallActivity.java +++ b/sample/src/main/java/cy/agorise/labs/sample/PerformCallActivity.java @@ -22,12 +22,14 @@ import java.util.HashMap; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; +import cy.agorise.graphenej.OperationType; import cy.agorise.graphenej.RPC; import cy.agorise.graphenej.UserAccount; import cy.agorise.graphenej.api.ConnectionStatusUpdate; import cy.agorise.graphenej.api.android.DeserializationMap; import cy.agorise.graphenej.api.android.RxBus; import cy.agorise.graphenej.api.calls.GetAccountByName; +import cy.agorise.graphenej.api.calls.GetAccountHistoryByOperations; import cy.agorise.graphenej.api.calls.GetAccounts; import cy.agorise.graphenej.api.calls.GetBlock; import cy.agorise.graphenej.api.calls.GetLimitOrders; @@ -35,7 +37,6 @@ import cy.agorise.graphenej.api.calls.GetObjects; import cy.agorise.graphenej.api.calls.ListAssets; import cy.agorise.graphenej.models.JsonRpcResponse; import cy.agorise.graphenej.objects.Memo; -import cy.agorise.graphenej.operations.TransferOperation; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; @@ -83,7 +84,6 @@ public class PerformCallActivity extends ConnectedActivity { private Gson gson = new GsonBuilder() .setExclusionStrategies(new DeserializationMap.SkipAccountOptionsStrategy(), new DeserializationMap.SkipAssetOptionsStrategy()) - .registerTypeAdapter(TransferOperation.class, new TransferOperation.TransferDeserializer()) .registerTypeAdapter(Memo.class, new Memo.MemoSerializer()) .create(); @@ -125,6 +125,9 @@ public class PerformCallActivity extends ConnectedActivity { case RPC.CALL_GET_ACCOUNT_BY_NAME: setupAccountByName(); break; + case RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS: + setupGetAccountHistoryByOperations(); + break; case RPC.CALL_GET_LIMIT_ORDERS: setupGetLimitOrders(); default: @@ -210,6 +213,21 @@ public class PerformCallActivity extends ConnectedActivity { param1.setInputType(InputType.TYPE_CLASS_TEXT); } + private void setupGetAccountHistoryByOperations(){ + requiredInput(4); + Resources resources = getResources(); + mParam1View.setHint(resources.getString(R.string.get_account_history_by_operations_arg1)); + mParam2View.setHint(resources.getString(R.string.get_account_history_by_operations_arg2)); + mParam3View.setHint(resources.getString(R.string.get_account_history_by_operations_arg3)); + mParam4View.setHint(resources.getString(R.string.get_account_history_by_operations_arg4)); + + param2.setText("0"); // Only transfer de-serialization is currently supported by the library! + param2.setEnabled(false); + param2.setInputType(InputType.TYPE_CLASS_NUMBER); + param3.setInputType(InputType.TYPE_CLASS_NUMBER); + param4.setInputType(InputType.TYPE_CLASS_NUMBER); + } + private void setupGetLimitOrders(){ requiredInput(3); Resources resources = getResources(); @@ -274,6 +292,10 @@ public class PerformCallActivity extends ConnectedActivity { break; case RPC.CALL_GET_LIMIT_ORDERS: getLimitOrders(); + break; + case RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS: + getAccountHistoryByOperations(); + break; default: Log.d(TAG,"Default called"); } @@ -334,6 +356,20 @@ public class PerformCallActivity extends ConnectedActivity { } } + private void getAccountHistoryByOperations(){ + try{ + String account = param1.getText().toString(); + ArrayList operationTypes = new ArrayList<>(); + operationTypes.add(OperationType.TRANSFER_OPERATION); // Currently restricted to transfer operations + long start = Long.parseLong(param3.getText().toString()); + long limit = Long.parseLong(param4.getText().toString()); + long id = mNetworkService.sendMessage(new GetAccountHistoryByOperations(account, operationTypes, start, limit), GetAccountHistoryByOperations.REQUIRED_API); + }catch(NumberFormatException e){ + Toast.makeText(this, getString(R.string.error_number_format), Toast.LENGTH_SHORT).show(); + Log.e(TAG,"NumberFormatException while trying to read arguments for 'get_account_history_by_operations'. Msg: "+e.getMessage()); + } + } + /** * Internal method that will decide what to do with each JSON-RPC response * @@ -345,36 +381,17 @@ public class PerformCallActivity extends ConnectedActivity { String request = responseMap.get(id); switch(request){ case RPC.CALL_GET_ACCOUNTS: - mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n"); - break; case RPC.CALL_GET_BLOCK: - mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n"); - break; case RPC.CALL_GET_BLOCK_HEADER: - mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n"); - break; case RPC.CALL_GET_MARKET_HISTORY: - mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n"); - break; case RPC.CALL_GET_ACCOUNT_HISTORY: - mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n"); - break; case RPC.CALL_GET_RELATIVE_ACCOUNT_HISTORY: - mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n"); - break; case RPC.CALL_GET_REQUIRED_FEES: - mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n"); - break; case RPC.CALL_LOOKUP_ASSET_SYMBOLS: - mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n"); - break; case RPC.CALL_LIST_ASSETS: - mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n"); - break; case RPC.CALL_GET_ACCOUNT_BY_NAME: - mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n"); - break; case RPC.CALL_GET_LIMIT_ORDERS: + case RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS: mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n"); break; default: diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml index fce56cc..1776b5c 100644 --- a/sample/src/main/res/values/strings.xml +++ b/sample/src/main/res/values/strings.xml @@ -41,6 +41,12 @@ Account name + + Account id or name + Operaton type (only transfer type is supported) + Start sequence number + Limit + Asset A Asset B