From 7378fb80bcb0937932626ab5d6335a48d8033cc9 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Fri, 23 Oct 2015 18:13:33 -0400 Subject: [PATCH] adding API call for market fill history --- libraries/app/api.cpp | 23 ++++++++++++ libraries/app/include/graphene/app/api.hpp | 2 + libraries/chain/market_evaluator.cpp | 3 ++ .../market_history/market_history_plugin.hpp | 30 +++++++++++++++ .../market_history/market_history_plugin.cpp | 37 +++++++++++++++++++ 5 files changed, 95 insertions(+) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index ac16c682..53cb6c36 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -310,6 +310,29 @@ namespace graphene { namespace app { return result; } // end get_relevant_accounts( obj ) + vector history_api::get_fill_order_history( asset_id_type a, asset_id_type b )const + { + FC_ASSERT(_app.chain_database()); + const auto& db = *_app.chain_database(); + if( a > b ) std::swap(a,b); + const auto& history_idx = db.get_index_type().indices().get(); + history_key hkey; + hkey.base = a; + hkey.quote = b; + hkey.sequence = 0; + + auto itr = history_idx.lower_bound( hkey ); + vector result; + while( itr != history_idx.end() ) + { + if( itr->key.base != a || itr->key.quote != b ) break; + result.push_back( itr->op ); + ++itr; + } + + return result; + } + vector history_api::get_account_history(account_id_type account, operation_history_id_type stop, unsigned limit, operation_history_id_type start) const { FC_ASSERT(_app.chain_database()); diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index 2a5827fa..1b800b46 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -70,6 +70,7 @@ namespace graphene { namespace app { unsigned limit = 100, operation_history_id_type start = operation_history_id_type())const; + vector get_fill_order_history( asset_id_type a, asset_id_type b )const; vector 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; flat_set get_market_history_buckets()const; @@ -203,6 +204,7 @@ FC_REFLECT( graphene::app::network_broadcast_api::transaction_confirmation, FC_API(graphene::app::history_api, (get_account_history) + (get_fill_order_history) (get_market_history) (get_market_history_buckets) ) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index a93e7578..a0eeac97 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -21,6 +21,9 @@ #include #include #include +#include +#include +#include #include namespace graphene { namespace chain { diff --git a/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp b/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp index abeacff0..9b2b855d 100644 --- a/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp +++ b/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp @@ -84,6 +84,24 @@ struct bucket_object : public abstract_object share_type quote_volume; }; +struct history_key { + asset_id_type base; + asset_id_type quote; + uint64_t sequence = 0; + + friend bool operator < ( const history_key& a, const history_key& b ) { + return std::tie( a.base, a.quote, a.sequence ) < std::tie( b.base, b.quote, b.sequence ); + } + friend bool operator == ( const history_key& a, const history_key& b ) { + return std::tie( a.base, a.quote, a.sequence ) == std::tie( b.base, b.quote, b.sequence ); + } +}; +struct order_history_object : public abstract_object +{ + history_key key; + fill_order_operation op; +}; + struct by_key; typedef multi_index_container< bucket_object, @@ -93,7 +111,17 @@ typedef multi_index_container< > > bucket_object_multi_index_type; +typedef multi_index_container< + order_history_object, + indexed_by< + hashed_unique< tag, member< object, object_id_type, &object::id > >, + ordered_unique< tag, member< order_history_object, history_key, &order_history_object::key > > + > +> order_history_multi_index_type; + + typedef generic_index bucket_index; +typedef generic_index history_index; namespace detail @@ -130,6 +158,8 @@ class market_history_plugin : public graphene::app::plugin } } //graphene::market_history +FC_REFLECT( graphene::market_history::history_key, (base)(quote)(sequence) ) +FC_REFLECT_DERIVED( graphene::market_history::order_history_object, (graphene::db::object), (key)(op) ) FC_REFLECT( graphene::market_history::bucket_key, (base)(quote)(seconds)(open) ) FC_REFLECT_DERIVED( graphene::market_history::bucket_object, (graphene::db::object), (key) diff --git a/libraries/plugins/market_history/market_history_plugin.cpp b/libraries/plugins/market_history/market_history_plugin.cpp index 6cdf4a7c..0a6fe88d 100644 --- a/libraries/plugins/market_history/market_history_plugin.cpp +++ b/libraries/plugins/market_history/market_history_plugin.cpp @@ -81,6 +81,41 @@ struct operation_process_fill_order const auto& buckets = _plugin.tracked_buckets(); auto& db = _plugin.database(); const auto& bucket_idx = db.get_index_type(); + const auto& history_idx = db.get_index_type().indices().get(); + + history_key hkey; + hkey.base = o.pays.asset_id; + hkey.quote = o.receives.asset_id; + if( hkey.base > hkey.quote ) + std::swap( hkey.base, hkey.quote ); + hkey.sequence = uint64_t(-1); + + auto itr = history_idx.upper_bound( hkey ); + if( itr != history_idx.begin() ) + --itr; + + if( itr->key.base == hkey.base && itr->key.quote == hkey.quote ) + hkey.sequence = itr->key.sequence + 1; + else + hkey.sequence = 0; + + db.create( [&]( order_history_object& ho ) { + ho.key = hkey; + ho.op = o; + }); + if( hkey.sequence > 200 ) + { + auto end = hkey.sequence - 200; + itr = history_idx.lower_bound( hkey ); + + while( itr != history_idx.end() && itr->key.sequence < end ) + { + auto delete_me = itr; + ++itr; + db.remove( *delete_me ); + } + } + auto max_history = _plugin.max_history(); for( auto bucket : buckets ) @@ -91,6 +126,7 @@ struct operation_process_fill_order key.base = o.pays.asset_id; key.quote = o.receives.asset_id; + /** for every matched order there are two fill order operations created, one for * each side. We can filter the duplicates by only considering the fill operations where * the base > quote @@ -222,6 +258,7 @@ void market_history_plugin::plugin_initialize(const boost::program_options::vari { try { database().applied_block.connect( [&]( const signed_block& b){ my->update_market_histories(b); } ); database().add_index< primary_index< bucket_index > >(); + database().add_index< primary_index< history_index > >(); if( options.count( "bucket-size" ) ) {