From 790bfe37048f3cadd114414d213ec1870c73c804 Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Sun, 9 Jul 2017 18:39:53 -0400 Subject: [PATCH] WIP Force all betting markets in a group to use the same asset_id for betting --- libraries/chain/betting_market_evaluator.cpp | 11 +- libraries/chain/db_bet.cpp | 210 ++++++++---------- .../graphene/chain/betting_market_object.hpp | 8 +- .../chain/protocol/betting_market.hpp | 20 +- .../wallet/include/graphene/wallet/wallet.hpp | 2 +- libraries/wallet/wallet.cpp | 4 +- tests/betting/betting_tests.cpp | 9 +- tests/common/database_fixture.cpp | 11 +- tests/common/database_fixture.hpp | 4 +- 9 files changed, 130 insertions(+), 149 deletions(-) diff --git a/libraries/chain/betting_market_evaluator.cpp b/libraries/chain/betting_market_evaluator.cpp index 8823e160..31691cf8 100644 --- a/libraries/chain/betting_market_evaluator.cpp +++ b/libraries/chain/betting_market_evaluator.cpp @@ -63,6 +63,8 @@ void_result betting_market_group_create_evaluator::do_evaluate(const betting_mar event_id = resolved_event_id; FC_ASSERT( db().find_object(event_id), "Invalid event specified" ); + FC_ASSERT( db().find_object(op.asset_id), "Invalid asset specified" ); + // 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.rules_id; @@ -84,6 +86,7 @@ object_id_type betting_market_group_create_evaluator::do_apply(const betting_mar betting_market_group_obj.event_id = event_id; betting_market_group_obj.rules_id = rules_id; betting_market_group_obj.description = op.description; + betting_market_group_obj.asset_id = op.asset_id; betting_market_group_obj.frozen = false; }); return new_betting_market_group.id; @@ -105,7 +108,6 @@ void_result betting_market_create_evaluator::do_evaluate(const betting_market_cr group_id = resolved_betting_market_group_id; FC_ASSERT( db().find_object(group_id), "Invalid betting_market_group specified" ); - // TODO: should we prevent creating multiple identical betting markets groups in a group (same asset and payout condition)? return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -115,7 +117,6 @@ object_id_type betting_market_create_evaluator::do_apply(const betting_market_cr db().create( [&]( betting_market_object& betting_market_obj ) { betting_market_obj.group_id = group_id; betting_market_obj.payout_condition = op.payout_condition; - betting_market_obj.asset_id = op.asset_id; }); return new_betting_market.id; } FC_CAPTURE_AND_RETHROW( (op) ) } @@ -127,12 +128,12 @@ void_result bet_place_evaluator::do_evaluate(const bet_place_operation& op) _betting_market = &op.betting_market_id(d); _betting_market_group = &_betting_market->group_id(d); - FC_ASSERT( op.amount_to_bet.asset_id == _betting_market->asset_id, + FC_ASSERT( op.amount_to_bet.asset_id == _betting_market_group->asset_id, "Asset type bet does not match the market's asset type" ); FC_ASSERT( !_betting_market_group->frozen, "Unable to place bets while the market is frozen" ); - _asset = &_betting_market->asset_id(d); + _asset = &_betting_market_group->asset_id(d); FC_ASSERT( is_authorized_asset( d, *fee_paying_account, *_asset ) ); const chain_parameters& current_params = d.get_global_properties().parameters; @@ -199,7 +200,7 @@ object_id_type bet_place_evaluator::do_apply(const bet_place_operation& op) bet_obj.back_or_lay = op.back_or_lay; }); - d.adjust_balance(fee_paying_account->id, asset(-_stake_plus_fees, _betting_market->asset_id)); + d.adjust_balance(fee_paying_account->id, asset(-_stake_plus_fees, _betting_market_group->asset_id)); bool bet_matched = d.place_bet(new_bet); diff --git a/libraries/chain/db_bet.cpp b/libraries/chain/db_bet.cpp index 39999b38..80a01e5d 100644 --- a/libraries/chain/db_bet.cpp +++ b/libraries/chain/db_bet.cpp @@ -43,9 +43,7 @@ void database::cancel_all_betting_markets_for_event(const event_object& event_ob //for each betting market group of event for (const betting_market_group_object& betting_market_group : boost::make_iterator_range(betting_market_group_index.equal_range(event_obj.id))) - { - resolve_betting_market_group(betting_market_group, {}); - } + resolve_betting_market_group(betting_market_group, {}); } void database::validate_betting_market_group_resolutions(const betting_market_group_object& betting_market_group, @@ -65,140 +63,118 @@ void database::validate_betting_market_group_resolutions(const betting_market_gr 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; + bool cancel = resolutions.size() == 0; - 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); + // we pay the rake fee to the dividend distribution account for the core asset, go ahead + // and look up that account now + fc::optional rake_account_id; + const asset_object& core_asset_obj = asset_id_type(0)(*this); + if (core_asset_obj.dividend_data_id) + { + const asset_dividend_data_object& core_asset_dividend_data_obj = (*core_asset_obj.dividend_data_id)(*this); + rake_account_id = core_asset_dividend_data_obj.dividend_distribution_account; + } - auto& index = get_index_type().indices().get(); - auto position_itr = index.lower_bound(std::make_tuple(betting_market.id)); + // collecting bettors and their positions + std::map > bettor_positions_map; - while (position_itr != index.end() && position_itr->betting_market_id == betting_market.id) - { - const betting_market_position_object& position = *position_itr; - ++position_itr; + auto& betting_market_index = get_index_type().indices().get(); + auto& position_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); - bettor_positions_map[position.bettor_id].push_back(&position); - } - } + auto position_itr = position_index.lower_bound(std::make_tuple(betting_market.id)); - // walking through bettors' positions and collecting winings and fees respecting asset_id - for (const auto& bettor_positions_pair: bettor_positions_map) - { + while (position_itr != position_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) + { uint16_t rake_fee_percentage = get_global_properties().parameters.betting_rake_fee_percentage; - std::map net_profits; - std::map payout_amounts; - std::map fees_collected; + share_type net_profits; + share_type payout_amounts; + share_type 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) { - betting_market_resolution_type resolution; - if (cancel) - { - resolution = betting_market_resolution_type::cancel; - } - else - { + 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; - net_profits[betting_market.asset_id] += position->pay_if_payout_condition; - net_profits[betting_market.asset_id] += position->pay_if_not_canceled; - net_profits[betting_market.asset_id] -= position->pay_if_canceled; - 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; - net_profits[betting_market.asset_id] += position->pay_if_not_payout_condition; - net_profits[betting_market.asset_id] += position->pay_if_not_canceled; - net_profits[betting_market.asset_id] -= position->pay_if_canceled; - 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); + switch (resolution) + { + case betting_market_resolution_type::win: + { + share_type total_payout = position->pay_if_payout_condition + position->pay_if_not_canceled; + payout_amounts += total_payout; + fees_collected += position->fees_collected; + net_profits += total_payout - position->pay_if_canceled; + break; + } + case betting_market_resolution_type::not_win: + { + share_type total_payout = position->pay_if_not_payout_condition + position->pay_if_not_canceled; + payout_amounts += total_payout; + fees_collected += position->fees_collected; + net_profits += total_payout - position->pay_if_canceled; + break; + } + case betting_market_resolution_type::cancel: + payout_amounts += position->pay_if_canceled + position->fees_collected; + break; + default: + continue; + } + remove(*position); } - std::vector winnings; - std::vector fees; - for (const auto& payout_amount_pair: payout_amounts) + // pay the fees to the dividend-distribution account if net profit + share_type rake_amount; + if (net_profits.value > 0 && rake_account_id) { - // pay the fees to the correct (dividend-distribution) account if net profit - asset_id_type asset_id = payout_amount_pair.first; - const asset_object & asset_obj = asset_id(*this); - optional dividend_id = asset_obj.dividend_data_id; - account_id_type rake_account_id; - if (dividend_id.valid()) - { - const asset_dividend_data_id_type& asset_dividend_data_id_= *dividend_id; - const asset_dividend_data_object& dividend_obj = asset_dividend_data_id_(*this); - rake_account_id = dividend_obj.dividend_distribution_account; - } - asset fee = fees_collected[asset_id]; - share_type net_profit = net_profits[asset_id]; - share_type payout_amount = payout_amount_pair.second; - share_type rake_amount = 0; - if (dividend_id.valid()) - { - if (net_profit.value > 0) - { - rake_amount = (fc::uint128_t(net_profit.value) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100).to_uint64(); - if (rake_amount.value) - { - // adjusting balance of dividend_distribution_account - asset rake(rake_amount, asset_id); - adjust_balance(rake_account_id, rake); - } - } - adjust_balance(rake_account_id, fee); - } - else - { - adjust_balance(account_id_type(), fee); - } - // pay winning - rake - asset payout = asset(payout_amount - rake_amount, asset_id); - adjust_balance(bettor_id, payout); - - winnings.push_back(payout); - fees.push_back(fee); + rake_amount = ((fc::uint128_t(net_profits.value) * rake_fee_percentage + GRAPHENE_100_PERCENT - 1) / GRAPHENE_100_PERCENT).to_uint64(); + if (rake_amount.value) + adjust_balance(*rake_account_id, asset(rake_amount, betting_market_group.asset_id)); } - push_applied_operation(betting_market_group_resolved_operation(bettor_id, - betting_market_group.id, - resolutions, - winnings, - fees)); - } + + if (fees_collected.value) + adjust_balance(*rake_account_id, asset(fees_collected, betting_market_group.asset_id)); - 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); + // pay winning - rake + adjust_balance(bettor_id, asset(payout_amounts - rake_amount, betting_market_group.asset_id)); + + push_applied_operation(betting_market_group_resolved_operation(bettor_id, + betting_market_group.id, + resolutions, + payout_amounts, + fees_collected)); + } + + 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_group); } diff --git a/libraries/chain/include/graphene/chain/betting_market_object.hpp b/libraries/chain/include/graphene/chain/betting_market_object.hpp index 71c3cd34..20b80afb 100644 --- a/libraries/chain/include/graphene/chain/betting_market_object.hpp +++ b/libraries/chain/include/graphene/chain/betting_market_object.hpp @@ -60,6 +60,8 @@ class betting_market_group_object : public graphene::db::abstract_object< bettin betting_market_rules_id_type rules_id; + asset_id_type asset_id; + bool frozen; }; @@ -74,8 +76,6 @@ class betting_market_object : public graphene::db::abstract_object< betting_mark internationalized_string_type description; internationalized_string_type payout_condition; - - asset_id_type asset_id; }; class bet_object : public graphene::db::abstract_object< bet_object > @@ -427,8 +427,8 @@ typedef generic_index resolutions; - std::vector winnings; - std::vector fees_paid; + + share_type winnings; // always the asset type of the betting market group + share_type fees_paid; // always the asset type of the betting market group asset fee; // unused in a virtual operation @@ -139,8 +143,8 @@ struct betting_market_group_resolved_operation : public base_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) : + share_type winnings, + share_type fees_paid) : bettor_id(bettor_id), betting_market_group_id(betting_market_group_id), resolutions(resolutions), @@ -296,11 +300,11 @@ FC_REFLECT( graphene::chain::betting_market_rules_create_operation, FC_REFLECT( graphene::chain::betting_market_group_create_operation::fee_parameters_type, (fee) ) FC_REFLECT( graphene::chain::betting_market_group_create_operation, - (fee)(description)(event_id)(extensions) ) + (fee)(description)(event_id)(rules_id)(asset_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)(asset_id)(extensions) ) + (fee)(group_id)(payout_condition)(extensions) ) FC_REFLECT_ENUM( graphene::chain::betting_market_resolution_type, (win)(not_win)(cancel)(BETTING_MARKET_RESOLUTION_COUNT) ) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 85737682..3cb4a7b5 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1561,6 +1561,7 @@ class wallet_api fc::time_point_sec expiration_time, internationalized_string_type description, event_id_type event_id, + asset_id_type asset_id, bool broadcast = false); signed_transaction propose_create_betting_market( @@ -1568,7 +1569,6 @@ class wallet_api fc::time_point_sec expiration_time, betting_market_group_id_type group_id, internationalized_string_type payout_condition, - asset_id_type asset_id, bool broadcast = false); signed_transaction place_bet( diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index ae47ac18..07abecf2 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -4561,6 +4561,7 @@ signed_transaction wallet_api::propose_create_betting_market_group( fc::time_point_sec expiration_time, internationalized_string_type description, event_id_type event_id, + asset_id_type asset_id, bool broadcast /*= false*/) { FC_ASSERT( !is_locked() ); @@ -4569,6 +4570,7 @@ signed_transaction wallet_api::propose_create_betting_market_group( betting_market_group_create_operation betting_market_group_create_op; betting_market_group_create_op.description = description; betting_market_group_create_op.event_id = event_id; + betting_market_group_create_op.asset_id = asset_id; proposal_create_operation prop_op; prop_op.expiration_time = expiration_time; @@ -4590,7 +4592,6 @@ signed_transaction wallet_api::propose_create_betting_market( fc::time_point_sec expiration_time, betting_market_group_id_type group_id, internationalized_string_type payout_condition, - asset_id_type asset_id, bool broadcast /*= false*/) { FC_ASSERT( !is_locked() ); @@ -4599,7 +4600,6 @@ signed_transaction wallet_api::propose_create_betting_market( betting_market_create_operation betting_market_create_op; betting_market_create_op.group_id = group_id; betting_market_create_op.payout_condition = payout_condition; - betting_market_create_op.asset_id = asset_id; proposal_create_operation prop_op; prop_op.expiration_time = expiration_time; diff --git a/tests/betting/betting_tests.cpp b/tests/betting/betting_tests.cpp index 7786e7e2..dda73b66 100644 --- a/tests/betting/betting_tests.cpp +++ b/tests/betting/betting_tests.cpp @@ -50,9 +50,9 @@ BOOST_FIXTURE_TEST_SUITE( betting_tests, database_fixture ) const event_group_object& nhl = create_event_group({{"en", "NHL"}, {"zh_Hans", "國家冰球聯盟"}, {"ja", "ナショナルホッケーリーグ"}}, ice_hockey.id); \ const event_object& capitals_vs_blackhawks = create_event({{"en", "Washington Capitals/Chicago Blackhawks"}, {"zh_Hans", "華盛頓首都隊/芝加哥黑鷹"}, {"ja", "ワシントン・キャピタルズ/シカゴ・ブラックホークス"}}, {{"en", "2016-17"}}, nhl.id); \ const betting_market_rules_object& betting_market_rules = create_betting_market_rules({{"en", "NHL Rules v1.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."}}); \ - const betting_market_group_object& moneyline_betting_markets = create_betting_market_group({{"en", "Moneyline"}}, capitals_vs_blackhawks.id, betting_market_rules.id); \ - const betting_market_object& capitals_win_market = create_betting_market(moneyline_betting_markets.id, {{"en", "Washington Capitals win"}}, asset_id_type()); \ - const betting_market_object& blackhawks_win_market = create_betting_market(moneyline_betting_markets.id, {{"en", "Chicago Blackhawks win"}}, asset_id_type()); + const betting_market_group_object& moneyline_betting_markets = create_betting_market_group({{"en", "Moneyline"}}, capitals_vs_blackhawks.id, betting_market_rules.id, asset_id_type()); \ + const betting_market_object& capitals_win_market = create_betting_market(moneyline_betting_markets.id, {{"en", "Washington Capitals win"}}); \ + const betting_market_object& blackhawks_win_market = create_betting_market(moneyline_betting_markets.id, {{"en", "Chicago Blackhawks win"}}); #if 0 BOOST_AUTO_TEST_CASE(generate_block) @@ -162,18 +162,17 @@ BOOST_AUTO_TEST_CASE( chained_market_create_test ) betting_market_group_create_operation betting_market_group_create_op; betting_market_group_create_op.description = {{"en", "Moneyline"}}; betting_market_group_create_op.event_id = object_id_type(relative_protocol_ids, 0, 2); + betting_market_group_create_op.asset_id = asset_id_type(); // operation 4 betting_market_create_operation caps_win_betting_market_create_op; caps_win_betting_market_create_op.group_id = object_id_type(relative_protocol_ids, 0, 3); caps_win_betting_market_create_op.payout_condition.insert(internationalized_string_type::value_type("en", "Washington Capitals win")); - caps_win_betting_market_create_op.asset_id = asset_id_type(); // operation 5 betting_market_create_operation blackhawks_win_betting_market_create_op; blackhawks_win_betting_market_create_op.group_id = object_id_type(relative_protocol_ids, 0, 4); blackhawks_win_betting_market_create_op.payout_condition.insert(internationalized_string_type::value_type("en", "Chicago Blackhawks win")); - blackhawks_win_betting_market_create_op.asset_id = asset_id_type(); proposal_create_operation proposal_op; diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 27431d1d..100c4d62 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -217,8 +217,9 @@ void database_fixture::verify_asset_supplies( const database& db ) for (const betting_market_position_object& o : db.get_index_type().indices()) { const betting_market_object& betting_market = o.betting_market_id(db); - total_balances[betting_market.asset_id] += o.pay_if_canceled; - total_balances[betting_market.asset_id] += o.fees_collected; + const betting_market_group_object& betting_market_group = betting_market.group_id(db); + total_balances[betting_market_group.asset_id] += o.pay_if_canceled; + total_balances[betting_market_group.asset_id] += o.fees_collected; } total_balances[asset_id_type()] += db.get_dynamic_global_properties().witness_budget; @@ -1174,23 +1175,23 @@ const betting_market_rules_object& database_fixture::create_betting_market_rules return *betting_market_rules_index.rbegin(); } FC_CAPTURE_AND_RETHROW( (name) ) } -const betting_market_group_object& database_fixture::create_betting_market_group(internationalized_string_type description, event_id_type event_id, betting_market_rules_id_type rules_id) +const betting_market_group_object& database_fixture::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) { try { betting_market_group_create_operation betting_market_group_create_op; betting_market_group_create_op.description = description; betting_market_group_create_op.event_id = event_id; betting_market_group_create_op.rules_id = rules_id; + betting_market_group_create_op.asset_id = asset_id; process_operation_by_witnesses(betting_market_group_create_op); const auto& betting_market_group_index = db.get_index_type().indices().get(); return *betting_market_group_index.rbegin(); } FC_CAPTURE_AND_RETHROW( (event_id) ) } -const betting_market_object& database_fixture::create_betting_market(betting_market_group_id_type group_id, internationalized_string_type payout_condition, asset_id_type asset_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; betting_market_create_op.group_id = group_id; betting_market_create_op.payout_condition = payout_condition; - betting_market_create_op.asset_id = asset_id; process_operation_by_witnesses(betting_market_create_op); const auto& betting_market_index = db.get_index_type().indices().get(); return *betting_market_index.rbegin(); diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index 826de672..ae6fe8ec 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -289,8 +289,8 @@ struct database_fixture { const event_group_object& create_event_group(internationalized_string_type name, sport_id_type sport_id); const event_object& create_event(internationalized_string_type name, internationalized_string_type season, event_group_id_type event_group_id); const betting_market_rules_object& create_betting_market_rules(internationalized_string_type name, internationalized_string_type 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); - const betting_market_object& create_betting_market(betting_market_group_id_type group_id, internationalized_string_type payout_condition, asset_id_type asset_id); + 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); + const betting_market_object& create_betting_market(betting_market_group_id_type group_id, internationalized_string_type 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);