diff --git a/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp b/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp index ef89c488..784c7e45 100644 --- a/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp +++ b/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp @@ -81,6 +81,17 @@ class account_history_plugin : public graphene::app::plugin std::unique_ptr my; }; +class affiliate_reward_index : public secondary_index +{ + public: + virtual void object_inserted( const object& obj ) override; + virtual void object_removed( const object& obj ) override; + virtual void about_to_modify( const object& before ) override{}; + virtual void object_modified( const object& after ) override{}; + + map > _history_by_account; +}; + } } //graphene::account_history /*struct by_id; diff --git a/libraries/plugins/affiliate_stats/affiliate_stats_api.cpp b/libraries/plugins/affiliate_stats/affiliate_stats_api.cpp index 5fcbe0d6..d37a0360 100644 --- a/libraries/plugins/affiliate_stats/affiliate_stats_api.cpp +++ b/libraries/plugins/affiliate_stats/affiliate_stats_api.cpp @@ -38,6 +38,8 @@ #include +#include + namespace graphene { namespace affiliate_stats { namespace detail { @@ -52,9 +54,9 @@ class affiliate_stats_api_impl std::vector result; result.reserve( limit ); auto& idx = app.chain_database()->get_index_type().indices().get(); - auto itr = idx.find( asset ); + auto itr = idx.lower_bound( boost::make_tuple( asset, share_type(GRAPHENE_MAX_SHARE_SUPPLY) ) ); while( itr != idx.end() && itr->get_asset_id() == asset && limit-- > 0 ) - result.push_back( *itr ); + result.push_back( *itr++ ); return result; } @@ -63,9 +65,22 @@ class affiliate_stats_api_impl std::vector result; result.reserve( limit ); auto& idx = app.chain_database()->get_index_type().indices().get(); - auto itr = idx.find( asset ); + auto itr = idx.lower_bound( boost::make_tuple( asset, share_type(GRAPHENE_MAX_SHARE_SUPPLY) ) ); while( itr != idx.end() && itr->get_asset_id() == asset && limit-- > 0 ) - result.push_back( *itr ); + result.push_back( *itr++ ); + return result; + } + + std::vector list_historic_referral_rewards( account_id_type affiliate, operation_history_id_type start, uint16_t limit )const + { + shared_ptr plugin = app.get_plugin( "affiliate_stats" ); + + std::vector result; + const auto& list = plugin->get_reward_history( affiliate ); + result.reserve( limit ); + auto inner = list.lower_bound( start ); + while( inner != list.end() && result.size() < limit ) + result.push_back( referral_payment( (*inner++)(*app.chain_database()) ) ); return result; } @@ -87,6 +102,7 @@ top_app::top_app() {} top_app::top_app( const app_reward_object& aro ) : app( aro.app ), total_payout( aro.total_payout ) {} + affiliate_stats_api::affiliate_stats_api(graphene::app::application& app) : my(std::make_shared(app)) {} @@ -102,11 +118,19 @@ std::vector affiliate_stats_api::list_top_rewards_per_app( asset_id_typ return my->list_top_rewards_per_app( asset, limit ); } -std::vector affiliate_stats_api::list_historic_referral_rewards( account_id_type affiliate )const +std::vector affiliate_stats_api::list_historic_referral_rewards( account_id_type affiliate, operation_history_id_type start, uint16_t limit )const { - FC_ASSERT( false, "Not implemented!" ); + FC_ASSERT( limit <= 100 ); + return my->list_historic_referral_rewards( affiliate, start, limit ); } + +referral_payment::referral_payment() {} + +referral_payment::referral_payment( const operation_history_object& oho ) + : id(oho.id), block_num(oho.block_num), tag(oho.op.get().tag), + payout(oho.op.get().payout) {} + } } // graphene::affiliate_stats diff --git a/libraries/plugins/affiliate_stats/affiliate_stats_plugin.cpp b/libraries/plugins/affiliate_stats/affiliate_stats_plugin.cpp index 3099b331..438b1aca 100644 --- a/libraries/plugins/affiliate_stats/affiliate_stats_plugin.cpp +++ b/libraries/plugins/affiliate_stats/affiliate_stats_plugin.cpp @@ -42,6 +42,19 @@ namespace graphene { namespace affiliate_stats { namespace detail { +class affiliate_reward_index : public graphene::db::index_observer +{ + public: + affiliate_reward_index( graphene::chain::database& _db ) : db(_db) {} + virtual void on_add( const graphene::db::object& obj ) override; + virtual void on_remove( const graphene::db::object& obj ) override; + virtual void on_modify( const graphene::db::object& before ) override{}; + + std::map > _history_by_account; + private: + graphene::chain::database& db; +}; + class affiliate_stats_plugin_impl { public: @@ -59,13 +72,16 @@ class affiliate_stats_plugin_impl return _self.database(); } + const std::set& get_reward_history( account_id_type& affiliate )const; + typedef void result_type; template void operator()( const Operation& op ) {} - affiliate_stats_plugin& _self; - app_reward_index* _ar_index; - referral_reward_index* _rr_index; + shared_ptr _fr_index; + affiliate_stats_plugin& _self; + app_reward_index* _ar_index; + referral_reward_index* _rr_index; private: }; @@ -123,9 +139,42 @@ void affiliate_stats_plugin_impl::update_affiliate_stats( const signed_block& b } } -} // end namespace detail +static const std::set EMPTY; +const std::set& affiliate_stats_plugin_impl::get_reward_history( account_id_type& affiliate )const +{ + auto itr = _fr_index->_history_by_account.find( affiliate ); + if( itr == _fr_index->_history_by_account.end() ) + return EMPTY; + return itr->second; +} +static optional> get_account( const database& db, const object& obj ) +{ + FC_ASSERT( dynamic_cast(&obj) ); + const account_transaction_history_object& ath = static_cast(obj); + const operation_history_object& oho = db.get( ath.operation_id ); + if( oho.op.which() == operation::tag::value ) + return std::make_pair( ath.account, ath.operation_id ); + return optional>(); +} + +void affiliate_reward_index::on_add( const object& obj ) +{ + optional> acct_ath = get_account( db, obj ); + if( !acct_ath.valid() ) return; + _history_by_account[acct_ath->first].insert( acct_ath->second ); +} + +void affiliate_reward_index::on_remove( const object& obj ) +{ + optional> acct_ath = get_account( db, obj ); + if( !acct_ath.valid() ) return; + _history_by_account[acct_ath->first].erase( acct_ath->second ); +} + +} // end namespace detail + affiliate_stats_plugin::affiliate_stats_plugin() : my( new detail::affiliate_stats_plugin_impl(*this) ) {} @@ -150,11 +199,17 @@ void affiliate_stats_plugin::plugin_initialize(const boost::program_options::var { database().applied_block.connect( [this]( const signed_block& b){ my->update_affiliate_stats(b); } ); - // my->_oho_index = database().add_index< primary_index< simple_index< operation_history_object > > >(); my->_ar_index = database().add_index< primary_index< app_reward_index > >(); my->_rr_index = database().add_index< primary_index< referral_reward_index > >(); + my->_fr_index = shared_ptr( new detail::affiliate_reward_index( database() ) ); + const_cast&>(database().get_index_type>()).add_observer( my->_fr_index ); } void affiliate_stats_plugin::plugin_startup() {} +const std::set& affiliate_stats_plugin::get_reward_history( account_id_type& affiliate )const +{ + return my->get_reward_history( affiliate ); +} + } } // graphene::affiliate_stats diff --git a/libraries/plugins/affiliate_stats/include/graphene/affiliate_stats/affiliate_stats_api.hpp b/libraries/plugins/affiliate_stats/include/graphene/affiliate_stats/affiliate_stats_api.hpp index d41e6d44..29c45d9f 100644 --- a/libraries/plugins/affiliate_stats/include/graphene/affiliate_stats/affiliate_stats_api.hpp +++ b/libraries/plugins/affiliate_stats/include/graphene/affiliate_stats/affiliate_stats_api.hpp @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -47,7 +48,12 @@ namespace detail { class referral_payment { public: - + referral_payment(); + referral_payment( const operation_history_object& oho ); + operation_history_id_type id; + uint32_t block_num; + app_tag tag; + asset payout; }; class top_referred_account { @@ -73,7 +79,7 @@ class affiliate_stats_api public: affiliate_stats_api(graphene::app::application& app); - std::vector list_historic_referral_rewards( account_id_type affiliate )const; + std::vector list_historic_referral_rewards( account_id_type affiliate, operation_history_id_type start, uint16_t limit = 100 )const; // get_pending_referral_reward() - not implemented because we have continuous payouts // get_previous_referral_reward() - not implemented because we have continuous payouts std::vector list_top_referred_accounts( asset_id_type asset, uint16_t limit = 100 )const; @@ -84,7 +90,7 @@ class affiliate_stats_api } } // graphene::affiliate_stats -FC_REFLECT(graphene::affiliate_stats::referral_payment, ) +FC_REFLECT(graphene::affiliate_stats::referral_payment, (id)(block_num)(tag)(payout) ) FC_REFLECT(graphene::affiliate_stats::top_referred_account, (referral)(total_payout) ) FC_REFLECT(graphene::affiliate_stats::top_app, (app)(total_payout) ) diff --git a/libraries/plugins/affiliate_stats/include/graphene/affiliate_stats/affiliate_stats_plugin.hpp b/libraries/plugins/affiliate_stats/include/graphene/affiliate_stats/affiliate_stats_plugin.hpp index 2262cfab..2d60f8ca 100644 --- a/libraries/plugins/affiliate_stats/include/graphene/affiliate_stats/affiliate_stats_plugin.hpp +++ b/libraries/plugins/affiliate_stats/include/graphene/affiliate_stats/affiliate_stats_plugin.hpp @@ -63,6 +63,8 @@ class affiliate_stats_plugin : public graphene::app::plugin virtual void plugin_initialize(const boost::program_options::variables_map& options) override; virtual void plugin_startup() override; + const std::set& get_reward_history( account_id_type& affiliate )const; + friend class detail::affiliate_stats_plugin_impl; std::unique_ptr my; };