From b96459045b7deb5a4d9c8afce1f411150a8a0069 Mon Sep 17 00:00:00 2001 From: Roman Olearski Date: Fri, 28 Jul 2017 18:23:57 +0200 Subject: [PATCH] added get_total_matched_bet_amount_for_betting_market_group to bookie_plugin --- libraries/chain/db_bet.cpp | 3 +- .../graphene/chain/betting_market_object.hpp | 4 +- .../chain/protocol/betting_market.hpp | 6 +- libraries/plugins/bookie/bookie_api.cpp | 12 ++++ libraries/plugins/bookie/bookie_plugin.cpp | 41 +++++++++++- .../include/graphene/bookie/bookie_api.hpp | 5 ++ .../include/graphene/bookie/bookie_plugin.hpp | 1 + .../wallet/include/graphene/wallet/wallet.hpp | 3 + libraries/wallet/wallet.cpp | 5 ++ tests/betting/betting_tests.cpp | 67 +++++++++++++++++-- tests/common/database_fixture.cpp | 11 +-- 11 files changed, 141 insertions(+), 17 deletions(-) diff --git a/libraries/chain/db_bet.cpp b/libraries/chain/db_bet.cpp index f820d43d..a4eded19 100644 --- a/libraries/chain/db_bet.cpp +++ b/libraries/chain/db_bet.cpp @@ -55,6 +55,7 @@ void database::validate_betting_market_group_resolutions(const betting_market_gr { const betting_market_object& betting_market = *betting_market_itr; // every betting market in the group tied with resolution + idump((betting_market.id)(resolutions)); assert(resolutions.count(betting_market.id)); ++betting_market_itr; } @@ -283,7 +284,7 @@ bool bet_was_matched(database& db, const bet_object& bet, // generate a virtual "match" op asset asset_amount_bet(amount_bet, bet.amount_to_bet.asset_id); - db.push_applied_operation(bet_matched_operation(bet.bettor_id, bet.id, + db.push_applied_operation(bet_matched_operation(bet.bettor_id, bet.id, bet.betting_market_id, asset_amount_bet, fee_paid, actual_multiplier, diff --git a/libraries/chain/include/graphene/chain/betting_market_object.hpp b/libraries/chain/include/graphene/chain/betting_market_object.hpp index 4e014762..715d997d 100644 --- a/libraries/chain/include/graphene/chain/betting_market_object.hpp +++ b/libraries/chain/include/graphene/chain/betting_market_object.hpp @@ -62,6 +62,8 @@ class betting_market_group_object : public graphene::db::abstract_object< bettin asset_id_type asset_id; + share_type total_matched_bets_amount; + bool frozen; }; @@ -427,7 +429,7 @@ typedef generic_index get_plugin(); + asset get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id); graphene::app::application& app; }; @@ -107,6 +108,11 @@ std::shared_ptr bookie_api_impl::get_plugin() return app.get_plugin("bookie"); } +asset bookie_api_impl::get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id) +{ + return get_plugin()->get_total_matched_bet_amount_for_betting_market_group(group_id); +} + } // detail bookie_api::bookie_api(graphene::app::application& app) : @@ -119,5 +125,11 @@ binned_order_book bookie_api::get_binned_order_book(graphene::chain::betting_mar return my->get_binned_order_book(betting_market_id, precision); } +asset bookie_api::get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id) +{ + return my->get_total_matched_bet_amount_for_betting_market_group(group_id); +} + } } // graphene::bookie + diff --git a/libraries/plugins/bookie/bookie_plugin.cpp b/libraries/plugins/bookie/bookie_plugin.cpp index acbd0a3d..5b1dcf46 100644 --- a/libraries/plugins/bookie/bookie_plugin.cpp +++ b/libraries/plugins/bookie/bookie_plugin.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include + #include #include @@ -141,6 +143,8 @@ class bookie_plugin_impl */ void on_block_applied( const signed_block& b ); + asset get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id); + graphene::chain::database& database() { return _self.database(); @@ -216,6 +220,35 @@ void bookie_plugin_impl::on_block_applied( const signed_block& ) { graphene::chain::database& db = database(); const vector >& hist = db.get_applied_operations(); + for( const optional< operation_history_object >& o_op : hist ) + { + if( !o_op.valid() ) + { + continue; + } + const operation_history_object& op = *o_op; + if( op.op.which() == operation::tag< bet_matched_operation >::value ) + { + const bet_matched_operation& bet_matched_op = op.op.get(); + idump((bet_matched_op)); + const asset& amount_bet = bet_matched_op.amount_bet; + // object may no longer exist + //const bet_object& bet = bet_matched_op.bet_id(db); + const betting_market_object& betting_market = bet_matched_op.betting_market_id(db); + const betting_market_group_object& betting_market_group = betting_market.group_id(db); + db.modify( betting_market_group, [&]( betting_market_group_object& obj ){ + obj.total_matched_bets_amount += amount_bet.amount; + }); + } + } +} + +asset bookie_plugin_impl::get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id) +{ + graphene::chain::database& db = database(); + FC_ASSERT( db.find_object(group_id), "Invalid betting market group specified" ); + const betting_market_group_object& betting_market_group = group_id(db); + return asset(betting_market_group.total_matched_bets_amount, betting_market_group.asset_id); } } // end namespace detail @@ -247,7 +280,7 @@ void bookie_plugin::plugin_set_program_options( void bookie_plugin::plugin_initialize(const boost::program_options::variables_map& options) { ilog("bookie plugin: plugin_startup() begin"); - //database().applied_block.connect( [&]( const signed_block& b){ my->on_block_applied(b); } ); + database().applied_block.connect( [&]( const signed_block& b){ my->on_block_applied(b); } ); database().changed_objects.connect([&](const vector& changed_object_ids, const fc::flat_set& impacted_accounts){ my->on_objects_changed(changed_object_ids); }); auto event_index = database().add_index >(); //event_index->add_secondary_index(); @@ -266,6 +299,12 @@ flat_set bookie_plugin::tracked_accounts() const return my->_tracked_accounts; } +asset bookie_plugin::get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id) +{ + ilog("bookie plugin: get_total_matched_bet_amount_for_betting_market_group($group_id)", ("group_d", group_id)); + return my->get_total_matched_bet_amount_for_betting_market_group(group_id); +} + } } FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_event_object, (graphene::db::object), (event_object_id)(name)(season)(start_time)(event_group_id)(status)(scores) ) diff --git a/libraries/plugins/bookie/include/graphene/bookie/bookie_api.hpp b/libraries/plugins/bookie/include/graphene/bookie/bookie_api.hpp index b3e1d402..6f8b5dea 100644 --- a/libraries/plugins/bookie/include/graphene/bookie/bookie_api.hpp +++ b/libraries/plugins/bookie/include/graphene/bookie/bookie_api.hpp @@ -7,6 +7,9 @@ #include #include +#include + +using namespace graphene::chain; namespace graphene { namespace app { class application; @@ -39,6 +42,7 @@ class bookie_api * 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); + asset get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id); std::shared_ptr my; }; @@ -50,5 +54,6 @@ FC_REFLECT(graphene::bookie::binned_order_book, (aggregated_back_bets)(aggregate FC_API(graphene::bookie::bookie_api, (get_binned_order_book) + (get_total_matched_bet_amount_for_betting_market_group) ) diff --git a/libraries/plugins/bookie/include/graphene/bookie/bookie_plugin.hpp b/libraries/plugins/bookie/include/graphene/bookie/bookie_plugin.hpp index 1d146ad0..8fa9e8e3 100644 --- a/libraries/plugins/bookie/include/graphene/bookie/bookie_plugin.hpp +++ b/libraries/plugins/bookie/include/graphene/bookie/bookie_plugin.hpp @@ -70,6 +70,7 @@ class bookie_plugin : public graphene::app::plugin virtual void plugin_startup() override; flat_set tracked_accounts()const; + asset get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id); friend class detail::bookie_plugin_impl; std::unique_ptr my; diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 2e444854..3a87a059 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1570,6 +1570,8 @@ class wallet_api order_book get_order_book( const string& base, const string& quote, unsigned limit = 50); + asset get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id); + vector list_sports() const; vector list_event_groups(sport_id_type sport_id) const; vector list_betting_market_groups(event_id_type event_id) const; @@ -1980,4 +1982,5 @@ FC_API( graphene::wallet::wallet_api, (get_tournaments_by_state) (get_tournament) (get_order_book) + (get_total_matched_bet_amount_for_betting_market_group) ) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index a5b2e6af..650dc1ea 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -5628,6 +5628,11 @@ order_book wallet_api::get_order_book( const string& base, const string& quote, return( my->_remote_db->get_order_book( base, quote, limit ) ); } +asset wallet_api::get_total_matched_bet_amount_for_betting_market_group(betting_market_group_id_type group_id) +{ + return asset(); +} + // default ctor necessary for FC_REFLECT signed_block_with_info::signed_block_with_info( const signed_block& block ) : signed_block( block ) diff --git a/tests/betting/betting_tests.cpp b/tests/betting/betting_tests.cpp index 8dc4f243..05acf8c1 100644 --- a/tests/betting/betting_tests.cpp +++ b/tests/betting/betting_tests.cpp @@ -775,7 +775,13 @@ BOOST_FIXTURE_TEST_SUITE( tennis_bet_tests, database_fixture ) const betting_market_object& berdych_wins_market = create_betting_market(moneyline_berdych_vs_federer.id, {{"en", "T. Berdych defeats R. Federer"}}); \ const betting_market_object& federer_wins_market = create_betting_market(moneyline_berdych_vs_federer.id, {{"en", "R. Federer defeats T. Berdych"}}); \ const betting_market_object& cilic_wins_market = create_betting_market(moneyline_cilic_vs_querrey.id, {{"en", "M. Cilic defeats S. Querrey"}}); \ - const betting_market_object& querrey_wins_market = create_betting_market(moneyline_cilic_vs_querrey.id, {{"en", "S. Querrey defeats M. Cilic"}}); + const betting_market_object& querrey_wins_market = create_betting_market(moneyline_cilic_vs_querrey.id, {{"en", "S. Querrey defeats M. Cilic"}});\ + \ + const event_object& cilic_vs_federer = create_event({{"en", "R. Federer/M. Cilic"}}, {{"en", "2017"}}, wimbledon.id); \ + const betting_market_group_object& moneyline_cilic_vs_federer = create_betting_market_group({{"en", "Moneyline final"}}, cilic_vs_federer.id, tennis_rules.id, asset_id_type()); \ + const betting_market_object& federer_wins_final_market = create_betting_market(moneyline_cilic_vs_federer.id, {{"en", "R. Federer defeats M. Cilic"}}); \ + const betting_market_object& cilic_wins_final_market = create_betting_market(moneyline_cilic_vs_federer.id, {{"en", "M. Cilic defeats R. Federer"}}); + BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_sf_test ) { @@ -789,13 +795,13 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_sf_test ) transfer(account_id_type(), alice_id, asset(10000000)); transfer(account_id_type(), bob_id, asset(10000000)); - BOOST_TEST_MESSAGE("moneyline_berdych_vs_federer event " << fc::variant(moneyline_berdych_vs_federer.event_id).as()); - BOOST_TEST_MESSAGE("moneyline_cilic_vs_querrey event " << fc::variant(moneyline_cilic_vs_querrey.event_id).as()); + BOOST_TEST_MESSAGE("moneyline_berdych_vs_federer " << fc::variant(moneyline_berdych_vs_federer.id).as()); + BOOST_TEST_MESSAGE("moneyline_cilic_vs_querrey " << fc::variant(moneyline_cilic_vs_querrey.id).as()); - BOOST_TEST_MESSAGE("berdych_wins_market group " << fc::variant(berdych_wins_market.group_id).as()); - BOOST_TEST_MESSAGE("federer_wins_market group " << fc::variant(federer_wins_market.group_id).as()); - BOOST_TEST_MESSAGE("cilic_wins_market group " << fc::variant(cilic_wins_market.group_id).as()); - BOOST_TEST_MESSAGE("querrey_wins_market group " << fc::variant(querrey_wins_market.group_id).as()); + BOOST_TEST_MESSAGE("berdych_wins_market " << fc::variant(berdych_wins_market.id).as()); + BOOST_TEST_MESSAGE("federer_wins_market " << fc::variant(federer_wins_market.id).as()); + BOOST_TEST_MESSAGE("cilic_wins_market " << fc::variant(cilic_wins_market.id).as()); + BOOST_TEST_MESSAGE("querrey_wins_market " << fc::variant(querrey_wins_market.id).as()); place_bet(alice_id, berdych_wins_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); place_bet(bob_id, berdych_wins_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); @@ -834,9 +840,56 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_sf_test ) } FC_LOG_AND_RETHROW() } +BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_final_test ) +{ + try + { + ACTORS( (alice)(bob) ); + CREATE_TENNIS_BETTING_MARKET(); + + uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage; + + transfer(account_id_type(), alice_id, asset(10000000)); + transfer(account_id_type(), bob_id, asset(10000000)); + + BOOST_TEST_MESSAGE("moneyline_cilic_vs_federer " << fc::variant(moneyline_cilic_vs_federer.id).as()); + + BOOST_TEST_MESSAGE("federer_wins_final_market " << fc::variant(federer_wins_final_market.id).as()); + BOOST_TEST_MESSAGE("cilic_wins_final_market " << fc::variant(cilic_wins_final_market.id).as()); + + place_bet(alice_id, cilic_wins_final_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); + place_bet(bob_id, cilic_wins_final_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); + + betting_market_group_id_type moneyline_cilic_vs_federer_id = moneyline_cilic_vs_federer.id; + auto cilic_wins_final_market_id = cilic_wins_final_market.id; + auto federer_wins_final_market_id = federer_wins_final_market.id; + + generate_blocks(13); + + const betting_market_group_object& betting_market_group = moneyline_cilic_vs_federer_id(db); + BOOST_CHECK_EQUAL(betting_market_group.total_matched_bets_amount.value, 2000000); + + BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000); + BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000); + + // federer wins + resolve_betting_market_group(moneyline_cilic_vs_federer_id, + {{cilic_wins_final_market_id, betting_market_resolution_type::/*don't use cancel - there are bets for berdych*/not_win}, + {federer_wins_final_market_id, betting_market_resolution_type::win}}); + + uint32_t bob_rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100; + BOOST_TEST_MESSAGE("Bob's rake value " + std::to_string(bob_rake_value)); + + BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000); + BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000 + 2000000 - bob_rake_value); + + } FC_LOG_AND_RETHROW() + } + BOOST_AUTO_TEST_SUITE_END() + //#define BOOST_TEST_MODULE "C++ Unit Tests for Graphene Blockchain Database" #include #include diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 896d9d6e..477256e0 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -26,7 +26,8 @@ #include #include -//#include +#include +#include #include @@ -81,7 +82,7 @@ database_fixture::database_fixture() auto ahplugin = app.register_plugin(); auto mhplugin = app.register_plugin(); - //auto bookieplugin = app.register_plugin(); + auto bookieplugin = app.register_plugin(); init_account_pub_key = init_account_priv_key.get_public_key(); boost::program_options::variables_map options; @@ -111,12 +112,12 @@ database_fixture::database_fixture() ahplugin->plugin_initialize(options); mhplugin->plugin_set_app(&app); mhplugin->plugin_initialize(options); - //bookieplugin->plugin_set_app(&app); - //bookieplugin->plugin_initialize(options); + bookieplugin->plugin_set_app(&app); + bookieplugin->plugin_initialize(options); ahplugin->plugin_startup(); mhplugin->plugin_startup(); - //bookieplugin->plugin_startup(); + bookieplugin->plugin_startup(); generate_block();