Added support for the 'get_full_accounts' API call in the single connecton mode

This commit is contained in:
Nelson R. Perez 2018-09-06 18:09:18 -05:00
parent 7d5cfbf14b
commit 6abd71252e
9 changed files with 183 additions and 1 deletions

View file

@ -14,6 +14,7 @@ public class RPC {
public static final String CALL_CANCEL_ALL_SUBSCRIPTIONS = "cancel_all_subscriptions";
public static final String CALL_GET_ACCOUNT_BY_NAME = "get_account_by_name";
public static final String CALL_GET_ACCOUNTS = "get_accounts";
public static final String CALL_GET_FULL_ACCOUNTS = "get_full_accounts";
public static final String CALL_GET_DYNAMIC_GLOBAL_PROPERTIES = "get_dynamic_global_properties";
public static final String CALL_BROADCAST_TRANSACTION = "broadcast_transaction";
public static final String CALL_GET_REQUIRED_FEES = "get_required_fees";

View file

@ -23,6 +23,7 @@ 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;
import cy.agorise.graphenej.api.calls.GetFullAccounts;
import cy.agorise.graphenej.api.calls.GetLimitOrders;
import cy.agorise.graphenej.api.calls.GetMarketHistory;
import cy.agorise.graphenej.api.calls.GetObjects;
@ -34,6 +35,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.FullAccountDetails;
import cy.agorise.graphenej.models.HistoryOperationDetail;
import cy.agorise.graphenej.models.OperationHistory;
import cy.agorise.graphenej.objects.Memo;
@ -156,6 +158,16 @@ public class DeserializationMap {
.registerTypeAdapter(AssetAmount.class, new AssetAmount.AssetAmountDeserializer())
.create();
mGsonMap.put(GetAccountHistoryByOperations.class, getAccountHistoryByOperationsGson);
// GetFullAccounts
mClassMap.put(GetFullAccounts.class, FullAccountDetails.class);
Gson getFullAccountsGson = new GsonBuilder()
.registerTypeAdapter(FullAccountDetails.class, new FullAccountDetails.FullAccountDeserializer())
.registerTypeAdapter(Authority.class, new Authority.AuthorityDeserializer())
.registerTypeAdapter(Memo.class, new Memo.MemoDeserializer())
.registerTypeAdapter(AccountOptions.class, new AccountOptions.AccountOptionsDeserializer())
.create();
mGsonMap.put(GetFullAccounts.class, getFullAccountsGson);
}
public Class getReceivedClass(Class _class){

View file

@ -30,6 +30,7 @@ import cy.agorise.graphenej.api.ConnectionStatusUpdate;
import cy.agorise.graphenej.api.bitshares.Nodes;
import cy.agorise.graphenej.api.calls.ApiCallable;
import cy.agorise.graphenej.api.calls.GetAccounts;
import cy.agorise.graphenej.api.calls.GetFullAccounts;
import cy.agorise.graphenej.api.calls.GetLimitOrders;
import cy.agorise.graphenej.api.calls.GetMarketHistory;
import cy.agorise.graphenej.api.calls.GetObjects;
@ -42,6 +43,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.FullAccountDetails;
import cy.agorise.graphenej.models.HistoryOperationDetail;
import cy.agorise.graphenej.models.JsonRpcNotification;
import cy.agorise.graphenej.models.JsonRpcResponse;
@ -390,7 +392,10 @@ public class NetworkService extends Service {
}else if(requestClass == GetLimitOrders.class){
Type GetLimitOrdersResponse = new TypeToken<JsonRpcResponse<List<LimitOrder>>>() {}.getType();
parsedResponse = gson.fromJson(text, GetLimitOrdersResponse);
}else{
} else if (requestClass == GetFullAccounts.class) {
Type GetFullAccountsResponse = new TypeToken<JsonRpcResponse<List<FullAccountDetails>>>(){}.getType();
parsedResponse = gson.fromJson(text, GetFullAccountsResponse);
} else {
Log.w(TAG,"Unknown request class");
}
}else{

View file

@ -0,0 +1,34 @@
package cy.agorise.graphenej.api.calls;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import cy.agorise.graphenej.RPC;
import cy.agorise.graphenej.api.ApiAccess;
import cy.agorise.graphenej.models.ApiCall;
/**
* Wrapper around the 'get_full_accounts' API call.
*/
public class GetFullAccounts implements ApiCallable {
public static final int REQUIRED_API = ApiAccess.API_NONE;
private List<String> mUserAccounts;
private boolean mSubscribe;
public GetFullAccounts(List<String> accounts, boolean subscribe){
this.mUserAccounts = accounts;
this.mSubscribe = subscribe;
}
@Override
public ApiCall toApiCall(int apiId, long sequenceId) {
ArrayList<Serializable> params = new ArrayList<>();
ArrayList<Serializable> accounts = new ArrayList<Serializable>(mUserAccounts);
params.add(accounts);
params.add(mSubscribe);
return new ApiCall(apiId, RPC.CALL_GET_FULL_ACCOUNTS, params, RPC.VERSION, sequenceId);
}
}

View file

@ -0,0 +1,68 @@
package cy.agorise.graphenej.models;
import com.google.gson.JsonArray;
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.lang.reflect.Type;
/**
* Model class used in the de-serialization of the response to the 'get_full_accounts' API call.
* @see cy.agorise.graphenej.api.calls.GetFullAccounts
*/
public class FullAccountDetails {
private AccountProperties account;
private Statistics statistics;
public FullAccountDetails(AccountProperties properties, Statistics statistics){
this.account = properties;
this.statistics = statistics;
}
public AccountProperties getAccount() {
return account;
}
public void setAccount(AccountProperties account) {
this.account = account;
}
public Statistics getStatistics() {
return statistics;
}
public void setStatistics(Statistics statistics) {
this.statistics = statistics;
}
public static class Statistics {
public String id;
public String owner;
public String name;
public String most_recent_op;
public long total_ops;
public long removed_ops;
public long total_core_in_orders;
public String core_in_balance;
public boolean has_cashback_vb;
public boolean is_voting;
public long lifetime_fees_paid;
public long pending_fees;
public long pending_vested_fees;
}
public static class FullAccountDeserializer implements JsonDeserializer<FullAccountDetails> {
@Override
public FullAccountDetails deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonArray array = (JsonArray) json;
JsonObject jsonObject = (JsonObject) array.get(1);
AccountProperties properties = context.deserialize(jsonObject.get("account"), AccountProperties.class);
Statistics statistics = context.deserialize(jsonObject.get("statistics"), Statistics.class);
return new FullAccountDetails(properties, statistics);
}
}
}

View file

@ -0,0 +1,39 @@
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 java.util.List;
import cy.agorise.graphenej.AccountOptions;
import cy.agorise.graphenej.Authority;
import cy.agorise.graphenej.objects.Memo;
public class FullAccountDetailsTest {
@Test
public void testDeserialization(){
String serialized = "{\"id\":0,\"jsonrpc\":\"2.0\",\"result\":[[\"bilthon-1\",{\"account\":{\"id\":\"1.2.139205\",\"membership_expiration_date\":\"1970-01-01T00:00:00\",\"registrar\":\"1.2.117600\",\"referrer\":\"1.2.90200\",\"lifetime_referrer\":\"1.2.90200\",\"network_fee_percentage\":2000,\"lifetime_referrer_fee_percentage\":3000,\"referrer_rewards_percentage\":9000,\"name\":\"bilthon-1\",\"owner\":{\"weight_threshold\":1,\"account_auths\":[],\"key_auths\":[[\"BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY\",1]],\"address_auths\":[]},\"active\":{\"weight_threshold\":1,\"account_auths\":[],\"key_auths\":[[\"BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY\",1]],\"address_auths\":[]},\"options\":{\"memo_key\":\"BTS8RiFgs8HkcVPVobHLKEv6yL3iXcC9SWjbPVS15dDAXLG9GYhnY\",\"voting_account\":\"1.2.5\",\"num_witness\":0,\"num_committee\":0,\"votes\":[],\"extensions\":[]},\"statistics\":\"2.6.139205\",\"whitelisting_accounts\":[],\"blacklisting_accounts\":[],\"whitelisted_accounts\":[],\"blacklisted_accounts\":[],\"owner_special_authority\":[0,{}],\"active_special_authority\":[0,{}],\"top_n_control_flags\":0},\"statistics\":{\"id\":\"2.6.139205\",\"owner\":\"1.2.139205\",\"name\":\"bilthon-1\",\"most_recent_op\":\"2.9.6668024\",\"total_ops\":3,\"removed_ops\":0,\"total_core_in_orders\":0,\"core_in_balance\":71279,\"has_cashback_vb\":false,\"is_voting\":false,\"lifetime_fees_paid\":28721,\"pending_fees\":0,\"pending_vested_fees\":0},\"registrar_name\":\"bitshares-munich-faucet\",\"referrer_name\":\"bitshares-munich\",\"lifetime_referrer_name\":\"bitshares-munich\",\"votes\":[],\"balances\":[{\"id\":\"2.5.44951\",\"owner\":\"1.2.139205\",\"asset_type\":\"1.3.0\",\"balance\":71279,\"maintenance_flag\":false}],\"vesting_balances\":[],\"limit_orders\":[],\"call_orders\":[],\"settle_orders\":[],\"proposals\":[],\"assets\":[],\"withdraws\":[]}],[\"bilthon-2\",{\"account\":{\"id\":\"1.2.139207\",\"membership_expiration_date\":\"1970-01-01T00:00:00\",\"registrar\":\"1.2.117600\",\"referrer\":\"1.2.90200\",\"lifetime_referrer\":\"1.2.90200\",\"network_fee_percentage\":2000,\"lifetime_referrer_fee_percentage\":3000,\"referrer_rewards_percentage\":9000,\"name\":\"bilthon-2\",\"owner\":{\"weight_threshold\":1,\"account_auths\":[],\"key_auths\":[[\"BTS7gD2wtSauXpSCBin1rYctBcPWeZieX7YrVk1DuQpg9peczSqTv\",1]],\"address_auths\":[]},\"active\":{\"weight_threshold\":1,\"account_auths\":[],\"key_auths\":[[\"BTS7gD2wtSauXpSCBin1rYctBcPWeZieX7YrVk1DuQpg9peczSqTv\",1]],\"address_auths\":[]},\"options\":{\"memo_key\":\"BTS7gD2wtSauXpSCBin1rYctBcPWeZieX7YrVk1DuQpg9peczSqTv\",\"voting_account\":\"1.2.5\",\"num_witness\":0,\"num_committee\":0,\"votes\":[],\"extensions\":[]},\"statistics\":\"2.6.139207\",\"whitelisting_accounts\":[],\"blacklisting_accounts\":[],\"whitelisted_accounts\":[],\"blacklisted_accounts\":[],\"owner_special_authority\":[0,{}],\"active_special_authority\":[0,{}],\"top_n_control_flags\":0},\"statistics\":{\"id\":\"2.6.139207\",\"owner\":\"1.2.139207\",\"name\":\"bilthon-2\",\"most_recent_op\":\"2.9.6159244\",\"total_ops\":1,\"removed_ops\":0,\"total_core_in_orders\":0,\"core_in_balance\":0,\"has_cashback_vb\":false,\"is_voting\":false,\"lifetime_fees_paid\":0,\"pending_fees\":0,\"pending_vested_fees\":0},\"registrar_name\":\"bitshares-munich-faucet\",\"referrer_name\":\"bitshares-munich\",\"lifetime_referrer_name\":\"bitshares-munich\",\"votes\":[],\"balances\":[],\"vesting_balances\":[],\"limit_orders\":[],\"call_orders\":[],\"settle_orders\":[],\"proposals\":[],\"assets\":[],\"withdraws\":[]}]]}";
Gson gson = new GsonBuilder()
.registerTypeAdapter(FullAccountDetails.class, new FullAccountDetails.FullAccountDeserializer())
.registerTypeAdapter(Authority.class, new Authority.AuthorityDeserializer())
.registerTypeAdapter(Memo.class, new Memo.MemoDeserializer())
.registerTypeAdapter(AccountOptions.class, new AccountOptions.AccountOptionsDeserializer())
.create();
Type FullAccountDetailsResponse = new TypeToken<JsonRpcResponse<List<FullAccountDetails>>>() {}.getType();
JsonRpcResponse<List<FullAccountDetails>> response = gson.fromJson(serialized, FullAccountDetailsResponse);
Assert.assertNotNull(response.result);
Assert.assertNull(response.error);
List<FullAccountDetails> fullAccountDetailsList = response.result;
Assert.assertNotNull(fullAccountDetailsList);
Assert.assertEquals(2, fullAccountDetailsList.size());
Assert.assertNotNull(fullAccountDetailsList.get(0).getAccount());
Assert.assertEquals("bilthon-1", fullAccountDetailsList.get(0).getAccount().name);
}
}

View file

@ -48,6 +48,7 @@ public class CallsActivity extends AppCompatActivity {
RPC.CALL_GET_ACCOUNT_BY_NAME,
RPC.CALL_GET_LIMIT_ORDERS,
RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS,
RPC.CALL_GET_FULL_ACCOUNTS,
RPC.CALL_SET_SUBSCRIBE_CALLBACK
};

View file

@ -17,6 +17,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import butterknife.BindView;
@ -32,6 +33,7 @@ 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.GetFullAccounts;
import cy.agorise.graphenej.api.calls.GetLimitOrders;
import cy.agorise.graphenej.api.calls.GetObjects;
import cy.agorise.graphenej.api.calls.ListAssets;
@ -130,6 +132,9 @@ public class PerformCallActivity extends ConnectedActivity {
break;
case RPC.CALL_GET_LIMIT_ORDERS:
setupGetLimitOrders();
case RPC.CALL_GET_FULL_ACCOUNTS:
setupGetFullAccounts();
break;
default:
Log.d(TAG,"Default called");
}
@ -239,6 +244,12 @@ public class PerformCallActivity extends ConnectedActivity {
param3.setInputType(InputType.TYPE_CLASS_NUMBER);
}
private void setupGetFullAccounts(){
requiredInput(1);
mParam1View.setHint(getString(R.string.get_full_accounts_arg1));
param1.setInputType(InputType.TYPE_CLASS_TEXT);
}
private void requiredInput(int inputCount){
if(inputCount == 1){
mParam1View.setVisibility(View.VISIBLE);
@ -296,6 +307,8 @@ public class PerformCallActivity extends ConnectedActivity {
case RPC.CALL_GET_ACCOUNT_HISTORY_BY_OPERATIONS:
getAccountHistoryByOperations();
break;
case RPC.CALL_GET_FULL_ACCOUNTS:
getFullAccounts();
default:
Log.d(TAG,"Default called");
}
@ -370,6 +383,12 @@ public class PerformCallActivity extends ConnectedActivity {
}
}
private void getFullAccounts(){
ArrayList<String> accounts = new ArrayList<>();
accounts.addAll(Arrays.asList(param1.getText().toString().split(",")));
long id = mNetworkService.sendMessage(new GetFullAccounts(accounts, false), GetFullAccounts.REQUIRED_API);
}
/**
* Internal method that will decide what to do with each JSON-RPC response
*

View file

@ -51,4 +51,7 @@
<string name="get_limit_orders_arg1">Asset A</string>
<string name="get_limit_orders_arg2">Asset B</string>
<string name="get_limit_orders_arg3">Number of orders</string>
<!-- GetFullAccounts input fields -->
<string name="get_full_accounts_arg1">Account names or ids, separated by commas</string>
</resources>