diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 5c69fcef..85398589 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -95,6 +95,10 @@ namespace graphene { namespace app { { _crypto_api = std::make_shared< crypto_api >(); } + else if( api_name == "asset_api" ) + { + _asset_api = std::make_shared< asset_api >( std::ref( *_app.chain_database() ) ); + } else if( api_name == "debug_api" ) { // can only enable this API if the plugin was loaded @@ -217,6 +221,12 @@ namespace graphene { namespace app { return *_crypto_api; } + fc::api login_api::asset() const + { + FC_ASSERT(_asset_api); + return *_asset_api; + } + fc::api login_api::debug() const { FC_ASSERT(_debug_api); @@ -550,4 +560,32 @@ namespace graphene { namespace app { return fc::ecc::range_get_info( proof ); } + // asset_api + asset_api::asset_api(graphene::chain::database& db) : _db(db) { } + asset_api::~asset_api() { } + + vector asset_api::get_asset_holders( asset_id_type asset_id ) const { + + const auto& bal_idx = _db.get_index_type< account_balance_index >().indices().get< by_asset_balance >(); + auto range = bal_idx.equal_range( boost::make_tuple( asset_id ) ); + + vector result; + + for( const account_balance_object& bal : boost::make_iterator_range( range.first, range.second ) ) + { + if( bal.balance.value == 0 ) continue; + + auto account = _db.find(bal.owner); + + account_asset_balance aab; + aab.name = account->name; + aab.account_id = account->id; + aab.amount = bal.balance.value; + + result.push_back(aab); + } + + return result; + } + } } // graphene::app diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index 1c2c52ba..5ebaa36e 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -71,6 +71,13 @@ namespace graphene { namespace app { string message_out; }; + struct account_asset_balance + { + string name; + account_id_type account_id; + share_type amount; + }; + /** * @brief The history_api class implements the RPC API for account history * @@ -252,6 +259,21 @@ namespace graphene { namespace app { range_proof_info range_get_info( const std::vector& proof ); }; + /** + * @brief + */ + class asset_api + { + public: + asset_api(graphene::chain::database& db); + ~asset_api(); + + vector get_asset_holders( asset_id_type asset_id )const; + + private: + graphene::chain::database& _db; + }; + /** * @brief The login_api class implements the bottom layer of the RPC API * @@ -283,6 +305,8 @@ namespace graphene { namespace app { fc::api network_node()const; /// @brief Retrieve the cryptography API fc::api crypto()const; + /// @brief Retrieve the asset API + fc::api asset()const; /// @brief Retrieve the debug API (if available) fc::api debug()const; @@ -296,6 +320,7 @@ namespace graphene { namespace app { optional< fc::api > _network_node_api; optional< fc::api > _history_api; optional< fc::api > _crypto_api; + optional< fc::api > _asset_api; optional< fc::api > _debug_api; }; @@ -310,6 +335,8 @@ FC_REFLECT( graphene::app::verify_range_proof_rewind_result, //FC_REFLECT_TYPENAME( fc::ecc::compact_signature ); //FC_REFLECT_TYPENAME( fc::ecc::commitment_type ); +FC_REFLECT( graphene::app::account_asset_balance, (name)(account_id)(amount) ); + FC_API(graphene::app::history_api, (get_account_history) (get_relative_account_history) @@ -341,6 +368,9 @@ FC_API(graphene::app::crypto_api, (verify_range_proof_rewind) (range_get_info) ) +FC_API(graphene::app::asset_api, + (get_asset_holders) + ) FC_API(graphene::app::login_api, (login) (network_broadcast) @@ -348,5 +378,6 @@ FC_API(graphene::app::login_api, (history) (network_node) (crypto) + (asset) (debug) )