3 #include <boost/range/algorithm/set_algorithm.hpp>
4 #include <boost/range/algorithm/find_if.hpp>
18 #include <scorum/utils/range/unwrap_ref_wrapper_adaptor.hpp>
19 #include <scorum/utils/algorithm/foreach_mut.hpp>
21 #include <scorum/utils/collect_range_adaptor.hpp>
36 : _account_svc(account_svc)
37 , _virt_op_emitter(virt_op_emitter)
38 , _betting_property_dba(betting_property_dba)
39 , _matched_bet_dba(matched_bet_dba)
40 , _pending_bet_dba(pending_bet_dba)
42 , _dprop_dba(dprop_dba)
43 , _uuid_hist_dba(uuid_hist_dba)
51 return _betting_property_dba.get().moderator == account_name;
53 FC_CAPTURE_LOG_AND_RETHROW((account_name))
64 const auto& better_acc = _account_svc.
get_account(better);
65 FC_ASSERT(better_acc.balance >= stake,
"Insufficient funds");
70 o.game_uuid = game_uuid;
72 o.data.
uuid = bet_uuid;
75 o.data.created = _dprop_dba.get().time;
76 o.data.better = better;
78 o.data.wincase = wincase;
81 _dprop_dba.update([&](
auto& obj) { obj.betting_stats.pending_bets_volume += stake; });
90 auto matched_bets = _matched_bet_dba.get_range_by<by_game_uuid_market>(game_uuid);
91 FC_ASSERT(matched_bets.empty(),
"Cannot cancel game which has associated bets");
93 auto pending_bets = _matched_bet_dba.get_range_by<by_game_uuid_market>(game_uuid);
94 FC_ASSERT(pending_bets.empty(),
"Cannot cancel game which has associated bets");
96 const auto& game = _game_dba.get_by<by_uuid>(game_uuid);
97 _game_dba.remove(game);
110 auto lower = std::make_tuple(game_uuid, created_after);
111 auto upper = game_uuid;
112 auto matched_bets = _matched_bet_dba.get_range_by<by_game_uuid_created>(lower <=
_x,
_x <= upper);
113 auto pending_bets = _pending_bet_dba.get_range_by<by_game_uuid_created>(lower <=
_x,
_x <= upper);
119 if (matched_bet.bet1_data.created >= created_after)
120 return_bet(matched_bet.bet1_data, game_uuid);
122 restore_pending_bet(matched_bet.bet1_data, game_uuid);
124 if (matched_bet.bet2_data.created >= created_after)
125 return_bet(matched_bet.bet2_data, game_uuid);
127 restore_pending_bet(matched_bet.bet2_data, game_uuid);
130 _matched_bet_dba.remove_all(matched_bets);
145 auto pending_bets = _pending_bet_dba.get_range_by<by_game_uuid_market>(game_uuid);
147 std::vector<std::reference_wrapper<const pending_bet_object>> filtered_pending_bets;
148 boost::set_intersection(pending_bets, cancelled_markets, std::back_inserter(filtered_pending_bets), less{});
152 auto matched_bets = _matched_bet_dba.get_range_by<by_game_uuid_market>(game_uuid);
154 std::vector<std::reference_wrapper<const matched_bet_object>> filtered_matched_bets;
155 boost::set_intersection(matched_bets, cancelled_markets, std::back_inserter(filtered_matched_bets), less{});
162 const auto& pending_bet = _pending_bet_dba.get_by<by_id>(id);
169 auto pending_bets = _pending_bet_dba.get_range_by<by_game_uuid_market>(game_uuid);
176 auto pending_bets = _pending_bet_dba.get_range_by<by_game_uuid_kind>(std::make_tuple(game_uuid, kind));
190 auto matched_bets = _matched_bet_dba.get_range_by<by_game_uuid_market>(game_uuid);
198 cancel_matched_bet(bet, game_uuid);
206 push_pending_bet_cancelled_op(bet.
data, game_uuid);
208 _dprop_dba.update([&](
auto& o) { o.betting_stats.pending_bets_volume -= bet.
data.
stake; });
210 _pending_bet_dba.remove(bet);
213 void betting_service::cancel_matched_bet(
const matched_bet_object& bet,
uuid_type game_uuid)
215 return_bet(bet.bet1_data, game_uuid);
216 return_bet(bet.bet2_data, game_uuid);
218 _matched_bet_dba.remove(bet);
221 void betting_service::return_bet(
const bet_data& bet,
uuid_type game_uuid)
225 push_matched_bet_cancelled_op(bet, game_uuid);
227 _dprop_dba.update([&](
auto& o) { o.betting_stats.matched_bets_volume -= bet.stake; });
230 void betting_service::restore_pending_bet(
const bet_data& bet,
uuid_type game_uuid)
232 auto is_exists = _pending_bet_dba.is_exists_by<by_uuid>(bet.uuid);
235 const auto& pending_bet = _pending_bet_dba.get_by<by_uuid>(bet.uuid);
236 auto old_stake = pending_bet.data.stake;
238 _pending_bet_dba.update(pending_bet, [&](pending_bet_object& o) { o.data.stake += bet.stake; });
241 bet_updated_operation{ game_uuid, bet.better, bet.uuid, old_stake, pending_bet.data.stake });
245 _pending_bet_dba.create([&](pending_bet_object& o) {
246 o.game_uuid = game_uuid;
251 _virt_op_emitter.
push_virtual_operation(bet_restored_operation{ game_uuid, bet.better, bet.uuid, bet.stake });
254 _dprop_dba.update([&](
auto& o) {
255 o.betting_stats.pending_bets_volume += bet.stake;
256 o.betting_stats.matched_bets_volume -= bet.stake;
260 void betting_service::push_matched_bet_cancelled_op(
const bet_data& bet,
uuid_type game_uuid)
263 bet_cancelled_operation{ game_uuid, bet.better, bet.uuid, bet.stake, bet_kind::matched });
266 void betting_service::push_pending_bet_cancelled_op(
const bet_data& bet,
uuid_type game_uuid)
269 bet_cancelled_operation{ game_uuid, bet.better, bet.uuid, bet.stake, bet_kind::pending });
void cancel_pending_bets(uuid_type game_uuid) override
const pending_bet_object & create_pending_bet(const account_name_type &better, const protocol::asset &stake, protocol::odds odds, const protocol::wincase_type &wincase, uuid_type game_uuid, uuid_type bet_uuid, pending_bet_kind kind) override
void cancel_matched_bets(uuid_type game_uuid) override
bool is_betting_moderator(const account_name_type &account_name) const override
void cancel_pending_bet(pending_bet_id_type id) override
void cancel_bets(uuid_type game_uuid) override
void cancel_game(uuid_type game_uuid) override
betting_service(account_service_i &, database_virtual_operations_emmiter_i &, dba::db_accessor< betting_property_object > &, dba::db_accessor< matched_bet_object > &, dba::db_accessor< pending_bet_object > &, dba::db_accessor< game_object > &, dba::db_accessor< dynamic_global_property_object > &, dba::db_accessor< bet_uuid_history_object > &)
const param_placeholder _x
market_type create_market(const wincase_type &wincase)
fc::fixed_string_16 account_name_type
fc::static_variant< result_home::yes, result_home::no, result_draw::yes, result_draw::no, result_away::yes, result_away::no, round_home::yes, round_home::no, handicap::over, handicap::under, correct_score_home::yes, correct_score_home::no, correct_score_draw::yes, correct_score_draw::no, correct_score_away::yes, correct_score_away::no, correct_score::yes, correct_score::no, goal_home::yes, goal_home::no, goal_both::yes, goal_both::no, goal_away::yes, goal_away::no, total::over, total::under, total_goals_home::over, total_goals_home::under, total_goals_away::over, total_goals_away::under > wincase_type
fc::static_variant< result_home, result_draw, result_away, round_home, handicap, correct_score_home, correct_score_draw, correct_score_away, correct_score, goal_home, goal_both, goal_away, total, total_goals_home, total_goals_away > market_type
boost::uuids::uuid uuid_type
virtual const account_object & get_account(const account_name_type &) const =0
virtual void increase_balance(const account_object &account, const asset &amount)=0
virtual void decrease_balance(const account_object &account, const asset &amount)=0
virtual ~betting_service_i()
virtual void push_virtual_operation(const operation &op)=0