- 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
This commit is contained in:
parent
f8326093a2
commit
229590457b
13 changed files with 290 additions and 34 deletions
|
@ -1,12 +1,19 @@
|
||||||
package cy.agorise.graphenej;
|
package cy.agorise.graphenej;
|
||||||
|
|
||||||
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.JsonParseException;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
import cy.agorise.graphenej.interfaces.ByteSerializable;
|
import cy.agorise.graphenej.interfaces.ByteSerializable;
|
||||||
import cy.agorise.graphenej.interfaces.JsonSerializable;
|
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 {
|
public abstract class BaseOperation implements ByteSerializable, JsonSerializable {
|
||||||
|
|
||||||
|
@ -32,4 +39,54 @@ public abstract class BaseOperation implements ByteSerializable, JsonSerializabl
|
||||||
array.add(this.getId());
|
array.add(this.getId());
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* De-serializer used to unpack data from a generic operation. The general format used in the
|
||||||
|
* JSON-RPC blockchain API is the following:
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <code>[OPERATION_ID, OPERATION_OBJECT]</code><br>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Where <code>OPERATION_ID</code> is one of the operations defined in {@link cy.agorise.graphenej.OperationType}
|
||||||
|
* and <code>OPERATION_OBJECT</code> is the actual operation serialized in the JSON format.
|
||||||
|
* </p>
|
||||||
|
* Here's an example of this serialized form for a transfer operation:<br><br>
|
||||||
|
*<pre>
|
||||||
|
*[
|
||||||
|
* 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": []
|
||||||
|
* }
|
||||||
|
*]
|
||||||
|
*</pre><br>
|
||||||
|
* If this class is used, this serialized data will be translated to a TransferOperation object instance.<br>
|
||||||
|
*
|
||||||
|
* TODO: Add support for operations other than the 'transfer'
|
||||||
|
*/
|
||||||
|
public static class OperationDeserializer implements JsonDeserializer<BaseOperation> {
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
package cy.agorise.graphenej;
|
package cy.agorise.graphenej;
|
||||||
|
|
||||||
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.JsonParseException;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import cy.agorise.graphenej.interfaces.ByteSerializable;
|
import cy.agorise.graphenej.interfaces.ByteSerializable;
|
||||||
import cy.agorise.graphenej.interfaces.JsonSerializable;
|
import cy.agorise.graphenej.interfaces.JsonSerializable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by nelson on 11/9/16.
|
* Created by nelson on 11/9/16.
|
||||||
*/
|
*/
|
||||||
|
@ -40,4 +45,15 @@ public class Extensions implements JsonSerializable, ByteSerializable {
|
||||||
public int size(){
|
public int size(){
|
||||||
return extensions.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<Extensions> {
|
||||||
|
@Override
|
||||||
|
public Extensions deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ public class RPC {
|
||||||
public static final String CALL_GET_KEY_REFERENCES = "get_key_references";
|
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_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 = "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_LOOKUP_ACCOUNTS = "lookup_accounts";
|
||||||
public static final String CALL_LIST_ASSETS = "list_assets";
|
public static final String CALL_LIST_ASSETS = "list_assets";
|
||||||
public static final String CALL_GET_OBJECTS = "get_objects";
|
public static final String CALL_GET_OBJECTS = "get_objects";
|
||||||
|
|
|
@ -13,10 +13,13 @@ import cy.agorise.graphenej.Asset;
|
||||||
import cy.agorise.graphenej.AssetAmount;
|
import cy.agorise.graphenej.AssetAmount;
|
||||||
import cy.agorise.graphenej.AssetOptions;
|
import cy.agorise.graphenej.AssetOptions;
|
||||||
import cy.agorise.graphenej.Authority;
|
import cy.agorise.graphenej.Authority;
|
||||||
|
import cy.agorise.graphenej.BaseOperation;
|
||||||
|
import cy.agorise.graphenej.Extensions;
|
||||||
import cy.agorise.graphenej.LimitOrder;
|
import cy.agorise.graphenej.LimitOrder;
|
||||||
import cy.agorise.graphenej.Transaction;
|
import cy.agorise.graphenej.Transaction;
|
||||||
import cy.agorise.graphenej.UserAccount;
|
import cy.agorise.graphenej.UserAccount;
|
||||||
import cy.agorise.graphenej.api.calls.GetAccountByName;
|
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.GetAccounts;
|
||||||
import cy.agorise.graphenej.api.calls.GetBlock;
|
import cy.agorise.graphenej.api.calls.GetBlock;
|
||||||
import cy.agorise.graphenej.api.calls.GetBlockHeader;
|
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.Block;
|
||||||
import cy.agorise.graphenej.models.BlockHeader;
|
import cy.agorise.graphenej.models.BlockHeader;
|
||||||
import cy.agorise.graphenej.models.BucketObject;
|
import cy.agorise.graphenej.models.BucketObject;
|
||||||
|
import cy.agorise.graphenej.models.HistoryOperationDetail;
|
||||||
import cy.agorise.graphenej.models.OperationHistory;
|
import cy.agorise.graphenej.models.OperationHistory;
|
||||||
import cy.agorise.graphenej.objects.Memo;
|
import cy.agorise.graphenej.objects.Memo;
|
||||||
import cy.agorise.graphenej.operations.CustomOperation;
|
import cy.agorise.graphenej.operations.CustomOperation;
|
||||||
|
@ -139,6 +143,19 @@ public class DeserializationMap {
|
||||||
.registerTypeAdapter(LimitOrder.class, new LimitOrder.LimitOrderDeserializer())
|
.registerTypeAdapter(LimitOrder.class, new LimitOrder.LimitOrderDeserializer())
|
||||||
.create();
|
.create();
|
||||||
mGsonMap.put(GetLimitOrders.class, getLimitOrdersGson);
|
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){
|
public Class getReceivedClass(Class _class){
|
||||||
|
|
|
@ -42,6 +42,7 @@ import cy.agorise.graphenej.models.Block;
|
||||||
import cy.agorise.graphenej.models.BlockHeader;
|
import cy.agorise.graphenej.models.BlockHeader;
|
||||||
import cy.agorise.graphenej.models.BucketObject;
|
import cy.agorise.graphenej.models.BucketObject;
|
||||||
import cy.agorise.graphenej.models.DynamicGlobalProperties;
|
import cy.agorise.graphenej.models.DynamicGlobalProperties;
|
||||||
|
import cy.agorise.graphenej.models.HistoryOperationDetail;
|
||||||
import cy.agorise.graphenej.models.JsonRpcNotification;
|
import cy.agorise.graphenej.models.JsonRpcNotification;
|
||||||
import cy.agorise.graphenej.models.JsonRpcResponse;
|
import cy.agorise.graphenej.models.JsonRpcResponse;
|
||||||
import cy.agorise.graphenej.models.OperationHistory;
|
import cy.agorise.graphenej.models.OperationHistory;
|
||||||
|
@ -359,7 +360,11 @@ public class NetworkService extends Service {
|
||||||
} else if(responsePayloadClass == AccountProperties.class){
|
} else if(responsePayloadClass == AccountProperties.class){
|
||||||
Type GetAccountByNameResponse = new TypeToken<JsonRpcResponse<AccountProperties>>(){}.getType();
|
Type GetAccountByNameResponse = new TypeToken<JsonRpcResponse<AccountProperties>>(){}.getType();
|
||||||
parsedResponse = gson.fromJson(text, GetAccountByNameResponse);
|
parsedResponse = gson.fromJson(text, GetAccountByNameResponse);
|
||||||
} else if(responsePayloadClass == List.class){
|
} else if(responsePayloadClass == HistoryOperationDetail.class){
|
||||||
|
Type GetAccountHistoryByOperationsResponse = new TypeToken<JsonRpcResponse<HistoryOperationDetail>>(){}.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
|
// If the response payload is a List, further inquiry is required in order to
|
||||||
// determine a list of what is expected here
|
// determine a list of what is expected here
|
||||||
if(requestClass == GetAccounts.class){
|
if(requestClass == GetAccounts.class){
|
||||||
|
|
|
@ -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<OperationType> 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<OperationType> 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<OperationType> 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<Serializable> params = new ArrayList<>();
|
||||||
|
if(mUserAccount.getName() != null){
|
||||||
|
params.add(mUserAccount.getName());
|
||||||
|
}else{
|
||||||
|
params.add(mUserAccount.getObjectId());
|
||||||
|
}
|
||||||
|
ArrayList<Integer> 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<OperationHistory> operation_history_objs;
|
||||||
|
|
||||||
|
public long getTotalCount() {
|
||||||
|
return total_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotalCount(long total_count) {
|
||||||
|
this.total_count = total_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<OperationHistory> getOperationHistoryObjs() {
|
||||||
|
return operation_history_objs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOperationHistoryObjs(List<OperationHistory> operation_history_objs) {
|
||||||
|
this.operation_history_objs = operation_history_objs;
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,8 +9,8 @@ import com.google.gson.JsonParseException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import cy.agorise.graphenej.BaseOperation;
|
||||||
import cy.agorise.graphenej.GrapheneObject;
|
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_OP_IN_TRX = "op_in_trx";
|
||||||
public static final String KEY_VIRTUAL_OP = "virtual_op";
|
public static final String KEY_VIRTUAL_OP = "virtual_op";
|
||||||
|
|
||||||
private TransferOperation op;
|
private BaseOperation op;
|
||||||
public Object[] result;
|
public Object[] result;
|
||||||
private long block_num;
|
private long block_num;
|
||||||
private long trx_in_block;
|
private long trx_in_block;
|
||||||
|
@ -38,11 +38,11 @@ public class OperationHistory extends GrapheneObject implements Serializable {
|
||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransferOperation getOperation() {
|
public BaseOperation getOperation() {
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOperation(TransferOperation op) {
|
public void setOperation(BaseOperation op) {
|
||||||
this.op = op;
|
this.op = op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,14 +122,13 @@ public class OperationHistory extends GrapheneObject implements Serializable {
|
||||||
long blockNum = jsonObject.get(KEY_BLOCK_NUM).getAsLong();
|
long blockNum = jsonObject.get(KEY_BLOCK_NUM).getAsLong();
|
||||||
long trxInBlock = jsonObject.get(KEY_TRX_IN_BLOCK).getAsLong();
|
long trxInBlock = jsonObject.get(KEY_TRX_IN_BLOCK).getAsLong();
|
||||||
long opInTrx = jsonObject.get(KEY_OP_IN_TRX).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();
|
long virtualOp = jsonObject.get(KEY_VIRTUAL_OP).getAsLong();
|
||||||
|
|
||||||
OperationHistory operationHistory = new OperationHistory(id);
|
OperationHistory operationHistory = new OperationHistory(id);
|
||||||
operationHistory.setBlockNum(blockNum);
|
operationHistory.setBlockNum(blockNum);
|
||||||
operationHistory.setTransactionsInBlock(trxInBlock);
|
operationHistory.setTransactionsInBlock(trxInBlock);
|
||||||
operationHistory.setOperationsInTrx(opInTrx);
|
operationHistory.setOperationsInTrx(opInTrx);
|
||||||
operationHistory.setOperation(transferOperation);
|
operationHistory.setOperation(operation);
|
||||||
operationHistory.setVirtualOp(virtualOp);
|
operationHistory.setVirtualOp(virtualOp);
|
||||||
return operationHistory;
|
return operationHistory;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class GetRelativeAccountHistoryTest extends BaseApiTest {
|
||||||
for(OperationHistory historicalTransfer : resp.result){
|
for(OperationHistory historicalTransfer : resp.result){
|
||||||
if(historicalTransfer.getOperation() != null){
|
if(historicalTransfer.getOperation() != null){
|
||||||
System.out.println("Got transfer operation!");
|
System.out.println("Got transfer operation!");
|
||||||
TransferOperation transferOperation = historicalTransfer.getOperation();
|
TransferOperation transferOperation = (TransferOperation) historicalTransfer.getOperation();
|
||||||
System.out.println(String.format("%s - > %s, memo: %s",
|
System.out.println(String.format("%s - > %s, memo: %s",
|
||||||
transferOperation.getFrom().getObjectId(),
|
transferOperation.getFrom().getObjectId(),
|
||||||
transferOperation.getTo().getObjectId(),
|
transferOperation.getTo().getObjectId(),
|
||||||
|
|
|
@ -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<JsonRpcResponse<HistoryOperationDetail>>(){}.getType();
|
||||||
|
JsonRpcResponse<HistoryOperationDetail> response = gson.fromJson(text, GetAccountHistoryByOperationsResponse);
|
||||||
|
Assert.assertNotNull(response.result);
|
||||||
|
Assert.assertNotNull(response.result.operation_history_objs);
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,6 +47,7 @@ public class CallsActivity extends AppCompatActivity {
|
||||||
RPC.CALL_LIST_ASSETS,
|
RPC.CALL_LIST_ASSETS,
|
||||||
RPC.CALL_GET_ACCOUNT_BY_NAME,
|
RPC.CALL_GET_ACCOUNT_BY_NAME,
|
||||||
RPC.CALL_GET_LIMIT_ORDERS,
|
RPC.CALL_GET_LIMIT_ORDERS,
|
||||||
|
RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS,
|
||||||
RPC.CALL_SET_SUBSCRIBE_CALLBACK
|
RPC.CALL_SET_SUBSCRIBE_CALLBACK
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,12 +22,14 @@ import java.util.HashMap;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import butterknife.OnClick;
|
import butterknife.OnClick;
|
||||||
|
import cy.agorise.graphenej.OperationType;
|
||||||
import cy.agorise.graphenej.RPC;
|
import cy.agorise.graphenej.RPC;
|
||||||
import cy.agorise.graphenej.UserAccount;
|
import cy.agorise.graphenej.UserAccount;
|
||||||
import cy.agorise.graphenej.api.ConnectionStatusUpdate;
|
import cy.agorise.graphenej.api.ConnectionStatusUpdate;
|
||||||
import cy.agorise.graphenej.api.android.DeserializationMap;
|
import cy.agorise.graphenej.api.android.DeserializationMap;
|
||||||
import cy.agorise.graphenej.api.android.RxBus;
|
import cy.agorise.graphenej.api.android.RxBus;
|
||||||
import cy.agorise.graphenej.api.calls.GetAccountByName;
|
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.GetAccounts;
|
||||||
import cy.agorise.graphenej.api.calls.GetBlock;
|
import cy.agorise.graphenej.api.calls.GetBlock;
|
||||||
import cy.agorise.graphenej.api.calls.GetLimitOrders;
|
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.api.calls.ListAssets;
|
||||||
import cy.agorise.graphenej.models.JsonRpcResponse;
|
import cy.agorise.graphenej.models.JsonRpcResponse;
|
||||||
import cy.agorise.graphenej.objects.Memo;
|
import cy.agorise.graphenej.objects.Memo;
|
||||||
import cy.agorise.graphenej.operations.TransferOperation;
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.functions.Consumer;
|
import io.reactivex.functions.Consumer;
|
||||||
|
@ -83,7 +84,6 @@ public class PerformCallActivity extends ConnectedActivity {
|
||||||
|
|
||||||
private Gson gson = new GsonBuilder()
|
private Gson gson = new GsonBuilder()
|
||||||
.setExclusionStrategies(new DeserializationMap.SkipAccountOptionsStrategy(), new DeserializationMap.SkipAssetOptionsStrategy())
|
.setExclusionStrategies(new DeserializationMap.SkipAccountOptionsStrategy(), new DeserializationMap.SkipAssetOptionsStrategy())
|
||||||
.registerTypeAdapter(TransferOperation.class, new TransferOperation.TransferDeserializer())
|
|
||||||
.registerTypeAdapter(Memo.class, new Memo.MemoSerializer())
|
.registerTypeAdapter(Memo.class, new Memo.MemoSerializer())
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
|
@ -125,6 +125,9 @@ public class PerformCallActivity extends ConnectedActivity {
|
||||||
case RPC.CALL_GET_ACCOUNT_BY_NAME:
|
case RPC.CALL_GET_ACCOUNT_BY_NAME:
|
||||||
setupAccountByName();
|
setupAccountByName();
|
||||||
break;
|
break;
|
||||||
|
case RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS:
|
||||||
|
setupGetAccountHistoryByOperations();
|
||||||
|
break;
|
||||||
case RPC.CALL_GET_LIMIT_ORDERS:
|
case RPC.CALL_GET_LIMIT_ORDERS:
|
||||||
setupGetLimitOrders();
|
setupGetLimitOrders();
|
||||||
default:
|
default:
|
||||||
|
@ -210,6 +213,21 @@ public class PerformCallActivity extends ConnectedActivity {
|
||||||
param1.setInputType(InputType.TYPE_CLASS_TEXT);
|
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(){
|
private void setupGetLimitOrders(){
|
||||||
requiredInput(3);
|
requiredInput(3);
|
||||||
Resources resources = getResources();
|
Resources resources = getResources();
|
||||||
|
@ -274,6 +292,10 @@ public class PerformCallActivity extends ConnectedActivity {
|
||||||
break;
|
break;
|
||||||
case RPC.CALL_GET_LIMIT_ORDERS:
|
case RPC.CALL_GET_LIMIT_ORDERS:
|
||||||
getLimitOrders();
|
getLimitOrders();
|
||||||
|
break;
|
||||||
|
case RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS:
|
||||||
|
getAccountHistoryByOperations();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Log.d(TAG,"Default called");
|
Log.d(TAG,"Default called");
|
||||||
}
|
}
|
||||||
|
@ -334,6 +356,20 @@ public class PerformCallActivity extends ConnectedActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void getAccountHistoryByOperations(){
|
||||||
|
try{
|
||||||
|
String account = param1.getText().toString();
|
||||||
|
ArrayList<OperationType> 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
|
* 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);
|
String request = responseMap.get(id);
|
||||||
switch(request){
|
switch(request){
|
||||||
case RPC.CALL_GET_ACCOUNTS:
|
case RPC.CALL_GET_ACCOUNTS:
|
||||||
mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n");
|
|
||||||
break;
|
|
||||||
case RPC.CALL_GET_BLOCK:
|
case RPC.CALL_GET_BLOCK:
|
||||||
mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n");
|
|
||||||
break;
|
|
||||||
case RPC.CALL_GET_BLOCK_HEADER:
|
case RPC.CALL_GET_BLOCK_HEADER:
|
||||||
mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n");
|
|
||||||
break;
|
|
||||||
case RPC.CALL_GET_MARKET_HISTORY:
|
case RPC.CALL_GET_MARKET_HISTORY:
|
||||||
mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n");
|
|
||||||
break;
|
|
||||||
case RPC.CALL_GET_ACCOUNT_HISTORY:
|
case RPC.CALL_GET_ACCOUNT_HISTORY:
|
||||||
mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n");
|
|
||||||
break;
|
|
||||||
case RPC.CALL_GET_RELATIVE_ACCOUNT_HISTORY:
|
case RPC.CALL_GET_RELATIVE_ACCOUNT_HISTORY:
|
||||||
mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n");
|
|
||||||
break;
|
|
||||||
case RPC.CALL_GET_REQUIRED_FEES:
|
case RPC.CALL_GET_REQUIRED_FEES:
|
||||||
mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n");
|
|
||||||
break;
|
|
||||||
case RPC.CALL_LOOKUP_ASSET_SYMBOLS:
|
case RPC.CALL_LOOKUP_ASSET_SYMBOLS:
|
||||||
mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n");
|
|
||||||
break;
|
|
||||||
case RPC.CALL_LIST_ASSETS:
|
case RPC.CALL_LIST_ASSETS:
|
||||||
mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n");
|
|
||||||
break;
|
|
||||||
case RPC.CALL_GET_ACCOUNT_BY_NAME:
|
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_LIMIT_ORDERS:
|
||||||
|
case RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS:
|
||||||
mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n");
|
mResponseView.setText(mResponseView.getText() + gson.toJson(response, JsonRpcResponse.class) + "\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -41,6 +41,12 @@
|
||||||
<!-- Get account by name fields -->
|
<!-- Get account by name fields -->
|
||||||
<string name="get_accounts_by_name_arg1">Account name</string>
|
<string name="get_accounts_by_name_arg1">Account name</string>
|
||||||
|
|
||||||
|
<!-- GetAccountHistoryByOperations input fields -->
|
||||||
|
<string name="get_account_history_by_operations_arg1">Account id or name</string>
|
||||||
|
<string name="get_account_history_by_operations_arg2">Operaton type (only transfer type is supported)</string>
|
||||||
|
<string name="get_account_history_by_operations_arg3">Start sequence number</string>
|
||||||
|
<string name="get_account_history_by_operations_arg4">Limit</string>
|
||||||
|
|
||||||
<!-- GetLimitOrders input fields -->
|
<!-- GetLimitOrders input fields -->
|
||||||
<string name="get_limit_orders_arg1">Asset A</string>
|
<string name="get_limit_orders_arg1">Asset A</string>
|
||||||
<string name="get_limit_orders_arg2">Asset B</string>
|
<string name="get_limit_orders_arg2">Asset B</string>
|
||||||
|
|
Loading…
Reference in a new issue