Enable building bookie plugin, add API for bookie plugin, and implement a
function for getting binned order books (as yet untested)
This commit is contained in:
parent
3ac447b8a7
commit
c4470131ac
11 changed files with 219 additions and 80 deletions
|
|
@ -13,7 +13,7 @@ add_library( graphene_app
|
|||
|
||||
# need to link graphene_debug_witness because plugins aren't sufficiently isolated #246
|
||||
#target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_chain fc graphene_db graphene_net graphene_utilities graphene_debug_witness )
|
||||
target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_accounts_list graphene_chain fc graphene_db graphene_net graphene_time graphene_utilities graphene_debug_witness )
|
||||
target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_accounts_list graphene_chain fc graphene_db graphene_net graphene_time graphene_utilities graphene_debug_witness graphene_bookie )
|
||||
target_include_directories( graphene_app
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../egenesis/include" )
|
||||
|
|
|
|||
|
|
@ -111,6 +111,12 @@ namespace graphene { namespace app {
|
|||
if( _app.get_plugin( "debug_witness" ) )
|
||||
_debug_api = std::make_shared< graphene::debug_witness::debug_api >( std::ref(_app) );
|
||||
}
|
||||
else if( api_name == "bookie_api" )
|
||||
{
|
||||
// can only enable this API if the plugin was loaded
|
||||
if( _app.get_plugin( "bookie" ) )
|
||||
_bookie_api = std::make_shared<graphene::bookie::bookie_api>(std::ref(_app));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -269,6 +275,12 @@ namespace graphene { namespace app {
|
|||
return *_debug_api;
|
||||
}
|
||||
|
||||
fc::api<graphene::bookie::bookie_api> login_api::bookie() const
|
||||
{
|
||||
FC_ASSERT(_bookie_api);
|
||||
return *_bookie_api;
|
||||
}
|
||||
|
||||
#if 0
|
||||
vector<account_id_type> get_relevant_accounts( const object* obj )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -228,6 +228,9 @@ namespace detail {
|
|||
|
||||
wsc->register_api(login->database());
|
||||
wsc->register_api(fc::api<graphene::app::login_api>(login));
|
||||
|
||||
wsc->register_api(fc::api<graphene::app::login_api>(login));
|
||||
|
||||
c->set_session_data( wsc );
|
||||
|
||||
std::string username = "*";
|
||||
|
|
@ -455,6 +458,7 @@ namespace detail {
|
|||
wild_access.allowed_apis.push_back( "network_broadcast_api" );
|
||||
wild_access.allowed_apis.push_back( "history_api" );
|
||||
wild_access.allowed_apis.push_back( "crypto_api" );
|
||||
wild_access.allowed_apis.push_back( "bookie_api" );
|
||||
_apiaccess.permission_map["*"] = wild_access;
|
||||
}
|
||||
|
||||
|
|
@ -463,6 +467,7 @@ namespace detail {
|
|||
reset_websocket_tls_server();
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
|
||||
optional< api_access_info > get_api_access_info(const string& username)const
|
||||
{
|
||||
optional< api_access_info > result;
|
||||
|
|
@ -1083,3 +1088,7 @@ void application::startup_plugins()
|
|||
|
||||
// namespace detail
|
||||
} }
|
||||
|
||||
// for some reason, g++ isn't instantiating this function on its own, force it to here
|
||||
template
|
||||
fc::api_id_type fc::api<graphene::bookie::bookie_api, fc::identity_member>::register_api(fc::api_connection&) const;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <graphene/accounts_list/accounts_list_plugin.hpp>
|
||||
|
||||
#include <graphene/debug_witness/debug_api.hpp>
|
||||
#include <graphene/bookie/bookie_api.hpp>
|
||||
|
||||
#include <graphene/net/node.hpp>
|
||||
|
||||
|
|
@ -359,6 +360,8 @@ namespace graphene { namespace app {
|
|||
fc::api<asset_api> asset()const;
|
||||
/// @brief Retrieve the debug API (if available)
|
||||
fc::api<graphene::debug_witness::debug_api> debug()const;
|
||||
/// @brief Retrieve the bookie API (if available)
|
||||
fc::api<graphene::bookie::bookie_api> bookie()const;
|
||||
|
||||
/// @brief Called to enable an API, not reflected.
|
||||
void enable_api( const string& api_name );
|
||||
|
|
@ -373,6 +376,7 @@ namespace graphene { namespace app {
|
|||
optional< fc::api<crypto_api> > _crypto_api;
|
||||
optional< fc::api<asset_api> > _asset_api;
|
||||
optional< fc::api<graphene::debug_witness::debug_api> > _debug_api;
|
||||
optional< fc::api<graphene::bookie::bookie_api> > _bookie_api;
|
||||
};
|
||||
|
||||
}} // graphene::app
|
||||
|
|
@ -441,4 +445,5 @@ FC_API(graphene::app::login_api,
|
|||
(crypto)
|
||||
(asset)
|
||||
(debug)
|
||||
(bookie)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ file(GLOB HEADERS "include/graphene/bookie/*.hpp")
|
|||
|
||||
add_library( graphene_bookie
|
||||
bookie_plugin.cpp
|
||||
bookie_api.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_bookie graphene_chain graphene_app )
|
||||
|
|
|
|||
123
libraries/plugins/bookie/bookie_api.cpp
Normal file
123
libraries/plugins/bookie/bookie_api.cpp
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
#include <fc/filesystem.hpp>
|
||||
#include <fc/optional.hpp>
|
||||
#include <fc/variant_object.hpp>
|
||||
#include <fc/smart_ref_impl.hpp>
|
||||
|
||||
#include <graphene/app/application.hpp>
|
||||
|
||||
#include <graphene/chain/block_database.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/betting_market_object.hpp>
|
||||
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
|
||||
#include <graphene/utilities/key_conversion.hpp>
|
||||
|
||||
#include <graphene/bookie/bookie_api.hpp>
|
||||
#include <graphene/bookie/bookie_plugin.hpp>
|
||||
|
||||
namespace graphene { namespace bookie {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class bookie_api_impl
|
||||
{
|
||||
public:
|
||||
bookie_api_impl(graphene::app::application& _app);
|
||||
|
||||
binned_order_book get_binned_order_book(graphene::chain::betting_market_id_type betting_market_id, int32_t precision);
|
||||
std::shared_ptr<graphene::bookie::bookie_plugin> get_plugin();
|
||||
|
||||
graphene::app::application& app;
|
||||
};
|
||||
|
||||
bookie_api_impl::bookie_api_impl(graphene::app::application& _app) : app(_app)
|
||||
{}
|
||||
|
||||
|
||||
binned_order_book bookie_api_impl::get_binned_order_book(graphene::chain::betting_market_id_type betting_market_id, int32_t precision)
|
||||
{
|
||||
std::shared_ptr<graphene::chain::database> db = app.chain_database();
|
||||
const auto& bet_odds_idx = db->get_index_type<graphene::chain::bet_object_index>().indices().get<graphene::chain::by_odds>();
|
||||
|
||||
graphene::chain::bet_multiplier_type bin_size = GRAPHENE_BETTING_ODDS_PRECISION;
|
||||
if (precision > 0)
|
||||
for (int32_t i = 0; i < precision; ++i) {
|
||||
FC_ASSERT(bin_size > (GRAPHENE_BETTING_MIN_MULTIPLIER - GRAPHENE_BETTING_ODDS_PRECISION), "invalid precision");
|
||||
bin_size /= 10;
|
||||
}
|
||||
else if (precision < 0)
|
||||
for (int32_t i = 0; i > precision; --i) {
|
||||
FC_ASSERT(bin_size < (GRAPHENE_BETTING_MAX_MULTIPLIER - GRAPHENE_BETTING_ODDS_PRECISION), "invalid precision");
|
||||
bin_size *= 10;
|
||||
}
|
||||
|
||||
binned_order_book result;
|
||||
|
||||
// use a bet_object here for convenience. we really only use it to track the amount, odds, and back_or_lay
|
||||
// note, the current bin is accumulating the matching bets, so it will be of type 'lay' when we're
|
||||
// binning 'back' bets, and vice versa
|
||||
fc::optional<bet_object> current_bin;
|
||||
|
||||
auto flush_current_bin = [¤t_bin, &result]()
|
||||
{
|
||||
if (current_bin) // do nothing if the current bin is empty
|
||||
{
|
||||
order_bin current_order_bin;
|
||||
|
||||
current_order_bin.backer_multiplier = current_bin->backer_multiplier;
|
||||
current_order_bin.amount_to_bet = current_bin->get_matching_amount();;
|
||||
if (current_bin->back_or_lay == bet_type::lay)
|
||||
result.aggregated_back_bets.emplace_back(std::move(current_order_bin));
|
||||
else // current_bin is aggregating back positions
|
||||
result.aggregated_lay_bets.emplace_back(std::move(current_order_bin));
|
||||
|
||||
current_bin.reset();
|
||||
}
|
||||
};
|
||||
|
||||
for (auto bet_odds_iter = bet_odds_idx.lower_bound(std::make_tuple(betting_market_id));
|
||||
bet_odds_iter != bet_odds_idx.end() && betting_market_id == bet_odds_iter->betting_market_id;
|
||||
++bet_odds_iter)
|
||||
{
|
||||
if (current_bin &&
|
||||
(bet_odds_iter->back_or_lay == current_bin->back_or_lay ||
|
||||
bet_odds_iter->backer_multiplier > current_bin->backer_multiplier))
|
||||
flush_current_bin();
|
||||
|
||||
if (!current_bin)
|
||||
{
|
||||
// if there is no current bin, create one appropriate for the bet we're processing
|
||||
current_bin = graphene::chain::bet_object();
|
||||
current_bin->backer_multiplier = (bet_odds_iter->backer_multiplier + bin_size - 1) / bin_size * bin_size;
|
||||
current_bin->amount_to_bet.amount = 0;
|
||||
current_bin->back_or_lay = bet_odds_iter->back_or_lay == bet_type::back ? bet_type::lay : bet_type::back;
|
||||
}
|
||||
|
||||
current_bin->amount_to_bet.amount += bet_odds_iter->get_matching_amount();
|
||||
}
|
||||
if (current_bin)
|
||||
flush_current_bin();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<graphene::bookie::bookie_plugin> bookie_api_impl::get_plugin()
|
||||
{
|
||||
return app.get_plugin<graphene::bookie::bookie_plugin>("bookie");
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
bookie_api::bookie_api(graphene::app::application& app) :
|
||||
my(std::make_shared<detail::bookie_api_impl>(app))
|
||||
{
|
||||
}
|
||||
|
||||
binned_order_book bookie_api::get_binned_order_book(graphene::chain::betting_market_id_type betting_market_id, int32_t precision)
|
||||
{
|
||||
return my->get_binned_order_book(betting_market_id, precision);
|
||||
}
|
||||
|
||||
} } // graphene::bookie
|
||||
|
||||
|
|
@ -215,77 +215,7 @@ void bookie_plugin_impl::on_objects_changed(const vector<object_id_type>& change
|
|||
void bookie_plugin_impl::on_block_applied( const signed_block& )
|
||||
{
|
||||
graphene::chain::database& db = database();
|
||||
const vector<optional< operation_history_object > >& hist = db.get_applied_operations();
|
||||
for( const optional< operation_history_object >& o_op : hist )
|
||||
{
|
||||
// add to the operation history index
|
||||
const auto& oho = db.create<operation_history_object>( [&]( operation_history_object& h )
|
||||
{
|
||||
if( o_op.valid() )
|
||||
h = *o_op;
|
||||
} );
|
||||
|
||||
if( !o_op.valid() )
|
||||
{
|
||||
ilog( "removing failed operation with ID: ${id}", ("id", oho.id) );
|
||||
db.remove( oho );
|
||||
continue;
|
||||
}
|
||||
|
||||
const operation_history_object& op = *o_op;
|
||||
|
||||
// get the set of accounts this operation applies to
|
||||
flat_set<account_id_type> impacted;
|
||||
vector<authority> other;
|
||||
operation_get_required_authorities( op.op, impacted, impacted, other );
|
||||
|
||||
if( op.op.which() == operation::tag< account_create_operation >::value )
|
||||
impacted.insert( oho.result.get<object_id_type>() );
|
||||
else
|
||||
graphene::app::operation_get_impacted_accounts( op.op, impacted );
|
||||
|
||||
for( auto& a : other )
|
||||
for( auto& item : a.account_auths )
|
||||
impacted.insert( item.first );
|
||||
|
||||
// for each operation this account applies to that is in the config link it into the history
|
||||
if( _tracked_accounts.size() == 0 )
|
||||
{
|
||||
for( auto& account_id : impacted )
|
||||
{
|
||||
// we don't do index_account_keys here anymore, because
|
||||
// that indexing now happens in observers' post_evaluate()
|
||||
|
||||
// add history
|
||||
const auto& stats_obj = account_id(db).statistics(db);
|
||||
const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){
|
||||
obj.operation_id = oho.id;
|
||||
obj.next = stats_obj.most_recent_op;
|
||||
});
|
||||
db.modify( stats_obj, [&]( account_statistics_object& obj ){
|
||||
obj.most_recent_op = ath.id;
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( auto account_id : _tracked_accounts )
|
||||
{
|
||||
if( impacted.find( account_id ) != impacted.end() )
|
||||
{
|
||||
// add history
|
||||
const auto& stats_obj = account_id(db).statistics(db);
|
||||
const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){
|
||||
obj.operation_id = oho.id;
|
||||
obj.next = stats_obj.most_recent_op;
|
||||
});
|
||||
db.modify( stats_obj, [&]( account_statistics_object& obj ){
|
||||
obj.most_recent_op = ath.id;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const vector<optional<operation_history_object> >& hist = db.get_applied_operations();
|
||||
}
|
||||
} // end namespace detail
|
||||
|
||||
|
|
@ -308,24 +238,27 @@ void bookie_plugin::plugin_set_program_options(
|
|||
boost::program_options::options_description& cfg
|
||||
)
|
||||
{
|
||||
cli.add_options()
|
||||
("track-account", boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(), "Account ID to track history for (may specify multiple times)")
|
||||
;
|
||||
cfg.add(cli);
|
||||
//cli.add_options()
|
||||
// ("track-account", boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(), "Account ID to track history for (may specify multiple times)")
|
||||
// ;
|
||||
//cfg.add(cli);
|
||||
}
|
||||
|
||||
void bookie_plugin::plugin_initialize(const boost::program_options::variables_map& options)
|
||||
{
|
||||
database().applied_block.connect( [&]( const signed_block& b){ my->on_block_applied(b); } );
|
||||
ilog("bookie plugin: plugin_startup() begin");
|
||||
//database().applied_block.connect( [&]( const signed_block& b){ my->on_block_applied(b); } );
|
||||
database().changed_objects.connect([&](const vector<object_id_type>& changed_object_ids, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts){ my->on_objects_changed(changed_object_ids); });
|
||||
auto event_index = database().add_index<primary_index<detail::persistent_event_object_index> >();
|
||||
//event_index->add_secondary_index<detail::events_by_competitor_index>();
|
||||
|
||||
LOAD_VALUE_SET(options, "tracked-accounts", my->_tracked_accounts, graphene::chain::account_id_type);
|
||||
//LOAD_VALUE_SET(options, "tracked-accounts", my->_tracked_accounts, graphene::chain::account_id_type);
|
||||
ilog("bookie plugin: plugin_startup() end");
|
||||
}
|
||||
|
||||
void bookie_plugin::plugin_startup()
|
||||
{
|
||||
ilog("bookie plugin: plugin_startup()");
|
||||
}
|
||||
|
||||
flat_set<account_id_type> bookie_plugin::tracked_accounts() const
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <fc/api.hpp>
|
||||
#include <fc/variant_object.hpp>
|
||||
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
namespace graphene { namespace app {
|
||||
class application;
|
||||
} }
|
||||
|
||||
namespace graphene { namespace bookie {
|
||||
|
||||
namespace detail {
|
||||
class bookie_api_impl;
|
||||
}
|
||||
|
||||
struct order_bin {
|
||||
graphene::chain::share_type amount_to_bet;
|
||||
graphene::chain::bet_multiplier_type backer_multiplier;
|
||||
};
|
||||
|
||||
struct binned_order_book {
|
||||
std::vector<order_bin> aggregated_back_bets;
|
||||
std::vector<order_bin> aggregated_lay_bets;
|
||||
};
|
||||
|
||||
class bookie_api
|
||||
{
|
||||
public:
|
||||
bookie_api(graphene::app::application& app);
|
||||
|
||||
/**
|
||||
* Returns the current order book, binned according to the given precision.
|
||||
* precision = 1 means bin using one decimal place: (1 - 1.1], (1.1 - 1.2], etc.
|
||||
* precision = 2 would bin on (1 - 1.01], (1.01 - 1.02]
|
||||
*/
|
||||
binned_order_book get_binned_order_book(graphene::chain::betting_market_id_type betting_market_id, int32_t precision);
|
||||
|
||||
std::shared_ptr<detail::bookie_api_impl> my;
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
FC_REFLECT(graphene::bookie::order_bin, (amount_to_bet)(backer_multiplier))
|
||||
FC_REFLECT(graphene::bookie::binned_order_book, (aggregated_back_bets)(aggregated_lay_bets))
|
||||
|
||||
FC_API(graphene::bookie::bookie_api,
|
||||
(get_binned_order_book)
|
||||
)
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ if( GPERFTOOLS_FOUND )
|
|||
endif()
|
||||
|
||||
target_link_libraries( debug_node
|
||||
PRIVATE graphene_app graphene_account_history graphene_market_history graphene_witness graphene_debug_witness graphene_chain graphene_egenesis_full fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
|
||||
PRIVATE graphene_app graphene_account_history graphene_market_history graphene_witness graphene_debug_witness graphene_bookie graphene_chain graphene_egenesis_full fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
|
||||
|
||||
install( TARGETS
|
||||
debug_node
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ endif()
|
|||
|
||||
# We have to link against graphene_debug_witness because deficiency in our API infrastructure doesn't allow plugins to be fully abstracted #246
|
||||
target_link_libraries( witness_node
|
||||
PRIVATE graphene_app graphene_account_history graphene_market_history graphene_witness graphene_chain graphene_debug_witness graphene_egenesis_full fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
|
||||
PRIVATE graphene_app graphene_account_history graphene_market_history graphene_witness graphene_chain graphene_debug_witness graphene_bookie graphene_egenesis_full fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
|
||||
# also add dependencies to graphene_generate_genesis graphene_generate_uia_sharedrop_genesis if you want those plugins
|
||||
|
||||
install( TARGETS
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <graphene/market_history/market_history_plugin.hpp>
|
||||
//#include <graphene/generate_genesis/generate_genesis_plugin.hpp>
|
||||
//#include <graphene/generate_uia_sharedrop_genesis/generate_uia_sharedrop_genesis.hpp>
|
||||
#include <graphene/bookie/bookie_plugin.hpp>
|
||||
|
||||
#include <fc/exception/exception.hpp>
|
||||
#include <fc/thread/thread.hpp>
|
||||
|
|
@ -80,6 +81,7 @@ int main(int argc, char** argv) {
|
|||
//auto generate_genesis_plug = node->register_plugin<generate_genesis_plugin::generate_genesis_plugin>();
|
||||
//auto generate_uia_sharedrop_genesis_plug = node->register_plugin<generate_uia_sharedrop_genesis::generate_uia_sharedrop_genesis_plugin>();
|
||||
auto list_plug = node->register_plugin<accounts_list::accounts_list_plugin>();
|
||||
auto bookie_plug = node->register_plugin<bookie::bookie_plugin>();
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue