Progress #166: Initial implementation of get_full_accounts API call
This commit is contained in:
parent
dc8849f23b
commit
723b11533b
5 changed files with 124 additions and 22 deletions
|
|
@ -149,6 +149,87 @@ namespace graphene { namespace app {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<std::string, fc::variant> database_api::get_full_accounts(std::function<void(const variant&)> callback,
|
||||||
|
const vector<std::string>& names_or_ids)
|
||||||
|
{
|
||||||
|
std::map<std::string, fc::variant> results;
|
||||||
|
std::set<object_id_type> ids_to_subscribe;
|
||||||
|
|
||||||
|
for (const std::string& account_name_or_id : names_or_ids)
|
||||||
|
{
|
||||||
|
const account_object* account = nullptr;
|
||||||
|
if (std::isdigit(account_name_or_id[0]))
|
||||||
|
account = _db.find(fc::variant(account_name_or_id).as<account_id_type>());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto& idx = _db.get_index_type<account_index>().indices().get<by_name>();
|
||||||
|
auto itr = idx.find(account_name_or_id);
|
||||||
|
if (itr != idx.end())
|
||||||
|
account = &*itr;
|
||||||
|
}
|
||||||
|
if (account == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ids_to_subscribe.insert({account->id, account->statistics});
|
||||||
|
|
||||||
|
fc::mutable_variant_object full_account;
|
||||||
|
|
||||||
|
// Add the account itself, its statistics object, cashback balance, and referral account names
|
||||||
|
full_account("account", *account)("statistics", account->statistics(_db))
|
||||||
|
("registrar_name", account->registrar(_db).name)("referrer_name", account->referrer(_db).name)
|
||||||
|
("lifetime_referrer_name", account->lifetime_referrer(_db).name);
|
||||||
|
if (account->cashback_vb)
|
||||||
|
{
|
||||||
|
ids_to_subscribe.insert(*account->cashback_vb);
|
||||||
|
full_account("cashback_balance", account->cashback_balance(_db));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the account's balances
|
||||||
|
auto balance_range = _db.get_index_type<account_balance_index>().indices().get<by_account>().equal_range(account->id);
|
||||||
|
vector<account_balance_object> balances;
|
||||||
|
std::for_each(balance_range.first, balance_range.second,
|
||||||
|
[&balances, &ids_to_subscribe](const account_balance_object& balance) {
|
||||||
|
balances.emplace_back(balance);
|
||||||
|
ids_to_subscribe.insert(balance.id);
|
||||||
|
});
|
||||||
|
idump((balances));
|
||||||
|
full_account("balances", balances);
|
||||||
|
|
||||||
|
// Add the account's vesting balances
|
||||||
|
auto vesting_range = _db.get_index_type<vesting_balance_index>().indices().get<by_account>().equal_range(account->id);
|
||||||
|
vector<vesting_balance_object> vesting_balances;
|
||||||
|
std::for_each(vesting_range.first, vesting_range.second,
|
||||||
|
[&vesting_balances, &ids_to_subscribe](const vesting_balance_object& balance) {
|
||||||
|
vesting_balances.emplace_back(balance);
|
||||||
|
ids_to_subscribe.insert(balance.id);
|
||||||
|
});
|
||||||
|
full_account("vesting_balances", vesting_balances);
|
||||||
|
|
||||||
|
// Add the account's orders
|
||||||
|
auto order_range = _db.get_index_type<limit_order_index>().indices().get<by_account>().equal_range(account->id);
|
||||||
|
vector<limit_order_object> orders;
|
||||||
|
std::for_each(order_range.first, order_range.second,
|
||||||
|
[&orders, &ids_to_subscribe] (const limit_order_object& order) {
|
||||||
|
orders.emplace_back(order);
|
||||||
|
ids_to_subscribe.insert(order.id);
|
||||||
|
});
|
||||||
|
auto call_range = _db.get_index_type<call_order_index>().indices().get<by_account>().equal_range(account->id);
|
||||||
|
vector<call_order_object> calls;
|
||||||
|
std::for_each(call_range.first, call_range.second,
|
||||||
|
[&calls, &ids_to_subscribe] (const call_order_object& call) {
|
||||||
|
calls.emplace_back(call);
|
||||||
|
ids_to_subscribe.insert(call.id);
|
||||||
|
});
|
||||||
|
full_account("limit_orders", orders)("call_orders", calls);
|
||||||
|
|
||||||
|
results[account_name_or_id] = full_account;
|
||||||
|
}
|
||||||
|
|
||||||
|
wdump((results));
|
||||||
|
subscribe_to_objects(callback, vector<object_id_type>(ids_to_subscribe.begin(), ids_to_subscribe.end()));
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
vector<asset> database_api::get_account_balances(account_id_type acnt, const flat_set<asset_id_type>& assets)const
|
vector<asset> database_api::get_account_balances(account_id_type acnt, const flat_set<asset_id_type>& assets)const
|
||||||
{
|
{
|
||||||
vector<asset> result;
|
vector<asset> result;
|
||||||
|
|
@ -278,12 +359,12 @@ namespace graphene { namespace app {
|
||||||
// we want to order witnesses by account name, but that name is in the account object
|
// we want to order witnesses by account name, but that name is in the account object
|
||||||
// so the witness_index doesn't have a quick way to access it.
|
// so the witness_index doesn't have a quick way to access it.
|
||||||
// get all the names and look them all up, sort them, then figure out what
|
// get all the names and look them all up, sort them, then figure out what
|
||||||
// records to return. This could be optimized, but we expect the
|
// records to return. This could be optimized, but we expect the
|
||||||
// number of witnesses to be few and the frequency of calls to be rare
|
// number of witnesses to be few and the frequency of calls to be rare
|
||||||
std::map<std::string, witness_id_type> witnesses_by_account_name;
|
std::map<std::string, witness_id_type> witnesses_by_account_name;
|
||||||
for (const witness_object& witness : witnesses_by_id)
|
for (const witness_object& witness : witnesses_by_id)
|
||||||
if (auto account_iter = _db.find(witness.witness_account))
|
if (auto account_iter = _db.find(witness.witness_account))
|
||||||
if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name
|
if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name
|
||||||
witnesses_by_account_name.insert(std::make_pair(account_iter->name, witness.id));
|
witnesses_by_account_name.insert(std::make_pair(account_iter->name, witness.id));
|
||||||
|
|
||||||
auto end_iter = witnesses_by_account_name.begin();
|
auto end_iter = witnesses_by_account_name.begin();
|
||||||
|
|
@ -292,7 +373,7 @@ namespace graphene { namespace app {
|
||||||
witnesses_by_account_name.erase(end_iter, witnesses_by_account_name.end());
|
witnesses_by_account_name.erase(end_iter, witnesses_by_account_name.end());
|
||||||
return witnesses_by_account_name;
|
return witnesses_by_account_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
map<string, committee_member_id_type> database_api::lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const
|
map<string, committee_member_id_type> database_api::lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const
|
||||||
{
|
{
|
||||||
FC_ASSERT( limit <= 1000 );
|
FC_ASSERT( limit <= 1000 );
|
||||||
|
|
@ -301,12 +382,12 @@ namespace graphene { namespace app {
|
||||||
// we want to order committee_members by account name, but that name is in the account object
|
// we want to order committee_members by account name, but that name is in the account object
|
||||||
// so the committee_member_index doesn't have a quick way to access it.
|
// so the committee_member_index doesn't have a quick way to access it.
|
||||||
// get all the names and look them all up, sort them, then figure out what
|
// get all the names and look them all up, sort them, then figure out what
|
||||||
// records to return. This could be optimized, but we expect the
|
// records to return. This could be optimized, but we expect the
|
||||||
// number of committee_members to be few and the frequency of calls to be rare
|
// number of committee_members to be few and the frequency of calls to be rare
|
||||||
std::map<std::string, committee_member_id_type> committee_members_by_account_name;
|
std::map<std::string, committee_member_id_type> committee_members_by_account_name;
|
||||||
for (const committee_member_object& committee_member : committee_members_by_id)
|
for (const committee_member_object& committee_member : committee_members_by_id)
|
||||||
if (auto account_iter = _db.find(committee_member.committee_member_account))
|
if (auto account_iter = _db.find(committee_member.committee_member_account))
|
||||||
if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name
|
if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name
|
||||||
committee_members_by_account_name.insert(std::make_pair(account_iter->name, committee_member.id));
|
committee_members_by_account_name.insert(std::make_pair(account_iter->name, committee_member.id));
|
||||||
|
|
||||||
auto end_iter = committee_members_by_account_name.begin();
|
auto end_iter = committee_members_by_account_name.begin();
|
||||||
|
|
@ -315,7 +396,7 @@ namespace graphene { namespace app {
|
||||||
committee_members_by_account_name.erase(end_iter, committee_members_by_account_name.end());
|
committee_members_by_account_name.erase(end_iter, committee_members_by_account_name.end());
|
||||||
return committee_members_by_account_name;
|
return committee_members_by_account_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<optional<witness_object>> database_api::get_witnesses(const vector<witness_id_type>& witness_ids)const
|
vector<optional<witness_object>> database_api::get_witnesses(const vector<witness_id_type>& witness_ids)const
|
||||||
{
|
{
|
||||||
vector<optional<witness_object>> result; result.reserve(witness_ids.size());
|
vector<optional<witness_object>> result; result.reserve(witness_ids.size());
|
||||||
|
|
@ -605,7 +686,7 @@ namespace graphene { namespace app {
|
||||||
return hist->tracked_buckets();
|
return hist->tracked_buckets();
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<bucket_object> history_api::get_market_history( asset_id_type a, asset_id_type b,
|
vector<bucket_object> history_api::get_market_history( asset_id_type a, asset_id_type b,
|
||||||
uint32_t bucket_seconds, fc::time_point_sec start, fc::time_point_sec end )const
|
uint32_t bucket_seconds, fc::time_point_sec start, fc::time_point_sec end )const
|
||||||
{ try {
|
{ try {
|
||||||
FC_ASSERT(_app.chain_database());
|
FC_ASSERT(_app.chain_database());
|
||||||
|
|
|
||||||
|
|
@ -57,29 +57,29 @@ namespace graphene { namespace app {
|
||||||
*
|
*
|
||||||
* If any of the provided IDs does not map to an object, a null variant is returned in its position.
|
* If any of the provided IDs does not map to an object, a null variant is returned in its position.
|
||||||
*/
|
*/
|
||||||
fc::variants get_objects(const vector<object_id_type>& ids)const;
|
fc::variants get_objects(const vector<object_id_type>& ids)const;
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve a block header
|
* @brief Retrieve a block header
|
||||||
* @param block_num Height of the block whose header should be returned
|
* @param block_num Height of the block whose header should be returned
|
||||||
* @return header of the referenced block, or null if no matching block was found
|
* @return header of the referenced block, or null if no matching block was found
|
||||||
*/
|
*/
|
||||||
optional<block_header> get_block_header(uint32_t block_num)const;
|
optional<block_header> get_block_header(uint32_t block_num)const;
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve a full, signed block
|
* @brief Retrieve a full, signed block
|
||||||
* @param block_num Height of the block to be returned
|
* @param block_num Height of the block to be returned
|
||||||
* @return the referenced block, or null if no matching block was found
|
* @return the referenced block, or null if no matching block was found
|
||||||
*/
|
*/
|
||||||
optional<signed_block> get_block(uint32_t block_num)const;
|
optional<signed_block> get_block(uint32_t block_num)const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief used to fetch an individual transaction.
|
* @brief used to fetch an individual transaction.
|
||||||
*/
|
*/
|
||||||
processed_transaction get_transaction( uint32_t block_num, uint32_t trx_in_block )const;
|
processed_transaction get_transaction( uint32_t block_num, uint32_t trx_in_block )const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve the current @ref global_property_object
|
* @brief Retrieve the current @ref global_property_object
|
||||||
*/
|
*/
|
||||||
global_property_object get_global_properties()const;
|
global_property_object get_global_properties()const;
|
||||||
/**
|
/**
|
||||||
* @brief Retrieve the current @ref dynamic_global_property_object
|
* @brief Retrieve the current @ref dynamic_global_property_object
|
||||||
*/
|
*/
|
||||||
|
|
@ -138,6 +138,21 @@ namespace graphene { namespace app {
|
||||||
*/
|
*/
|
||||||
map<string,account_id_type> lookup_accounts(const string& lower_bound_name, uint32_t limit)const;
|
map<string,account_id_type> lookup_accounts(const string& lower_bound_name, uint32_t limit)const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Fetch all objects relevant to the specified accounts and subscribe to updates
|
||||||
|
* @param callback Function to call with updates
|
||||||
|
* @param names_or_ids Each item must be the name or ID of an account to retrieve
|
||||||
|
* @return Map of string from @ref names_or_ids to the corresponding account
|
||||||
|
*
|
||||||
|
* This function fetches all relevant objects for the given accounts, and subscribes to updates to the given
|
||||||
|
* accounts. If any of the strings in @ref names_or_ids cannot be tied to an account, that input will be
|
||||||
|
* ignored. All other accounts will be retrieved and subscribed.
|
||||||
|
*
|
||||||
|
* TODO: Describe the return value and argument to callback in detail
|
||||||
|
*/
|
||||||
|
std::map<string,fc::variant> get_full_accounts(std::function<void(const variant&)> callback,
|
||||||
|
const vector<string>& names_or_ids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get limit orders in a given market
|
* @brief Get limit orders in a given market
|
||||||
* @param a ID of asset being sold
|
* @param a ID of asset being sold
|
||||||
|
|
@ -324,9 +339,9 @@ namespace graphene { namespace app {
|
||||||
|
|
||||||
vector<bucket_object> get_market_history( asset_id_type a, asset_id_type b, uint32_t bucket_seconds,
|
vector<bucket_object> get_market_history( asset_id_type a, asset_id_type b, uint32_t bucket_seconds,
|
||||||
fc::time_point_sec start, fc::time_point_sec end )const;
|
fc::time_point_sec start, fc::time_point_sec end )const;
|
||||||
flat_set<uint32_t> get_market_history_buckets()const;
|
flat_set<uint32_t> get_market_history_buckets()const;
|
||||||
private:
|
private:
|
||||||
application& _app;
|
application& _app;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -403,7 +418,7 @@ namespace graphene { namespace app {
|
||||||
std::vector<net::peer_status> get_connected_peers() const;
|
std::vector<net::peer_status> get_connected_peers() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
application& _app;
|
application& _app;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -440,7 +455,7 @@ namespace graphene { namespace app {
|
||||||
/// @brief Called to enable an API, not reflected.
|
/// @brief Called to enable an API, not reflected.
|
||||||
void enable_api( const string& api_name );
|
void enable_api( const string& api_name );
|
||||||
|
|
||||||
application& _app;
|
application& _app;
|
||||||
optional< fc::api<database_api> > _database_api;
|
optional< fc::api<database_api> > _database_api;
|
||||||
optional< fc::api<network_broadcast_api> > _network_broadcast_api;
|
optional< fc::api<network_broadcast_api> > _network_broadcast_api;
|
||||||
optional< fc::api<network_node_api> > _network_node_api;
|
optional< fc::api<network_node_api> > _network_node_api;
|
||||||
|
|
@ -464,6 +479,7 @@ FC_API(graphene::app::database_api,
|
||||||
(lookup_account_names)
|
(lookup_account_names)
|
||||||
(get_account_count)
|
(get_account_count)
|
||||||
(lookup_accounts)
|
(lookup_accounts)
|
||||||
|
(get_full_accounts)
|
||||||
(get_account_balances)
|
(get_account_balances)
|
||||||
(get_named_account_balances)
|
(get_named_account_balances)
|
||||||
(lookup_asset_symbols)
|
(lookup_asset_symbols)
|
||||||
|
|
|
||||||
|
|
@ -174,8 +174,7 @@ void database::initialize_indexes()
|
||||||
prop_index->add_secondary_index<required_approval_index>();
|
prop_index->add_secondary_index<required_approval_index>();
|
||||||
|
|
||||||
add_index< primary_index<withdraw_permission_index > >();
|
add_index< primary_index<withdraw_permission_index > >();
|
||||||
//add_index< primary_index<vesting_balance_index> >();
|
add_index< primary_index<vesting_balance_index> >();
|
||||||
add_index< primary_index<simple_index<vesting_balance_object>> >();
|
|
||||||
add_index< primary_index<worker_index> >();
|
add_index< primary_index<worker_index> >();
|
||||||
add_index< primary_index<balance_index> >();
|
add_index< primary_index<balance_index> >();
|
||||||
|
|
||||||
|
|
@ -214,7 +213,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
||||||
|
|
||||||
transaction_evaluation_state genesis_eval_state(this);
|
transaction_evaluation_state genesis_eval_state(this);
|
||||||
|
|
||||||
flat_index<block_summary_object>& bsi = get_mutable_index_type< flat_index<block_summary_object> >();
|
flat_index<block_summary_object>& bsi = get_mutable_index_type< flat_index<block_summary_object> >();
|
||||||
bsi.resize(0xffff+1);
|
bsi.resize(0xffff+1);
|
||||||
|
|
||||||
// Create blockchain accounts
|
// Create blockchain accounts
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ namespace graphene { namespace chain {
|
||||||
struct by_id;
|
struct by_id;
|
||||||
struct by_price;
|
struct by_price;
|
||||||
struct by_expiration;
|
struct by_expiration;
|
||||||
|
struct by_account;
|
||||||
typedef multi_index_container<
|
typedef multi_index_container<
|
||||||
limit_order_object,
|
limit_order_object,
|
||||||
indexed_by<
|
indexed_by<
|
||||||
|
|
@ -46,7 +47,8 @@ namespace graphene { namespace chain {
|
||||||
member< object, object_id_type, &object::id>
|
member< object, object_id_type, &object::id>
|
||||||
>,
|
>,
|
||||||
composite_key_compare< std::greater<price>, std::less<object_id_type> >
|
composite_key_compare< std::greater<price>, std::less<object_id_type> >
|
||||||
>
|
>,
|
||||||
|
ordered_non_unique< tag<by_account>, member<limit_order_object, account_id_type, &limit_order_object::seller>>
|
||||||
>
|
>
|
||||||
> limit_order_multi_index_type;
|
> limit_order_multi_index_type;
|
||||||
|
|
||||||
|
|
@ -74,7 +76,7 @@ namespace graphene { namespace chain {
|
||||||
account_id_type borrower;
|
account_id_type borrower;
|
||||||
share_type collateral; ///< call_price.base.asset_id, access via get_collateral
|
share_type collateral; ///< call_price.base.asset_id, access via get_collateral
|
||||||
share_type debt; ///< call_price.quote.asset_id, access via get_collateral
|
share_type debt; ///< call_price.quote.asset_id, access via get_collateral
|
||||||
price call_price; ///< Debt / Collateral
|
price call_price; ///< Debt / Collateral
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -159,10 +159,14 @@ namespace graphene { namespace chain {
|
||||||
/**
|
/**
|
||||||
* @ingroup object_index
|
* @ingroup object_index
|
||||||
*/
|
*/
|
||||||
|
struct by_account;
|
||||||
typedef multi_index_container<
|
typedef multi_index_container<
|
||||||
vesting_balance_object,
|
vesting_balance_object,
|
||||||
indexed_by<
|
indexed_by<
|
||||||
hashed_unique< tag<by_id>, member< object, object_id_type, &object::id > >
|
hashed_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||||
|
ordered_non_unique< tag<by_account>,
|
||||||
|
member<vesting_balance_object, account_id_type, &vesting_balance_object::owner>
|
||||||
|
>
|
||||||
>
|
>
|
||||||
> vesting_balance_multi_index_type;
|
> vesting_balance_multi_index_type;
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue