diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index 3038c8f7..7a5370dc 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -209,7 +209,7 @@ struct get_impacted_account_visitor void operator()( const event_create_operation& op ) {} void operator()( const betting_market_group_create_operation& op ) {} void operator()( const betting_market_create_operation& op ) {} - void operator()( const betting_market_resolve_operation& op ) {} + void operator()( const betting_market_group_resolve_operation& op ) {} void operator()( const bet_place_operation& op ) { _impacted.insert( op.bettor_id ); @@ -226,7 +226,7 @@ struct get_impacted_account_visitor { _impacted.insert( op.bettor_id ); } - void operator()( const betting_market_resolved_operation& op ) + void operator()( const betting_market_group_resolved_operation& op ) { _impacted.insert( op.bettor_id ); } diff --git a/libraries/chain/betting_market_evaluator.cpp b/libraries/chain/betting_market_evaluator.cpp index 98173cfe..d55042e0 100644 --- a/libraries/chain/betting_market_evaluator.cpp +++ b/libraries/chain/betting_market_evaluator.cpp @@ -191,17 +191,19 @@ void_result bet_cancel_evaluator::do_apply(const bet_cancel_operation& op) return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } -void_result betting_market_resolve_evaluator::do_evaluate(const betting_market_resolve_operation& op) +void_result betting_market_group_resolve_evaluator::do_evaluate(const betting_market_group_resolve_operation& op) { try { const database& d = db(); - _betting_market = &op.betting_market_id(d); + _betting_market_group = &op.betting_market_group_id(d); + db().validate_betting_market_group_resolutions(*_betting_market_group, op.resolutions); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } -void_result betting_market_resolve_evaluator::do_apply(const betting_market_resolve_operation& op) +void_result betting_market_group_resolve_evaluator::do_apply(const betting_market_group_resolve_operation& op) { try { - db().resolve_betting_market(*_betting_market, op.resolution); + db().resolve_betting_market_group(*_betting_market_group, op.resolutions); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } + } } // graphene::chain diff --git a/libraries/chain/db_bet.cpp b/libraries/chain/db_bet.cpp index 2c5c9374..776640d9 100644 --- a/libraries/chain/db_bet.cpp +++ b/libraries/chain/db_bet.cpp @@ -44,64 +44,126 @@ void database::cancel_all_betting_markets_for_event(const event_object& event_ob for (const betting_market_group_object& betting_market_group : boost::make_iterator_range(betting_market_group_index.equal_range(event_obj.id))) { - //for each betting market in the betting market group - auto betting_market_itr = betting_market_index.lower_bound(betting_market_group.id); - while (betting_market_itr != betting_market_index.end() && - betting_market_itr->group_id == betting_market_group.id) - { - auto old_betting_market_itr = betting_market_itr; - ++betting_market_itr; - resolve_betting_market(*old_betting_market_itr, betting_market_resolution_type::cancel); - } + resolve_betting_market_group(betting_market_group, {}); } - //TODO: should we remove market groups once all their markets are resolved? } -void database::resolve_betting_market(const betting_market_object& betting_market, - betting_market_resolution_type resolution) +void database::validate_betting_market_group_resolutions(const betting_market_group_object& betting_market_group, + const std::map& resolutions) { - cancel_all_unmatched_bets_on_betting_market(betting_market); + auto& betting_market_index = get_index_type().indices().get(); + auto betting_market_itr = betting_market_index.lower_bound(betting_market_group.id); + while (betting_market_itr != betting_market_index.end() && betting_market_itr->group_id == betting_market_group.id) + { + const betting_market_object& betting_market = *betting_market_itr; + // every betting market in the group tied with resolution + assert(resolutions.count(betting_market.id)); + ++betting_market_itr; + } +} - auto& index = get_index_type().indices().get(); - auto position_itr = index.lower_bound(std::make_tuple(betting_market.id)); - while (position_itr != index.end() && - position_itr->betting_market_id == betting_market.id) - { - const betting_market_position_object& position = *position_itr; - ++position_itr; +void database::resolve_betting_market_group(const betting_market_group_object& betting_market_group, + const std::map& resolutions) +{ + bool cancel = resolutions.size() == 0; + // collecting bettors and their positions + std::map > bettor_positions_map; - share_type payout_amount = 0; - switch (resolution) + auto& betting_market_index = get_index_type().indices().get(); + auto betting_market_itr = betting_market_index.lower_bound(betting_market_group.id); + while (betting_market_itr != betting_market_index.end() && betting_market_itr->group_id == betting_market_group.id) + { + const betting_market_object& betting_market = *betting_market_itr; + ++betting_market_itr; + cancel_all_unmatched_bets_on_betting_market(betting_market); + + auto& index = get_index_type().indices().get(); + auto position_itr = index.lower_bound(std::make_tuple(betting_market.id)); + + while (position_itr != index.end() && position_itr->betting_market_id == betting_market.id) + { + const betting_market_position_object& position = *position_itr; + ++position_itr; + + bettor_positions_map[position.bettor_id].push_back(&position); + } + } + + // walking through bettors' positions and collecting winings and fees respecting asset_id + for (const auto& bettor_positions_pair: bettor_positions_map) + { + std::map payout_amounts; + std::map fees_collected; + account_id_type bettor_id = bettor_positions_pair.first; + const std::vector& bettor_positions = bettor_positions_pair.second; + + for (const betting_market_position_object* position : bettor_positions) { - case betting_market_resolution_type::win: - payout_amount += position.pay_if_payout_condition; - payout_amount += position.pay_if_not_canceled; - //TODO: pay the fees to the correct (dividend-distribution) account - adjust_balance(account_id_type(), asset(position.fees_collected, betting_market.asset_id)); - break; - case betting_market_resolution_type::not_win: - payout_amount += position.pay_if_not_payout_condition; - payout_amount += position.pay_if_not_canceled; - //TODO: pay the fees to the correct (dividend-distribution) account - adjust_balance(account_id_type(), asset(position.fees_collected, betting_market.asset_id)); - break; - case betting_market_resolution_type::cancel: - payout_amount += position.pay_if_canceled; - payout_amount += position.fees_collected; - break; + betting_market_resolution_type resolution; + if (cancel) + { + resolution = betting_market_resolution_type::cancel; + } + else + { + // checked in evaluator, should never happen, see above + assert(resolutions.count(position->betting_market_id)); + resolution = resolutions.at(position->betting_market_id); + } + const betting_market_object& betting_market = position->betting_market_id(*this); + + switch (resolution) + { + case betting_market_resolution_type::win: + payout_amounts[betting_market.asset_id] += position->pay_if_payout_condition; + payout_amounts[betting_market.asset_id] += position->pay_if_not_canceled; + fees_collected[betting_market.asset_id] += position->fees_collected; + break; + case betting_market_resolution_type::not_win: + payout_amounts[betting_market.asset_id] += position->pay_if_not_payout_condition; + payout_amounts[betting_market.asset_id] += position->pay_if_not_canceled; + fees_collected[betting_market.asset_id] += position->fees_collected; + break; + case betting_market_resolution_type::cancel: + payout_amounts[betting_market.asset_id] += position->pay_if_canceled; + payout_amounts[betting_market.asset_id] += position->fees_collected; + break; + default: + continue; + } + remove(*position); } - adjust_balance(position.bettor_id, asset(payout_amount, betting_market.asset_id)); + std::vector winnings; + std::vector fees; + for (const auto& payout_amount_pair: payout_amounts) + { + asset payout = asset(payout_amount_pair.second, payout_amount_pair.first); + adjust_balance(bettor_id, payout); + winnings.push_back(payout); + } + for (const auto& fee_collected_pair: fees_collected) + { + // TODO : pay the fees to the correct (dividend-distribution) account + asset fee = asset(fee_collected_pair.second, fee_collected_pair.first); + adjust_balance(account_id_type(), fee); + fees.push_back(fee); + } + push_applied_operation(betting_market_group_resolved_operation(bettor_id, + betting_market_group.id, + resolutions, + winnings, + fees)); + } - push_applied_operation(betting_market_resolved_operation(position.bettor_id, - betting_market.id, - resolution, - payout_amount, - position.fees_collected)); - - remove(position); + betting_market_itr = betting_market_index.lower_bound(betting_market_group.id); + while (betting_market_itr != betting_market_index.end() && betting_market_itr->group_id == betting_market_group.id) + { + const betting_market_object& betting_market = *betting_market_itr; + ++betting_market_itr; + remove(betting_market); } - remove(betting_market); + remove(betting_market_group); } #if 0 diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index e37578aa..a57af12d 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -218,7 +218,7 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); - register_evaluator(); + register_evaluator(); } void database::initialize_indexes() diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index a03c7c7b..a3660bc9 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -192,8 +192,8 @@ struct get_impacted_account_visitor void operator()(const betting_market_group_create_operation&){} void operator()(const betting_market_create_operation&){} void operator()(const bet_place_operation&){} - void operator()(const betting_market_resolve_operation&){} - void operator()(const betting_market_resolved_operation &){} + void operator()(const betting_market_group_resolve_operation&){} + void operator()(const betting_market_group_resolved_operation &){} void operator()(const bet_matched_operation &){} void operator()(const bet_cancel_operation&){} void operator()(const bet_canceled_operation &){} diff --git a/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp b/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp index bae04611..f25e54f6 100644 --- a/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/betting_market_evaluator.hpp @@ -76,15 +76,16 @@ namespace graphene { namespace chain { const bet_object* _bet_to_cancel; }; - class betting_market_resolve_evaluator : public evaluator + class betting_market_group_resolve_evaluator : public evaluator { public: - typedef betting_market_resolve_operation operation_type; + typedef betting_market_group_resolve_operation operation_type; - void_result do_evaluate( const betting_market_resolve_operation& o ); - void_result do_apply( const betting_market_resolve_operation& o ); + void_result do_evaluate( const betting_market_group_resolve_operation& o ); + void_result do_apply( const betting_market_group_resolve_operation& o ); private: - const betting_market_object* _betting_market; + const betting_market_group_object* _betting_market_group; }; + } } // graphene::chain diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index a37449c0..b06c60b9 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -375,8 +375,10 @@ namespace graphene { namespace chain { void cancel_bet(const bet_object& bet, bool create_virtual_op = true); void cancel_all_unmatched_bets_on_betting_market(const betting_market_object& betting_market); void cancel_all_betting_markets_for_event(const event_object&); - void resolve_betting_market(const betting_market_object& betting_market, - betting_market_resolution_type resolution); + void validate_betting_market_group_resolutions(const betting_market_group_object& betting_market_group, + const std::map& resolutions); + void resolve_betting_market_group(const betting_market_group_object& betting_market_group, + const std::map& resolutions); /** * @brief Process a new bet * @param new_bet_object The new bet to process diff --git a/libraries/chain/include/graphene/chain/protocol/betting_market.hpp b/libraries/chain/include/graphene/chain/protocol/betting_market.hpp index 5bedf242..5996f4f8 100644 --- a/libraries/chain/include/graphene/chain/protocol/betting_market.hpp +++ b/libraries/chain/include/graphene/chain/protocol/betting_market.hpp @@ -95,14 +95,14 @@ enum class betting_market_resolution_type { BETTING_MARKET_RESOLUTION_COUNT }; -struct betting_market_resolve_operation : public base_operation +struct betting_market_group_resolve_operation : public base_operation { struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; asset fee; - betting_market_id_type betting_market_id; + betting_market_group_id_type betting_market_group_id; - betting_market_resolution_type resolution; + std::map resolutions; extensions_type extensions; @@ -110,30 +110,32 @@ struct betting_market_resolve_operation : public base_operation void validate()const; }; -struct betting_market_resolved_operation : public base_operation +struct betting_market_group_resolved_operation : public base_operation { struct fee_parameters_type {}; account_id_type bettor_id; - betting_market_id_type betting_market_id; - betting_market_resolution_type resolution; - asset winnings; - share_type fees_paid; + betting_market_group_id_type betting_market_group_id; + std::map resolutions; + std::vector winnings; + std::vector fees_paid; asset fee; // unused in a virtual operation - betting_market_resolved_operation() {} - betting_market_resolved_operation(account_id_type bettor_id, - betting_market_id_type betting_market_id, - betting_market_resolution_type resolution, - asset winnings, - share_type fees_paid) : + betting_market_group_resolved_operation() {} + betting_market_group_resolved_operation(account_id_type bettor_id, + betting_market_group_id_type betting_market_group_id, + const std::map& resolutions, + std::vector winnings, + std::vector fees_paid) : bettor_id(bettor_id), - betting_market_id(betting_market_id), - resolution(resolution), + betting_market_group_id(betting_market_group_id), + resolutions(resolutions), winnings(winnings), fees_paid(fees_paid) - {} + { + // TODO ? + } account_id_type fee_payer()const { return bettor_id; } void validate()const { FC_ASSERT(false, "virtual operation"); } @@ -279,13 +281,13 @@ FC_REFLECT( graphene::chain::betting_market_create_operation, FC_REFLECT_ENUM( graphene::chain::betting_market_resolution_type, (win)(not_win)(cancel)(BETTING_MARKET_RESOLUTION_COUNT) ) -FC_REFLECT( graphene::chain::betting_market_resolve_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::betting_market_resolve_operation, - (fee)(betting_market_id)(resolution)(extensions) ) +FC_REFLECT( graphene::chain::betting_market_group_resolve_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::betting_market_group_resolve_operation, + (fee)(betting_market_group_id)(resolutions)(extensions) ) -FC_REFLECT( graphene::chain::betting_market_resolved_operation::fee_parameters_type, ) -FC_REFLECT( graphene::chain::betting_market_resolved_operation, - (bettor_id)(betting_market_id)(resolution)(winnings)(fees_paid)(fee) ) +FC_REFLECT( graphene::chain::betting_market_group_resolved_operation::fee_parameters_type, ) +FC_REFLECT( graphene::chain::betting_market_group_resolved_operation, + (bettor_id)(betting_market_group_id)(resolutions)(winnings)(fees_paid)(fee) ) FC_REFLECT_ENUM( graphene::chain::bet_type, (back)(lay) ) FC_REFLECT( graphene::chain::bet_place_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 8ba64fb7..097ad854 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -104,8 +104,8 @@ namespace graphene { namespace chain { betting_market_group_create_operation, betting_market_create_operation, bet_place_operation, - betting_market_resolve_operation, - betting_market_resolved_operation, // VIRTUAL + betting_market_group_resolve_operation, + betting_market_group_resolved_operation, // VIRTUAL bet_matched_operation, // VIRTUAL bet_cancel_operation, bet_canceled_operation // VIRTUAL diff --git a/libraries/chain/protocol/betting_market.cpp b/libraries/chain/protocol/betting_market.cpp index b0578c53..405e5c16 100644 --- a/libraries/chain/protocol/betting_market.cpp +++ b/libraries/chain/protocol/betting_market.cpp @@ -35,9 +35,9 @@ void betting_market_create_operation::validate() const FC_ASSERT( fee.amount >= 0 ); } -void betting_market_resolve_operation::validate() const +void betting_market_group_resolve_operation::validate() const { - FC_ASSERT( fee.amount >= 0 ); + //FC_ASSERT( fee.amount >= 0 ); } void bet_place_operation::validate() const diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 13d29f9f..84b17dea 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1559,11 +1559,11 @@ class wallet_api share_type amount_reserved_for_fees, bool broadcast = false); - signed_transaction propose_resolve_betting_market( + signed_transaction propose_resolve_betting_market_group( const string& proposing_account, fc::time_point_sec expiration_time, - betting_market_id_type betting_market_id, - betting_market_resolution_type resolution, + betting_market_group_id_type betting_market_group_id, + const std::map& resolutions, bool broadcast = false); void dbg_make_uia(string creator, string symbol); @@ -1779,6 +1779,6 @@ FC_API( graphene::wallet::wallet_api, (propose_create_betting_market_group) (propose_create_betting_market) (place_bet) - (propose_resolve_betting_market) + (propose_resolve_betting_market_group) (get_order_book) ) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 0681c649..adadf868 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -4577,25 +4577,25 @@ signed_transaction wallet_api::place_bet( return my->sign_transaction(tx, broadcast); } -signed_transaction wallet_api::propose_resolve_betting_market( +signed_transaction wallet_api::propose_resolve_betting_market_group( const string& proposing_account, fc::time_point_sec expiration_time, - betting_market_id_type betting_market_id, - betting_market_resolution_type resolution, + betting_market_group_id_type betting_market_group_id, + const std::map& resolutions, bool broadcast /*= false*/) { FC_ASSERT( !is_locked() ); const chain_parameters& current_params = get_global_properties().parameters; - betting_market_resolve_operation betting_market_resolve_op; - betting_market_resolve_op.betting_market_id = betting_market_id; - betting_market_resolve_op.resolution = resolution; + betting_market_group_resolve_operation betting_market_group_resolve_op; + betting_market_group_resolve_op.betting_market_group_id = betting_market_group_id; + betting_market_group_resolve_op.resolutions = resolutions; proposal_create_operation prop_op; prop_op.expiration_time = expiration_time; prop_op.review_period_seconds = current_params.committee_proposal_review_period; prop_op.fee_paying_account = get_account(proposing_account).id; - prop_op.proposed_ops.emplace_back( betting_market_resolve_op ); + prop_op.proposed_ops.emplace_back( betting_market_group_resolve_op ); current_params.current_fees->set_fee( prop_op.proposed_ops.back().op ); signed_transaction tx; diff --git a/tests/betting/betting_tests.cpp b/tests/betting/betting_tests.cpp index 7ca41dac..c8d56b6c 100644 --- a/tests/betting/betting_tests.cpp +++ b/tests/betting/betting_tests.cpp @@ -114,7 +114,9 @@ BOOST_AUTO_TEST_CASE( peerplays_sport_create_test ) BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000); // caps win - resolve_betting_market(capitals_win_market.id, betting_market_resolution_type::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}}); BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 + 2000000); BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000); @@ -253,6 +255,9 @@ BOOST_AUTO_TEST_SUITE_END() // the result in all three possible outcomes struct simple_bet_test_fixture : database_fixture { betting_market_id_type capitals_win_betting_market_id; + betting_market_id_type blackhawks_win_betting_market_id; + betting_market_group_id_type moneyline_betting_markets_id; + simple_bet_test_fixture() { ACTORS( (alice)(bob) ); @@ -271,6 +276,8 @@ struct simple_bet_test_fixture : database_fixture { place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(1100, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 22); capitals_win_betting_market_id = capitals_win_market.id; + blackhawks_win_betting_market_id = blackhawks_win_market.id; + moneyline_betting_markets_id = moneyline_betting_markets.id; } }; @@ -280,7 +287,9 @@ BOOST_AUTO_TEST_CASE( win ) { try { - resolve_betting_market(capitals_win_betting_market_id, betting_market_resolution_type::win); + resolve_betting_market_group(moneyline_betting_markets_id, + {{capitals_win_betting_market_id, betting_market_resolution_type::win}, + {blackhawks_win_betting_market_id, betting_market_resolution_type::cancel}}); GET_ACTOR(alice); GET_ACTOR(bob); @@ -296,7 +305,9 @@ BOOST_AUTO_TEST_CASE( not_win ) { try { - resolve_betting_market(capitals_win_betting_market_id, betting_market_resolution_type::not_win); + resolve_betting_market_group(moneyline_betting_markets_id, + {{capitals_win_betting_market_id, betting_market_resolution_type::not_win}, + {blackhawks_win_betting_market_id, betting_market_resolution_type::cancel}}); GET_ACTOR(alice); GET_ACTOR(bob); @@ -312,7 +323,9 @@ BOOST_AUTO_TEST_CASE( cancel ) { try { - resolve_betting_market(capitals_win_betting_market_id, betting_market_resolution_type::cancel); + resolve_betting_market_group(moneyline_betting_markets_id, + {{capitals_win_betting_market_id, betting_market_resolution_type::cancel}, + {blackhawks_win_betting_market_id, betting_market_resolution_type::cancel}}); GET_ACTOR(alice); GET_ACTOR(bob); diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 308512d9..04fb62ec 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -1198,13 +1198,14 @@ const betting_market_object& database_fixture::create_betting_market(betting_mar trx.operations.clear(); } FC_CAPTURE_AND_RETHROW( (bettor_id)(back_or_lay)(amount_to_bet) ) } -void database_fixture::resolve_betting_market(betting_market_id_type betting_market_id, betting_market_resolution_type resolution) +void database_fixture::resolve_betting_market_group(betting_market_group_id_type betting_market_group_id, + std::map resolutions) { try { - betting_market_resolve_operation betting_market_resolve_op; - betting_market_resolve_op.betting_market_id = betting_market_id; - betting_market_resolve_op.resolution = resolution; - process_operation_by_witnesses(betting_market_resolve_op); -} FC_CAPTURE_AND_RETHROW( (betting_market_id)(resolution) ) } + betting_market_group_resolve_operation betting_market_group_resolve_op; + betting_market_group_resolve_op.betting_market_group_id = betting_market_group_id; + betting_market_group_resolve_op.resolutions = resolutions; + process_operation_by_witnesses(betting_market_group_resolve_op); +} FC_CAPTURE_AND_RETHROW( (betting_market_group_id)(resolutions) ) } namespace test { diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index e7041eea..de800fe0 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -290,7 +290,7 @@ struct database_fixture { const betting_market_object& create_betting_market(betting_market_group_id_type group_id, internationalized_string_type payout_condition, asset_id_type asset_id); 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(betting_market_id_type betting_market_id, betting_market_resolution_type resolution); + void resolve_betting_market_group(betting_market_group_id_type betting_market_group_id, std::map resolutions); }; namespace test {