diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index c723c1fe..be4440fe 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -218,7 +218,9 @@ struct get_impacted_account_visitor void operator()( const betting_market_rules_create_operation& op ) {} void operator()( const betting_market_rules_update_operation& op ) {} void operator()( const betting_market_group_create_operation& op ) {} + void operator()( const betting_market_group_update_operation& op ) {} void operator()( const betting_market_create_operation& op ) {} + void operator()( const betting_market_update_operation& op ) {} void operator()( const betting_market_group_resolve_operation& op ) {} void operator()( const betting_market_group_freeze_operation& op ) {} void operator()( const betting_market_group_cancel_unmatched_bets_operation& op ) {} diff --git a/libraries/chain/betting_market_evaluator.cpp b/libraries/chain/betting_market_evaluator.cpp index c74f650b..b2ba5f25 100644 --- a/libraries/chain/betting_market_evaluator.cpp +++ b/libraries/chain/betting_market_evaluator.cpp @@ -116,6 +116,61 @@ object_id_type betting_market_group_create_evaluator::do_apply(const betting_mar return new_betting_market_group.id; } FC_CAPTURE_AND_RETHROW( (op) ) } +void_result betting_market_group_update_evaluator::do_evaluate(const betting_market_group_update_operation& op) +{ try { + FC_ASSERT(trx_state->_is_proposed_trx); + FC_ASSERT(op.new_event_id.valid() || op.new_description || op.new_rules_id, "nothing to change"); + + // the event_id in the operation can be a relative id. If it is, + // resolve it and verify that it is truly an event + if (op.new_event_id.valid()) + { + object_id_type resolved_event_id = *op.new_event_id; + if (is_relative(*op.new_event_id)) + resolved_event_id = get_relative_id(*op.new_event_id); + + FC_ASSERT(resolved_event_id.space() == event_id_type::space_id && + resolved_event_id.type() == event_id_type::type_id, + "event_id must refer to a event_id_type"); + event_id = resolved_event_id; + FC_ASSERT( db().find_object(event_id), "invalid event specified" ); + } + + if (op.new_rules_id.valid()) + { + // the rules_id in the operation can be a relative id. If it is, + // resolve it and verify that it is truly rules + object_id_type resolved_rules_id = *op.new_rules_id; + if (is_relative(*op.new_rules_id)) + resolved_rules_id = get_relative_id(*op.new_rules_id); + + FC_ASSERT(resolved_rules_id.space() == betting_market_rules_id_type::space_id && + resolved_rules_id.type() == betting_market_rules_id_type::type_id, + "rules_id must refer to a betting_market_rules_id_type"); + rules_id = resolved_rules_id; + FC_ASSERT( db().find_object(rules_id), "invalid rules specified" ); + } + + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + +void_result betting_market_group_update_evaluator::do_apply(const betting_market_group_update_operation& op) +{ try { + database& _db = db(); + _db.modify( + _db.get(op.betting_market_group_id), + [&]( betting_market_group_object& bmgo ) + { + if( op.new_description.valid() ) + bmgo.description = *op.new_description; + if( op.new_event_id.valid() ) + bmgo.event_id = event_id; + if( op.new_rules_id.valid() ) + bmgo.rules_id = rules_id; + }); + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + void_result betting_market_create_evaluator::do_evaluate(const betting_market_create_operation& op) { try { FC_ASSERT(trx_state->_is_proposed_trx); @@ -145,6 +200,44 @@ object_id_type betting_market_create_evaluator::do_apply(const betting_market_cr return new_betting_market.id; } FC_CAPTURE_AND_RETHROW( (op) ) } +void_result betting_market_update_evaluator::do_evaluate(const betting_market_update_operation& op) +{ try { + FC_ASSERT(trx_state->_is_proposed_trx); + FC_ASSERT(op.new_group_id.valid() || op.new_payout_condition, "nothing to change"); + + if (op.new_group_id.valid()) + { + // the betting_market_group_id in the operation can be a relative id. If it is, + // resolve it and verify that it is truly an betting_market_group + object_id_type resolved_betting_market_group_id = *op.new_group_id; + if (is_relative(*op.new_group_id)) + resolved_betting_market_group_id = get_relative_id(*op.new_group_id); + + FC_ASSERT(resolved_betting_market_group_id.space() == betting_market_group_id_type::space_id && + resolved_betting_market_group_id.type() == betting_market_group_id_type::type_id, + "betting_market_group_id must refer to a betting_market_group_id_type"); + group_id = resolved_betting_market_group_id; + FC_ASSERT( db().find_object(group_id), "invalid betting_market_group specified" ); + } + + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + +void_result betting_market_update_evaluator::do_apply(const betting_market_update_operation& op) +{ try { + database& _db = db(); + _db.modify( + _db.get(op.betting_market_id), + [&]( betting_market_object& bmo ) + { + if( op.new_group_id.valid() ) + bmo.group_id = group_id; + if( op.new_payout_condition.valid() ) + bmo.payout_condition = *op.new_payout_condition; + }); + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + void_result bet_place_evaluator::do_evaluate(const bet_place_operation& op) { try { const database& d = db(); diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 54344a1b..c7b06abf 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -223,7 +223,9 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); + register_evaluator(); register_evaluator(); + register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index 90d27618..bcaf4a80 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -200,7 +200,9 @@ struct get_impacted_account_visitor void operator()(const betting_market_rules_create_operation&){} void operator()(const betting_market_rules_update_operation& op ) {} void operator()(const betting_market_group_create_operation&){} + void operator()(const betting_market_group_update_operation& op ) {} void operator()(const betting_market_create_operation&){} + void operator()(const betting_market_update_operation&){} void operator()(const bet_place_operation&){} void operator()(const betting_market_group_resolve_operation&){} void operator()(const betting_market_group_freeze_operation&){} diff --git a/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp b/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp index d07b6696..a1a1128f 100644 --- a/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp @@ -59,6 +59,18 @@ namespace graphene { namespace chain { betting_market_rules_id_type rules_id; }; + class betting_market_group_update_evaluator : public evaluator + { + public: + typedef betting_market_group_update_operation operation_type; + + void_result do_evaluate( const betting_market_group_update_operation& o ); + void_result do_apply( const betting_market_group_update_operation& o ); + private: + event_id_type event_id; + betting_market_rules_id_type rules_id; + }; + class betting_market_create_evaluator : public evaluator { public: @@ -70,6 +82,17 @@ namespace graphene { namespace chain { betting_market_group_id_type group_id; }; + class betting_market_update_evaluator : public evaluator + { + public: + typedef betting_market_update_operation operation_type; + + void_result do_evaluate( const betting_market_update_operation& o ); + void_result do_apply( const betting_market_update_operation& o ); + private: + betting_market_group_id_type group_id; + }; + class bet_place_evaluator : public evaluator { public: diff --git a/libraries/chain/include/graphene/chain/protocol/betting_market.hpp b/libraries/chain/include/graphene/chain/protocol/betting_market.hpp index b02603b0..1d1e527b 100644 --- a/libraries/chain/include/graphene/chain/protocol/betting_market.hpp +++ b/libraries/chain/include/graphene/chain/protocol/betting_market.hpp @@ -103,6 +103,25 @@ struct betting_market_group_create_operation : public base_operation void validate()const; }; +struct betting_market_group_update_operation : public base_operation +{ + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + asset fee; + + betting_market_group_id_type betting_market_group_id; + + optional new_description; + + optional new_event_id; + + optional new_rules_id; + + extensions_type extensions; + + account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + void validate()const; +}; + struct betting_market_create_operation : public base_operation { struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; @@ -122,6 +141,23 @@ struct betting_market_create_operation : public base_operation void validate()const; }; +struct betting_market_update_operation : public base_operation +{ + struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; + asset fee; + + betting_market_id_type betting_market_id; + + optional new_group_id; + + optional new_payout_condition; + + extensions_type extensions; + + account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; } + void validate()const; +}; + enum class betting_market_resolution_type { win, not_win, @@ -337,10 +373,18 @@ FC_REFLECT( graphene::chain::betting_market_group_create_operation::fee_paramete FC_REFLECT( graphene::chain::betting_market_group_create_operation, (fee)(description)(event_id)(rules_id)(asset_id)(extensions) ) +FC_REFLECT( graphene::chain::betting_market_group_update_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::betting_market_group_update_operation, + (fee)(betting_market_group_id)(new_description)(new_event_id)(new_rules_id)(extensions) ) + FC_REFLECT( graphene::chain::betting_market_create_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::betting_market_create_operation, (fee)(group_id)(payout_condition)(extensions) ) +FC_REFLECT( graphene::chain::betting_market_update_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::betting_market_update_operation, + (fee)(betting_market_id)(new_group_id)(new_payout_condition)(extensions) ) + FC_REFLECT_ENUM( graphene::chain::betting_market_resolution_type, (win)(not_win)(cancel)(BETTING_MARKET_RESOLUTION_COUNT) ) FC_REFLECT( graphene::chain::betting_market_group_resolve_operation::fee_parameters_type, (fee) ) diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index 97e74eb9..8f6d50ae 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -121,7 +121,9 @@ namespace graphene { namespace chain { tournament_join_operation, game_move_operation, tournament_payout_operation, // VIRTUAL - tournament_leave_operation + tournament_leave_operation, + betting_market_group_update_operation, + betting_market_update_operation > operation; /// @} // operations group diff --git a/libraries/chain/protocol/betting_market.cpp b/libraries/chain/protocol/betting_market.cpp index 553d546f..baec1545 100644 --- a/libraries/chain/protocol/betting_market.cpp +++ b/libraries/chain/protocol/betting_market.cpp @@ -40,11 +40,21 @@ void betting_market_group_create_operation::validate() const FC_ASSERT( fee.amount >= 0 ); } +void betting_market_group_update_operation::validate() const +{ + FC_ASSERT( fee.amount >= 0 ); +} + void betting_market_create_operation::validate() const { FC_ASSERT( fee.amount >= 0 ); } +void betting_market_update_operation::validate() const +{ + FC_ASSERT( fee.amount >= 0 ); +} + void betting_market_group_resolve_operation::validate() const { FC_ASSERT( fee.amount >= 0 ); diff --git a/tests/betting/betting_tests.cpp b/tests/betting/betting_tests.cpp index fe11184f..2b48c80d 100644 --- a/tests/betting/betting_tests.cpp +++ b/tests/betting/betting_tests.cpp @@ -180,147 +180,6 @@ BOOST_AUTO_TEST_CASE( peerplays_sport_create_test ) } FC_LOG_AND_RETHROW() } -BOOST_AUTO_TEST_CASE(peerplays_sport_update_test) -{ - try - { - ACTORS( (alice) ); - CREATE_ICE_HOCKEY_BETTING_MARKET(); - update_sport(ice_hockey.id, {{"en", "Hockey on Ice"}, {"zh_Hans", "冰"}, {"ja", "アイスホッケ"}}); - - transfer(account_id_type(), alice_id, asset(10000000)); - place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); - - BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000); - - } FC_LOG_AND_RETHROW() -} - -BOOST_AUTO_TEST_CASE(peerplays_event_group_update_test) -{ - try - { - ACTORS( (alice)(bob) ); - CREATE_ICE_HOCKEY_BETTING_MARKET(); - - transfer(account_id_type(), alice_id, asset(10000000)); - transfer(account_id_type(), bob_id, asset(10000000)); - - place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); - - internationalized_string_type n = {{"en", "IBM"}, {"zh_Hans", "國家冰球聯"}, {"ja", "ナショナルホッケーリー"}}; - const sport_object& ice_on_hockey = create_sport({{"en", "Hockey on Ice"}, {"zh_Hans", "冰球"}, {"ja", "アイスホッケー"}}); \ - - fc::optional name = n; - - object_id_type object_id = ice_on_hockey.id; - fc::optional sport_id = object_id; - - update_event_group(nhl.id, fc::optional(), name); - update_event_group(nhl.id, sport_id, fc::optional()); - update_event_group(nhl.id, sport_id, name); - - place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); - - 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); - - // caps win - resolve_betting_market_group(moneyline_betting_markets.id, - {{capitals_win_market.id, betting_market_resolution_type::win}, - {blackhawks_win_market.id, betting_market_resolution_type::cancel}}); - - - uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage; - uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100; - BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value)); - BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 + 2000000 - rake_value); - BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000); - - } FC_LOG_AND_RETHROW() -} - - -BOOST_AUTO_TEST_CASE(peerplays_event_update_test) -{ - try - { - ACTORS( (alice)(bob) ); - CREATE_ICE_HOCKEY_BETTING_MARKET(); - - transfer(account_id_type(), alice_id, asset(10000000)); - transfer(account_id_type(), bob_id, asset(10000000)); - - place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); - - internationalized_string_type n = {{"en", "Washington Capitals vs. Chicago Blackhawks"}, {"zh_Hans", "華盛頓首都隊/芝加哥黑"}, {"ja", "ワシントン・キャピタルズ/シカゴ・ブラックホーク"}}; - internationalized_string_type s = {{"en", "2017-18"}}; - - fc::optional empty; - fc::optional name = n; - fc::optional season = s; - fc::optional empty_object_id; - - update_event(capitals_vs_blackhawks.id, empty_object_id, name, empty); - update_event(capitals_vs_blackhawks.id, empty_object_id, empty, season); - update_event(capitals_vs_blackhawks.id, empty_object_id, name, season); - - const sport_object& ice_on_hockey = create_sport({{"en", "Hockey on Ice"}, {"zh_Hans", "冰球"}, {"ja", "アイスホッケー"}}); \ - const event_group_object& nhl2 = create_event_group({{"en", "NHL2"}, {"zh_Hans", "國家冰球聯盟"}, {"ja", "ナショナルホッケーリーグ"}}, ice_on_hockey.id); \ - object_id_type object_id = nhl2.id; - fc::optional event_group_id = object_id; - - update_event(capitals_vs_blackhawks.id, event_group_id , empty, empty); - - place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); - - 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); - - // caps win - resolve_betting_market_group(moneyline_betting_markets.id, - {{capitals_win_market.id, betting_market_resolution_type::win}, - {blackhawks_win_market.id, betting_market_resolution_type::cancel}}); - - - uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage; - uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100; - BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value)); - BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 + 2000000 - rake_value); - BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000); - - } FC_LOG_AND_RETHROW() -} - -BOOST_AUTO_TEST_CASE(peerplays_betting_market_rules_update_test) -{ - try - { - ACTORS( (alice) ); - CREATE_ICE_HOCKEY_BETTING_MARKET(); - - internationalized_string_type n = {{"en", "NHL Rules v1.1"}}; - internationalized_string_type d = {{"en", "The winner will be the team with the most points at the end of the game. The team with fewer points will not be the winner."}}; - - fc::optional empty; - fc::optional name = n; - fc::optional desc = d; - - update_betting_market_rules(betting_market_rules.id, name, empty); - update_betting_market_rules(betting_market_rules.id, empty, desc); - update_betting_market_rules(betting_market_rules.id, name, desc); - - transfer(account_id_type(), alice_id, asset(10000000)); - place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); - - BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000); - - //GRAPHENE_REQUIRE_THROW(update_betting_market_rules(betting_market_rules.id, empty, empty), fc::exception); - - } FC_LOG_AND_RETHROW() -} - - BOOST_AUTO_TEST_CASE( cancel_unmatched_in_betting_group_test ) { try @@ -595,6 +454,194 @@ struct simple_bet_test_fixture_2 : database_fixture { } }; +BOOST_FIXTURE_TEST_SUITE( update_tests, database_fixture ) + +BOOST_AUTO_TEST_CASE(sport_update_test) +{ + try + { + ACTORS( (alice) ); + CREATE_ICE_HOCKEY_BETTING_MARKET(); + update_sport(ice_hockey.id, {{"en", "Hockey on Ice"}, {"zh_Hans", "冰"}, {"ja", "アイスホッケ"}}); + + transfer(account_id_type(), alice_id, asset(10000000)); + place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); + + BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000); + + } FC_LOG_AND_RETHROW() +} + +BOOST_AUTO_TEST_CASE(event_group_update_test) +{ + try + { + ACTORS( (alice)(bob) ); + CREATE_ICE_HOCKEY_BETTING_MARKET(); + + transfer(account_id_type(), alice_id, asset(10000000)); + transfer(account_id_type(), bob_id, asset(10000000)); + + place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); + + internationalized_string_type n = {{"en", "IBM"}, {"zh_Hans", "國家冰球聯"}, {"ja", "ナショナルホッケーリー"}}; + const sport_object& ice_on_hockey = create_sport({{"en", "Hockey on Ice"}, {"zh_Hans", "冰球"}, {"ja", "アイスホッケー"}}); \ + + fc::optional name = n; + + fc::optional sport_id = ice_on_hockey.id; + + update_event_group(nhl.id, fc::optional(), name); + update_event_group(nhl.id, sport_id, fc::optional()); + update_event_group(nhl.id, sport_id, name); + + place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); + + 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); + + // caps win + resolve_betting_market_group(moneyline_betting_markets.id, + {{capitals_win_market.id, betting_market_resolution_type::win}, + {blackhawks_win_market.id, betting_market_resolution_type::cancel}}); + + + uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage; + uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100; + BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value)); + BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 + 2000000 - rake_value); + BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000); + + } FC_LOG_AND_RETHROW() +} + + +BOOST_AUTO_TEST_CASE(event_update_test) +{ + try + { + ACTORS( (alice)(bob) ); + CREATE_ICE_HOCKEY_BETTING_MARKET(); + + transfer(account_id_type(), alice_id, asset(10000000)); + transfer(account_id_type(), bob_id, asset(10000000)); + + place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); + + internationalized_string_type n = {{"en", "Washington Capitals vs. Chicago Blackhawks"}, {"zh_Hans", "華盛頓首都隊/芝加哥黑"}, {"ja", "ワシントン・キャピタルズ/シカゴ・ブラックホーク"}}; + internationalized_string_type s = {{"en", "2017-18"}}; + + fc::optional empty; + fc::optional name = n; + fc::optional season = s; + fc::optional empty_object_id; + + update_event(capitals_vs_blackhawks.id, empty_object_id, name, empty); + update_event(capitals_vs_blackhawks.id, empty_object_id, empty, season); + update_event(capitals_vs_blackhawks.id, empty_object_id, name, season); + + const sport_object& ice_on_hockey = create_sport({{"en", "Hockey on Ice"}, {"zh_Hans", "冰球"}, {"ja", "アイスホッケー"}}); \ + const event_group_object& nhl2 = create_event_group({{"en", "NHL2"}, {"zh_Hans", "國家冰球聯盟"}, {"ja", "ナショナルホッケーリーグ"}}, ice_on_hockey.id); \ + fc::optional event_group_id = nhl2.id; + + update_event(capitals_vs_blackhawks.id, event_group_id , empty, empty); + + place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); + + 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); + + // caps win + resolve_betting_market_group(moneyline_betting_markets.id, + {{capitals_win_market.id, betting_market_resolution_type::win}, + {blackhawks_win_market.id, betting_market_resolution_type::cancel}}); + + + uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage; + uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100; + BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value)); + BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 + 2000000 - rake_value); + BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000); + + } FC_LOG_AND_RETHROW() +} + +BOOST_AUTO_TEST_CASE(betting_market_rules_update_test) +{ + try + { + ACTORS( (alice) ); + CREATE_ICE_HOCKEY_BETTING_MARKET(); + + internationalized_string_type n = {{"en", "NHL Rules v1.1"}}; + internationalized_string_type d = {{"en", "The winner will be the team with the most points at the end of the game. The team with fewer points will not be the winner."}}; + + fc::optional empty; + fc::optional name = n; + fc::optional desc = d; + + update_betting_market_rules(betting_market_rules.id, name, empty); + update_betting_market_rules(betting_market_rules.id, empty, desc); + update_betting_market_rules(betting_market_rules.id, name, desc); + + transfer(account_id_type(), alice_id, asset(10000000)); + place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); + + BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000); + + } FC_LOG_AND_RETHROW() +} + +BOOST_AUTO_TEST_CASE(betting_market_group_update_test) +{ + try + { + ACTORS( (alice)(bob) ); + CREATE_ICE_HOCKEY_BETTING_MARKET(); + + transfer(account_id_type(), alice_id, asset(10000000)); + place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); + + fc::optional dempty; + fc::optional empty_object_id; + + internationalized_string_type d = {{"en", "Money line"}}; + fc::optional new_desc = d; + + const event_object& odd_vs_even = create_event({{"en", "Capitals vs. Blackhawks"}}, {{"en", "2017-18"}}, nhl.id); \ + fc::optional new_event = odd_vs_even.id; + + const betting_market_rules_object& new_betting_market_rules = create_betting_market_rules({{"en", "NHL Rules v2.0"}}, {{"en", "The winner will be the team with the most points at the end of the game. The team with fewer points will not be the winner."}}); + fc::optional new_rule = new_betting_market_rules.id; + + update_betting_market_group(moneyline_betting_markets.id, new_desc, empty_object_id, empty_object_id); + update_betting_market_group(moneyline_betting_markets.id, dempty, new_event, empty_object_id); + update_betting_market_group(moneyline_betting_markets.id, dempty, empty_object_id, new_rule); + update_betting_market_group(moneyline_betting_markets.id, new_desc, new_event, new_rule); + + transfer(account_id_type(), bob_id, asset(10000000)); + place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); + + 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); + + // caps win + resolve_betting_market_group(moneyline_betting_markets.id, + {{capitals_win_market.id, betting_market_resolution_type::win}, + {blackhawks_win_market.id, betting_market_resolution_type::cancel}}); + + + uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage; + uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100; + BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value)); + BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 + 2000000 - rake_value); + BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000); + + } FC_LOG_AND_RETHROW() +} + +BOOST_AUTO_TEST_SUITE_END() + // testing assertions BOOST_AUTO_TEST_SUITE(other_betting_tests) @@ -607,9 +654,12 @@ BOOST_AUTO_TEST_SUITE(other_betting_tests) } \ catch (exc_type& e) \ { \ + if (1) \ + { \ edump(("###")); \ edump((e.to_detail_string())); \ edump(("###")); \ + } \ FC_ASSERT(e.to_detail_string().find(reason) != \ std::string::npos, "expected error hasn't occured");\ } \ @@ -623,7 +673,7 @@ BOOST_FIXTURE_TEST_CASE( another_event_group_update_test, database_fixture) { try { - ACTORS( (alice)(bob)(nathan) ); + ACTORS( (alice)(bob) ); CREATE_ICE_HOCKEY_BETTING_MARKET(); transfer(account_id_type(), alice_id, asset(10000000)); @@ -632,12 +682,10 @@ BOOST_FIXTURE_TEST_CASE( another_event_group_update_test, database_fixture) place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 1000000 / 50 /* chain defaults to 2% fees */); internationalized_string_type n = {{"en", "IBM"}, {"zh_Hans", "國家冰球聯"}, {"ja", "ナショナルホッケーリー"}}; - const sport_object& ice_on_hockey = create_sport({{"en", "Hockey on Ice"}, {"zh_Hans", "冰球"}, {"ja", "アイスホッケー"}}); \ - fc::optional name = n; - object_id_type object_id = ice_on_hockey.id; - fc::optional sport_id = object_id; + const sport_object& ice_on_hockey = create_sport({{"en", "Hockey on Ice"}, {"zh_Hans", "冰球"}, {"ja", "アイスホッケー"}}); \ + fc::optional sport_id = ice_on_hockey.id; update_event_group(nhl.id, fc::optional(), name); update_event_group(nhl.id, sport_id, fc::optional()); @@ -652,14 +700,12 @@ BOOST_FIXTURE_TEST_CASE( another_event_group_update_test, database_fixture) TRY_EXPECT_THROW(try_update_event_group(nhl.id, fc::optional(), fc::optional()), fc::exception, "nothing to change"); // #! sport_id must refer to a sport_id_type - object_id = capitals_win_market.id; - sport_id = object_id; + sport_id = capitals_win_market.id; //GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, sport_id, fc::optional()), fc::exception); TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional()), fc::exception, "sport_id must refer to a sport_id_type"); // #! invalid sport specified - object_id = sport_id_type(13); - sport_id = object_id; + sport_id = sport_id_type(13); //GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, sport_id, fc::optional()), fc::exception); TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional()), fc::exception, "invalid sport specified"); diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index ca7d9530..d59aa0b8 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -1352,6 +1352,21 @@ const betting_market_group_object& database_fixture::create_betting_market_group return *betting_market_group_index.rbegin(); } FC_CAPTURE_AND_RETHROW( (event_id) ) } + +void database_fixture::update_betting_market_group(betting_market_group_id_type betting_market_group_id, + fc::optional description, + fc::optional event_id, + fc::optional rules_id) +{ try { + betting_market_group_update_operation betting_market_group_update_op; + betting_market_group_update_op.betting_market_group_id = betting_market_group_id; + betting_market_group_update_op.new_description = description; + betting_market_group_update_op.new_event_id = event_id; + betting_market_group_update_op.new_rules_id = rules_id; + process_operation_by_witnesses(betting_market_group_update_op); +} FC_CAPTURE_AND_RETHROW( (betting_market_group_id)(description)(event_id)(rules_id)) } + + const betting_market_object& database_fixture::create_betting_market(betting_market_group_id_type group_id, internationalized_string_type payout_condition) { try { betting_market_create_operation betting_market_create_op; @@ -1362,6 +1377,18 @@ const betting_market_object& database_fixture::create_betting_market(betting_mar return *betting_market_index.rbegin(); } FC_CAPTURE_AND_RETHROW( (payout_condition) ) } +void database_fixture::update_betting_market(betting_market_id_type betting_market_id, + fc::optional group_id, + fc::optional payout_condition) +{ try { + betting_market_update_operation betting_market_update_op; + betting_market_update_op.betting_market_id = betting_market_id; + betting_market_update_op.new_group_id = group_id; + betting_market_update_op.new_payout_condition = payout_condition; + process_operation_by_witnesses(betting_market_update_op); +} FC_CAPTURE_AND_RETHROW( (betting_market_id) (group_id) (payout_condition) ) } + + void database_fixture::place_bet(account_id_type bettor_id, betting_market_id_type betting_market_id, bet_type back_or_lay, asset amount_to_bet, bet_multiplier_type backer_multiplier, share_type amount_reserved_for_fees) { try { bet_place_operation bet_place_op; diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index 6064c638..08ad2833 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -297,16 +297,24 @@ struct database_fixture { fc::optional name, bool dont_set_is_proposed_trx = false); const event_object& create_event(internationalized_string_type name, internationalized_string_type season, event_group_id_type event_group_id); - void update_event(event_id_type event_id, + void update_event(event_id_type event_id, fc::optional event_group_id, fc::optional name, fc::optional season); - const betting_market_rules_object& create_betting_market_rules(internationalized_string_type name, internationalized_string_type description); - void update_betting_market_rules(betting_market_rules_id_type rules_id, + const betting_market_rules_object& create_betting_market_rules(internationalized_string_type name, internationalized_string_type description); + void update_betting_market_rules(betting_market_rules_id_type rules_id, fc::optional name, fc::optional description); const betting_market_group_object& create_betting_market_group(internationalized_string_type description, event_id_type event_id, betting_market_rules_id_type rules_id, asset_id_type asset_id); + void update_betting_market_group(betting_market_group_id_type betting_market_group_id, + fc::optional description, + fc::optional event_id, + fc::optional rules_id); + const betting_market_object& create_betting_market(betting_market_group_id_type group_id, internationalized_string_type payout_condition); + void update_betting_market(betting_market_id_type betting_market_id, + fc::optional group_id, + fc::optional payout_condition); void place_bet(account_id_type bettor_id, betting_market_id_type betting_market_id, bet_type back_or_lay, asset amount_to_bet, bet_multiplier_type backer_multiplier, share_type amount_reserved_for_fees); void resolve_betting_market_group(betting_market_group_id_type betting_market_group_id, std::map resolutions);