Merge branch 'betting-merge' of https://bitbucket.org/peerplaysblockchain/peerplays-graphene into betting-merge
This commit is contained in:
commit
2c8b9ce17a
15 changed files with 511 additions and 243 deletions
|
|
@ -236,6 +236,10 @@ struct get_impacted_account_visitor
|
||||||
{
|
{
|
||||||
_impacted.insert( op.bettor_id );
|
_impacted.insert( op.bettor_id );
|
||||||
}
|
}
|
||||||
|
void operator()( const bet_adjusted_operation& op )
|
||||||
|
{
|
||||||
|
_impacted.insert( op.bettor_id );
|
||||||
|
}
|
||||||
void operator()( const bet_matched_operation& op )
|
void operator()( const bet_matched_operation& op )
|
||||||
{
|
{
|
||||||
_impacted.insert( op.bettor_id );
|
_impacted.insert( op.bettor_id );
|
||||||
|
|
|
||||||
|
|
@ -291,26 +291,14 @@ void_result bet_place_evaluator::do_evaluate(const bet_place_operation& op)
|
||||||
simulated_bet.betting_market_id = op.betting_market_id;
|
simulated_bet.betting_market_id = op.betting_market_id;
|
||||||
simulated_bet.amount_to_bet = op.amount_to_bet;
|
simulated_bet.amount_to_bet = op.amount_to_bet;
|
||||||
simulated_bet.backer_multiplier = op.backer_multiplier;
|
simulated_bet.backer_multiplier = op.backer_multiplier;
|
||||||
simulated_bet.amount_reserved_for_fees = op.amount_reserved_for_fees;
|
|
||||||
simulated_bet.back_or_lay = op.back_or_lay;
|
simulated_bet.back_or_lay = op.back_or_lay;
|
||||||
|
|
||||||
share_type required_deposit = get_required_deposit_for_bet(simulated_bet);
|
share_type required_deposit = get_required_deposit_for_bet(simulated_bet);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// verify they reserved enough to cover the percentage fee
|
|
||||||
uint16_t percentage_fee = current_params.current_fees->get<bet_place_operation>().percentage_fee;
|
|
||||||
fc::uint128_t minimum_percentage_fee_calculation = op.amount_to_bet.amount.value;
|
|
||||||
minimum_percentage_fee_calculation *= percentage_fee;
|
|
||||||
minimum_percentage_fee_calculation += GRAPHENE_100_PERCENT - 1; // round up
|
|
||||||
minimum_percentage_fee_calculation /= GRAPHENE_100_PERCENT;
|
|
||||||
share_type minimum_percentage_fee = minimum_percentage_fee_calculation.to_uint64();
|
|
||||||
FC_ASSERT(op.amount_reserved_for_fees >= minimum_percentage_fee, "insufficient fees",
|
|
||||||
("fee_provided", op.amount_reserved_for_fees)("fee_required", minimum_percentage_fee));
|
|
||||||
|
|
||||||
// do they have enough in their account to place the bet
|
// do they have enough in their account to place the bet
|
||||||
_stake_plus_fees = op.amount_to_bet.amount + op.amount_reserved_for_fees;
|
FC_ASSERT( d.get_balance( *fee_paying_account, *_asset ).amount >= op.amount_to_bet.amount, "insufficient balance",
|
||||||
FC_ASSERT( d.get_balance( *fee_paying_account, *_asset ).amount >= _stake_plus_fees, "insufficient balance",
|
("balance", d.get_balance(*fee_paying_account, *_asset))("amount_to_bet", op.amount_to_bet.amount) );
|
||||||
("balance", d.get_balance(*fee_paying_account, *_asset))("stake_plus_fees", _stake_plus_fees) );
|
|
||||||
|
|
||||||
return void_result();
|
return void_result();
|
||||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
@ -324,15 +312,16 @@ object_id_type bet_place_evaluator::do_apply(const bet_place_operation& op)
|
||||||
bet_obj.betting_market_id = op.betting_market_id;
|
bet_obj.betting_market_id = op.betting_market_id;
|
||||||
bet_obj.amount_to_bet = op.amount_to_bet;
|
bet_obj.amount_to_bet = op.amount_to_bet;
|
||||||
bet_obj.backer_multiplier = op.backer_multiplier;
|
bet_obj.backer_multiplier = op.backer_multiplier;
|
||||||
bet_obj.amount_reserved_for_fees = op.amount_reserved_for_fees;
|
|
||||||
bet_obj.back_or_lay = op.back_or_lay;
|
bet_obj.back_or_lay = op.back_or_lay;
|
||||||
});
|
});
|
||||||
|
|
||||||
d.adjust_balance(fee_paying_account->id, asset(-_stake_plus_fees, _betting_market_group->asset_id));
|
bet_id_type new_bet_id = new_bet.id; // save the bet id here, new_bet may be deleted during place_bet()
|
||||||
|
|
||||||
|
d.adjust_balance(fee_paying_account->id, -op.amount_to_bet);
|
||||||
|
|
||||||
bool bet_matched = d.place_bet(new_bet);
|
bool bet_matched = d.place_bet(new_bet);
|
||||||
|
|
||||||
return new_bet.id;
|
return new_bet_id;
|
||||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
void_result bet_cancel_evaluator::do_evaluate(const bet_cancel_operation& op)
|
void_result bet_cancel_evaluator::do_evaluate(const bet_cancel_operation& op)
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,12 @@ namespace graphene { namespace chain {
|
||||||
void database::cancel_bet( const bet_object& bet, bool create_virtual_op )
|
void database::cancel_bet( const bet_object& bet, bool create_virtual_op )
|
||||||
{
|
{
|
||||||
asset amount_to_refund = bet.amount_to_bet;
|
asset amount_to_refund = bet.amount_to_bet;
|
||||||
amount_to_refund += bet.amount_reserved_for_fees;
|
|
||||||
//TODO: update global statistics
|
//TODO: update global statistics
|
||||||
adjust_balance(bet.bettor_id, amount_to_refund); //return unmatched stake + fees
|
adjust_balance(bet.bettor_id, amount_to_refund);
|
||||||
//TODO: do special fee accounting as required
|
|
||||||
if (create_virtual_op)
|
if (create_virtual_op)
|
||||||
{
|
{
|
||||||
bet_canceled_operation bet_canceled_virtual_op(bet.bettor_id, bet.id,
|
bet_canceled_operation bet_canceled_virtual_op(bet.bettor_id, bet.id,
|
||||||
bet.amount_to_bet,
|
bet.amount_to_bet);
|
||||||
bet.amount_reserved_for_fees);
|
|
||||||
//idump((bet_canceled_virtual_op));
|
//idump((bet_canceled_virtual_op));
|
||||||
push_applied_operation(std::move(bet_canceled_virtual_op));
|
push_applied_operation(std::move(bet_canceled_virtual_op));
|
||||||
}
|
}
|
||||||
|
|
@ -127,7 +124,6 @@ void database::resolve_betting_market_group(const betting_market_group_object& b
|
||||||
uint16_t rake_fee_percentage = get_global_properties().parameters.betting_rake_fee_percentage;
|
uint16_t rake_fee_percentage = get_global_properties().parameters.betting_rake_fee_percentage;
|
||||||
share_type net_profits;
|
share_type net_profits;
|
||||||
share_type payout_amounts;
|
share_type payout_amounts;
|
||||||
share_type fees_collected;
|
|
||||||
account_id_type bettor_id = bettor_positions_pair.first;
|
account_id_type bettor_id = bettor_positions_pair.first;
|
||||||
const std::vector<const betting_market_position_object*>& bettor_positions = bettor_positions_pair.second;
|
const std::vector<const betting_market_position_object*>& bettor_positions = bettor_positions_pair.second;
|
||||||
|
|
||||||
|
|
@ -149,7 +145,6 @@ void database::resolve_betting_market_group(const betting_market_group_object& b
|
||||||
{
|
{
|
||||||
share_type total_payout = position->pay_if_payout_condition + position->pay_if_not_canceled;
|
share_type total_payout = position->pay_if_payout_condition + position->pay_if_not_canceled;
|
||||||
payout_amounts += total_payout;
|
payout_amounts += total_payout;
|
||||||
fees_collected += position->fees_collected;
|
|
||||||
net_profits += total_payout - position->pay_if_canceled;
|
net_profits += total_payout - position->pay_if_canceled;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -157,12 +152,11 @@ void database::resolve_betting_market_group(const betting_market_group_object& b
|
||||||
{
|
{
|
||||||
share_type total_payout = position->pay_if_not_payout_condition + position->pay_if_not_canceled;
|
share_type total_payout = position->pay_if_not_payout_condition + position->pay_if_not_canceled;
|
||||||
payout_amounts += total_payout;
|
payout_amounts += total_payout;
|
||||||
fees_collected += position->fees_collected;
|
|
||||||
net_profits += total_payout - position->pay_if_canceled;
|
net_profits += total_payout - position->pay_if_canceled;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case betting_market_resolution_type::cancel:
|
case betting_market_resolution_type::cancel:
|
||||||
payout_amounts += position->pay_if_canceled + position->fees_collected;
|
payout_amounts += position->pay_if_canceled;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -179,9 +173,6 @@ void database::resolve_betting_market_group(const betting_market_group_object& b
|
||||||
adjust_balance(*rake_account_id, asset(rake_amount, betting_market_group.asset_id));
|
adjust_balance(*rake_account_id, asset(rake_amount, betting_market_group.asset_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fees_collected.value)
|
|
||||||
adjust_balance(*rake_account_id, asset(fees_collected, betting_market_group.asset_id));
|
|
||||||
|
|
||||||
// pay winning - rake
|
// pay winning - rake
|
||||||
adjust_balance(bettor_id, asset(payout_amounts - rake_amount, betting_market_group.asset_id));
|
adjust_balance(bettor_id, asset(payout_amounts - rake_amount, betting_market_group.asset_id));
|
||||||
// [ROL]
|
// [ROL]
|
||||||
|
|
@ -191,7 +182,7 @@ void database::resolve_betting_market_group(const betting_market_group_object& b
|
||||||
betting_market_group.id,
|
betting_market_group.id,
|
||||||
resolutions,
|
resolutions,
|
||||||
payout_amounts,
|
payout_amounts,
|
||||||
fees_collected));
|
rake_amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
betting_market_itr = betting_market_index.lower_bound(betting_market_group.id);
|
betting_market_itr = betting_market_index.lower_bound(betting_market_group.id);
|
||||||
|
|
@ -213,27 +204,7 @@ void database::get_required_deposit_for_bet(const betting_market_object& betting
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool maybe_cull_small_bet( database& db, const bet_object& bet_object_to_cull )
|
share_type adjust_betting_position(database& db, account_id_type bettor_id, betting_market_id_type betting_market_id, bet_type back_or_lay, share_type bet_amount, share_type matched_amount)
|
||||||
{
|
|
||||||
/**
|
|
||||||
* There are times when this bet can't be even partially matched at its stated odds
|
|
||||||
* For example, say it's a back bet for 20 satoshis at 1.92 odds (which comes out to 25:23
|
|
||||||
* odds). It's not possible for it to match at exact odds since it's < 25
|
|
||||||
*
|
|
||||||
* Remove these bets from the books to reduce clutter.
|
|
||||||
*/
|
|
||||||
share_type minimum_matchable_amount = bet_object_to_cull.get_minimum_matchable_amount();
|
|
||||||
if (bet_object_to_cull.amount_to_bet.amount < minimum_matchable_amount)
|
|
||||||
{
|
|
||||||
dlog("culling small bet of ${amount}, smaller than the minimum ${minimum_matchable_amount} at odds ${odds}",
|
|
||||||
("amount", bet_object_to_cull.amount_to_bet.amount)("minimum_matchable_amount", minimum_matchable_amount)("odds", bet_object_to_cull.backer_multiplier));
|
|
||||||
db.cancel_bet(bet_object_to_cull);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
share_type adjust_betting_position(database& db, account_id_type bettor_id, betting_market_id_type betting_market_id, bet_type back_or_lay, share_type bet_amount, share_type matched_amount, share_type fees_collected)
|
|
||||||
{ try {
|
{ try {
|
||||||
assert(bet_amount >= 0);
|
assert(bet_amount >= 0);
|
||||||
|
|
||||||
|
|
@ -253,7 +224,6 @@ share_type adjust_betting_position(database& db, account_id_type bettor_id, bett
|
||||||
position.pay_if_not_payout_condition = back_or_lay == bet_type::lay ? bet_amount + matched_amount : 0;
|
position.pay_if_not_payout_condition = back_or_lay == bet_type::lay ? bet_amount + matched_amount : 0;
|
||||||
position.pay_if_canceled = bet_amount;
|
position.pay_if_canceled = bet_amount;
|
||||||
position.pay_if_not_canceled = 0;
|
position.pay_if_not_canceled = 0;
|
||||||
position.fees_collected = fees_collected;
|
|
||||||
// this should not be reducible
|
// this should not be reducible
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -263,7 +233,6 @@ share_type adjust_betting_position(database& db, account_id_type bettor_id, bett
|
||||||
position.pay_if_payout_condition += back_or_lay == bet_type::back ? bet_amount + matched_amount : 0;
|
position.pay_if_payout_condition += back_or_lay == bet_type::back ? bet_amount + matched_amount : 0;
|
||||||
position.pay_if_not_payout_condition += back_or_lay == bet_type::lay ? bet_amount + matched_amount : 0;
|
position.pay_if_not_payout_condition += back_or_lay == bet_type::lay ? bet_amount + matched_amount : 0;
|
||||||
position.pay_if_canceled += bet_amount;
|
position.pay_if_canceled += bet_amount;
|
||||||
position.fees_collected += fees_collected;
|
|
||||||
|
|
||||||
guaranteed_winnings_returned = position.reduce();
|
guaranteed_winnings_returned = position.reduce();
|
||||||
});
|
});
|
||||||
|
|
@ -275,29 +244,21 @@ share_type adjust_betting_position(database& db, account_id_type bettor_id, bett
|
||||||
// called twice when a bet is matched, once for the taker, once for the maker
|
// called twice when a bet is matched, once for the taker, once for the maker
|
||||||
bool bet_was_matched(database& db, const bet_object& bet,
|
bool bet_was_matched(database& db, const bet_object& bet,
|
||||||
share_type amount_bet, share_type amount_matched,
|
share_type amount_bet, share_type amount_matched,
|
||||||
bet_multiplier_type actual_multiplier, bool cull_if_small)
|
bet_multiplier_type actual_multiplier)
|
||||||
{
|
{
|
||||||
// calculate the percentage fee paid
|
|
||||||
fc::uint128_t percentage_fee_128 = bet.amount_reserved_for_fees.value;
|
|
||||||
percentage_fee_128 *= amount_bet.value;
|
|
||||||
percentage_fee_128 += bet.amount_to_bet.amount.value - 1;
|
|
||||||
percentage_fee_128 /= bet.amount_to_bet.amount.value;
|
|
||||||
share_type fee_paid = percentage_fee_128.to_uint64();
|
|
||||||
|
|
||||||
// record their bet, modifying their position, and return any winnings
|
// record their bet, modifying their position, and return any winnings
|
||||||
share_type guaranteed_winnings_returned = adjust_betting_position(db, bet.bettor_id, bet.betting_market_id,
|
share_type guaranteed_winnings_returned = adjust_betting_position(db, bet.bettor_id, bet.betting_market_id,
|
||||||
bet.back_or_lay, amount_bet, amount_matched, fee_paid);
|
bet.back_or_lay, amount_bet, amount_matched);
|
||||||
db.adjust_balance(bet.bettor_id, asset(guaranteed_winnings_returned, bet.amount_to_bet.asset_id));
|
db.adjust_balance(bet.bettor_id, asset(guaranteed_winnings_returned, bet.amount_to_bet.asset_id));
|
||||||
|
|
||||||
// generate a virtual "match" op
|
// generate a virtual "match" op
|
||||||
asset asset_amount_bet(amount_bet, bet.amount_to_bet.asset_id);
|
asset asset_amount_bet(amount_bet, bet.amount_to_bet.asset_id);
|
||||||
|
|
||||||
bet_matched_operation bet_matched_virtual_op(bet.bettor_id, bet.id, bet.betting_market_id,
|
bet_matched_operation bet_matched_virtual_op(bet.bettor_id, bet.id,
|
||||||
asset_amount_bet,
|
asset_amount_bet,
|
||||||
fee_paid,
|
|
||||||
actual_multiplier,
|
actual_multiplier,
|
||||||
guaranteed_winnings_returned);
|
guaranteed_winnings_returned);
|
||||||
//idump((bet_matched_virtual_op));
|
//edump((bet_matched_virtual_op));
|
||||||
db.push_applied_operation(std::move(bet_matched_virtual_op));
|
db.push_applied_operation(std::move(bet_matched_virtual_op));
|
||||||
|
|
||||||
// update the bet on the books
|
// update the bet on the books
|
||||||
|
|
@ -310,12 +271,7 @@ bool bet_was_matched(database& db, const bet_object& bet,
|
||||||
{
|
{
|
||||||
db.modify(bet, [&](bet_object& bet_obj) {
|
db.modify(bet, [&](bet_object& bet_obj) {
|
||||||
bet_obj.amount_to_bet -= asset_amount_bet;
|
bet_obj.amount_to_bet -= asset_amount_bet;
|
||||||
bet_obj.amount_reserved_for_fees -= fee_paid;
|
|
||||||
});
|
});
|
||||||
//TODO: cull_if_small is currently always true, remove the parameter if we don't find a
|
|
||||||
// need for it soon
|
|
||||||
if (cull_if_small)
|
|
||||||
return maybe_cull_small_bet(db, bet);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -334,7 +290,7 @@ int match_bet(database& db, const bet_object& taker_bet, const bet_object& maker
|
||||||
{
|
{
|
||||||
assert(taker_bet.amount_to_bet.asset_id == maker_bet.amount_to_bet.asset_id);
|
assert(taker_bet.amount_to_bet.asset_id == maker_bet.amount_to_bet.asset_id);
|
||||||
assert(taker_bet.amount_to_bet.amount > 0 && maker_bet.amount_to_bet.amount > 0);
|
assert(taker_bet.amount_to_bet.amount > 0 && maker_bet.amount_to_bet.amount > 0);
|
||||||
assert(taker_bet.backer_multiplier >= maker_bet.backer_multiplier);
|
assert(taker_bet.back_or_lay == bet_type::back ? taker_bet.backer_multiplier <= maker_bet.backer_multiplier : taker_bet.backer_multiplier >= maker_bet.backer_multiplier);
|
||||||
assert(taker_bet.back_or_lay != maker_bet.back_or_lay);
|
assert(taker_bet.back_or_lay != maker_bet.back_or_lay);
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
@ -381,37 +337,80 @@ int match_bet(database& db, const bet_object& taker_bet, const bet_object& maker
|
||||||
|
|
||||||
//idump((taker_amount_to_match)(maker_amount_to_match));
|
//idump((taker_amount_to_match)(maker_amount_to_match));
|
||||||
|
|
||||||
result |= bet_was_matched(db, taker_bet, taker_amount_to_match, maker_amount_to_match, maker_bet.backer_multiplier, true);
|
result |= bet_was_matched(db, taker_bet, taker_amount_to_match, maker_amount_to_match, maker_bet.backer_multiplier);
|
||||||
result |= bet_was_matched(db, maker_bet, maker_amount_to_match, taker_amount_to_match, maker_bet.backer_multiplier, true) << 1;
|
result |= bet_was_matched(db, maker_bet, maker_amount_to_match, taker_amount_to_match, maker_bet.backer_multiplier) << 1;
|
||||||
|
|
||||||
assert(result != 0);
|
assert(result != 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// called from the bet_place_evaluator
|
||||||
bool database::place_bet(const bet_object& new_bet_object)
|
bool database::place_bet(const bet_object& new_bet_object)
|
||||||
{
|
{
|
||||||
bet_id_type bet_id = new_bet_object.id;
|
|
||||||
const asset_object& bet_asset = get(new_bet_object.amount_to_bet.asset_id);
|
|
||||||
|
|
||||||
const auto& bet_odds_idx = get_index_type<bet_object_index>().indices().get<by_odds>();
|
const auto& bet_odds_idx = get_index_type<bet_object_index>().indices().get<by_odds>();
|
||||||
|
|
||||||
bet_type bet_type_to_match = new_bet_object.back_or_lay == bet_type::back ? bet_type::lay : bet_type::back;
|
bet_type bet_type_to_match = new_bet_object.back_or_lay == bet_type::back ? bet_type::lay : bet_type::back;
|
||||||
auto book_itr = bet_odds_idx.lower_bound(std::make_tuple(new_bet_object.betting_market_id, bet_type_to_match));
|
auto book_itr = bet_odds_idx.lower_bound(std::make_tuple(new_bet_object.betting_market_id, bet_type_to_match));
|
||||||
auto book_end = bet_odds_idx.upper_bound(std::make_tuple(new_bet_object.betting_market_id, bet_type_to_match, new_bet_object.backer_multiplier));
|
auto book_end = bet_odds_idx.upper_bound(std::make_tuple(new_bet_object.betting_market_id, bet_type_to_match, new_bet_object.backer_multiplier));
|
||||||
|
|
||||||
|
// ilog("");
|
||||||
|
// ilog("------------ order book ------------------");
|
||||||
|
// for (auto itr = book_itr; itr != book_end; ++itr)
|
||||||
|
// idump((*itr));
|
||||||
|
// ilog("------------ order book ------------------");
|
||||||
|
|
||||||
int orders_matched_flags = 0;
|
int orders_matched_flags = 0;
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
while (!finished && book_itr != book_end)
|
while (!finished && book_itr != book_end)
|
||||||
{
|
{
|
||||||
auto old_book_itr = book_itr;
|
auto old_book_itr = book_itr;
|
||||||
++book_itr;
|
++book_itr;
|
||||||
// match returns 2 when only the old order was fully filled. In this case, we keep matching; otherwise, we stop.
|
|
||||||
|
|
||||||
orders_matched_flags = match_bet(*this, new_bet_object, *old_book_itr);
|
orders_matched_flags = match_bet(*this, new_bet_object, *old_book_itr);
|
||||||
|
|
||||||
|
// we continue if the maker bet was completely consumed AND the taker bet was not
|
||||||
finished = orders_matched_flags != 2;
|
finished = orders_matched_flags != 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (orders_matched_flags & 1) != 0;
|
if (!(orders_matched_flags & 1))
|
||||||
|
{
|
||||||
|
// if the new (taker) bet was not completely consumed, we need to put whatever remains
|
||||||
|
// of it on the books. But we only allow bets that can be exactly matched
|
||||||
|
// on the books, so round the amount down if necessary
|
||||||
|
share_type minimum_matchable_amount = new_bet_object.get_minimum_matchable_amount();
|
||||||
|
share_type scale_factor = new_bet_object.amount_to_bet.amount / minimum_matchable_amount;
|
||||||
|
share_type rounded_bet_amount = scale_factor * minimum_matchable_amount;
|
||||||
|
//idump((new_bet_object.amount_to_bet.amount)(rounded_bet_amount)(minimum_matchable_amount)(scale_factor));
|
||||||
|
|
||||||
|
if (rounded_bet_amount == share_type())
|
||||||
|
{
|
||||||
|
// the remainder of the bet was too small to match, cancel the bet
|
||||||
|
cancel_bet(new_bet_object, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (rounded_bet_amount != new_bet_object.amount_to_bet.amount)
|
||||||
|
{
|
||||||
|
asset stake_returned = new_bet_object.amount_to_bet;
|
||||||
|
stake_returned.amount -= rounded_bet_amount;
|
||||||
|
|
||||||
|
modify(new_bet_object, [&rounded_bet_amount](bet_object& modified_bet_object) {
|
||||||
|
modified_bet_object.amount_to_bet.amount = rounded_bet_amount;
|
||||||
|
});
|
||||||
|
|
||||||
|
adjust_balance(new_bet_object.bettor_id, stake_returned);
|
||||||
|
// TODO: update global statistics
|
||||||
|
bet_adjusted_operation bet_adjusted_op(new_bet_object.bettor_id, new_bet_object.id,
|
||||||
|
stake_returned);
|
||||||
|
// idump((bet_adjusted_op)(new_bet_object));
|
||||||
|
push_applied_operation(std::move(bet_adjusted_op));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,7 @@ struct get_impacted_account_visitor
|
||||||
void operator()(const bet_matched_operation &){}
|
void operator()(const bet_matched_operation &){}
|
||||||
void operator()(const bet_cancel_operation&){}
|
void operator()(const bet_cancel_operation&){}
|
||||||
void operator()(const bet_canceled_operation &){}
|
void operator()(const bet_canceled_operation &){}
|
||||||
|
void operator()(const bet_adjusted_operation &){}
|
||||||
|
|
||||||
void operator()( const tournament_create_operation& op )
|
void operator()( const tournament_create_operation& op )
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,6 @@ class bet_object : public graphene::db::abstract_object< bet_object >
|
||||||
|
|
||||||
bet_multiplier_type backer_multiplier;
|
bet_multiplier_type backer_multiplier;
|
||||||
|
|
||||||
share_type amount_reserved_for_fees; // same asset type as amount_to_bet
|
|
||||||
|
|
||||||
bet_type back_or_lay;
|
bet_type back_or_lay;
|
||||||
|
|
||||||
static share_type get_approximate_matching_amount(share_type bet_amount, bet_multiplier_type backer_multiplier, bet_type back_or_lay, bool round_up = false);
|
static share_type get_approximate_matching_amount(share_type bet_amount, bet_multiplier_type backer_multiplier, bet_type back_or_lay, bool round_up = false);
|
||||||
|
|
@ -241,7 +239,10 @@ struct compare_bet_by_odds {
|
||||||
return true;
|
return true;
|
||||||
if (lhs_bet_type > rhs_bet_type)
|
if (lhs_bet_type > rhs_bet_type)
|
||||||
return false;
|
return false;
|
||||||
return lhs_backer_multiplier < rhs_backer_multiplier;
|
if (lhs_bet_type == bet_type::back)
|
||||||
|
return lhs_backer_multiplier < rhs_backer_multiplier;
|
||||||
|
else
|
||||||
|
return lhs_backer_multiplier > rhs_backer_multiplier;
|
||||||
}
|
}
|
||||||
bool compare(const betting_market_id_type& lhs_betting_market_id, bet_type lhs_bet_type,
|
bool compare(const betting_market_id_type& lhs_betting_market_id, bet_type lhs_bet_type,
|
||||||
bet_multiplier_type lhs_backer_multiplier, const bet_id_type& lhs_bet_id,
|
bet_multiplier_type lhs_backer_multiplier, const bet_id_type& lhs_bet_id,
|
||||||
|
|
@ -257,9 +258,9 @@ struct compare_bet_by_odds {
|
||||||
if (lhs_bet_type > rhs_bet_type)
|
if (lhs_bet_type > rhs_bet_type)
|
||||||
return false;
|
return false;
|
||||||
if (lhs_backer_multiplier < rhs_backer_multiplier)
|
if (lhs_backer_multiplier < rhs_backer_multiplier)
|
||||||
return true;
|
return lhs_bet_type == bet_type::back;
|
||||||
if (lhs_backer_multiplier > rhs_backer_multiplier)
|
if (lhs_backer_multiplier > rhs_backer_multiplier)
|
||||||
return false;
|
return lhs_bet_type == bet_type::lay;
|
||||||
return lhs_bet_id < rhs_bet_id;
|
return lhs_bet_id < rhs_bet_id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -381,7 +382,10 @@ struct compare_bet_by_bettor_then_odds {
|
||||||
return true;
|
return true;
|
||||||
if (lhs_bet_type > rhs_bet_type)
|
if (lhs_bet_type > rhs_bet_type)
|
||||||
return false;
|
return false;
|
||||||
return lhs_backer_multiplier < rhs_backer_multiplier;
|
if (lhs_bet_type == bet_type::back)
|
||||||
|
return lhs_backer_multiplier < rhs_backer_multiplier;
|
||||||
|
else
|
||||||
|
return lhs_backer_multiplier > rhs_backer_multiplier;
|
||||||
}
|
}
|
||||||
bool compare(const betting_market_id_type& lhs_betting_market_id, const account_id_type& lhs_bettor_id,
|
bool compare(const betting_market_id_type& lhs_betting_market_id, const account_id_type& lhs_bettor_id,
|
||||||
bet_type lhs_bet_type,
|
bet_type lhs_bet_type,
|
||||||
|
|
@ -403,9 +407,10 @@ struct compare_bet_by_bettor_then_odds {
|
||||||
if (lhs_bet_type > rhs_bet_type)
|
if (lhs_bet_type > rhs_bet_type)
|
||||||
return false;
|
return false;
|
||||||
if (lhs_backer_multiplier < rhs_backer_multiplier)
|
if (lhs_backer_multiplier < rhs_backer_multiplier)
|
||||||
return true;
|
return lhs_bet_type == bet_type::back;
|
||||||
if (lhs_backer_multiplier > rhs_backer_multiplier)
|
if (lhs_backer_multiplier > rhs_backer_multiplier)
|
||||||
return false;
|
return lhs_bet_type == bet_type::lay;
|
||||||
|
|
||||||
return lhs_bet_id < rhs_bet_id;
|
return lhs_bet_id < rhs_bet_id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -444,6 +449,6 @@ typedef generic_index<betting_market_position_object, betting_market_position_mu
|
||||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_rules_object, (graphene::db::object), (name)(description) )
|
FC_REFLECT_DERIVED( graphene::chain::betting_market_rules_object, (graphene::db::object), (name)(description) )
|
||||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_group_object, (graphene::db::object), (description)(event_id)(rules_id)(asset_id)(frozen)(total_matched_bets_amount) )
|
FC_REFLECT_DERIVED( graphene::chain::betting_market_group_object, (graphene::db::object), (description)(event_id)(rules_id)(asset_id)(frozen)(total_matched_bets_amount) )
|
||||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_object, (graphene::db::object), (group_id)(description)(payout_condition) )
|
FC_REFLECT_DERIVED( graphene::chain::betting_market_object, (graphene::db::object), (group_id)(description)(payout_condition) )
|
||||||
FC_REFLECT_DERIVED( graphene::chain::bet_object, (graphene::db::object), (bettor_id)(betting_market_id)(amount_to_bet)(backer_multiplier)(amount_reserved_for_fees)(back_or_lay) )
|
FC_REFLECT_DERIVED( graphene::chain::bet_object, (graphene::db::object), (bettor_id)(betting_market_id)(amount_to_bet)(backer_multiplier)(back_or_lay) )
|
||||||
|
|
||||||
FC_REFLECT_DERIVED( graphene::chain::betting_market_position_object, (graphene::db::object), (bettor_id)(betting_market_id)(pay_if_payout_condition)(pay_if_not_payout_condition)(pay_if_canceled)(pay_if_not_canceled)(fees_collected) )
|
FC_REFLECT_DERIVED( graphene::chain::betting_market_position_object, (graphene::db::object), (bettor_id)(betting_market_id)(pay_if_payout_condition)(pay_if_not_payout_condition)(pay_if_canceled)(pay_if_not_canceled)(fees_collected) )
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,6 @@ struct bet_place_operation : public base_operation
|
||||||
struct fee_parameters_type
|
struct fee_parameters_type
|
||||||
{
|
{
|
||||||
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; // fixed fee charged upon placing the bet
|
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; // fixed fee charged upon placing the bet
|
||||||
uint16_t percentage_fee = 2 * GRAPHENE_1_PERCENT; // charged when bet is matched
|
|
||||||
};
|
};
|
||||||
asset fee;
|
asset fee;
|
||||||
|
|
||||||
|
|
@ -257,11 +256,6 @@ struct bet_place_operation : public base_operation
|
||||||
// would be 2 * GRAPHENE_BETTING_ODDS_PRECISION.
|
// would be 2 * GRAPHENE_BETTING_ODDS_PRECISION.
|
||||||
bet_multiplier_type backer_multiplier;
|
bet_multiplier_type backer_multiplier;
|
||||||
|
|
||||||
// the amount the blockchain reserves to pay the percentage fee on matched bets.
|
|
||||||
// when this bet is (partially) matched, the blockchain will take (part of) the fee. If this bet is canceled
|
|
||||||
// the remaining amount will be returned to the bettor (same asset type as the amount_to_bet)
|
|
||||||
share_type amount_reserved_for_fees;
|
|
||||||
|
|
||||||
bet_type back_or_lay;
|
bet_type back_or_lay;
|
||||||
|
|
||||||
extensions_type extensions;
|
extensions_type extensions;
|
||||||
|
|
@ -278,24 +272,20 @@ struct bet_matched_operation : public base_operation
|
||||||
struct fee_parameters_type {};
|
struct fee_parameters_type {};
|
||||||
|
|
||||||
bet_matched_operation(){}
|
bet_matched_operation(){}
|
||||||
bet_matched_operation(account_id_type bettor_id, bet_id_type bet_id, betting_market_id_type betting_market_id,
|
bet_matched_operation(account_id_type bettor_id, bet_id_type bet_id,
|
||||||
asset amount_bet, share_type fees_paid,
|
asset amount_bet,
|
||||||
bet_multiplier_type backer_multiplier,
|
bet_multiplier_type backer_multiplier,
|
||||||
share_type guaranteed_winnings_returned) :
|
share_type guaranteed_winnings_returned) :
|
||||||
bettor_id(bettor_id),
|
bettor_id(bettor_id),
|
||||||
bet_id(bet_id),
|
bet_id(bet_id),
|
||||||
betting_market_id(betting_market_id),
|
|
||||||
amount_bet(amount_bet),
|
amount_bet(amount_bet),
|
||||||
fees_paid(fees_paid),
|
|
||||||
backer_multiplier(backer_multiplier),
|
backer_multiplier(backer_multiplier),
|
||||||
guaranteed_winnings_returned(guaranteed_winnings_returned)
|
guaranteed_winnings_returned(guaranteed_winnings_returned)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
account_id_type bettor_id;
|
account_id_type bettor_id;
|
||||||
bet_id_type bet_id;
|
bet_id_type bet_id;
|
||||||
betting_market_id_type betting_market_id;
|
|
||||||
asset amount_bet;
|
asset amount_bet;
|
||||||
share_type fees_paid; // same asset type as amount_bet
|
|
||||||
bet_multiplier_type backer_multiplier; // the actual odds received
|
bet_multiplier_type backer_multiplier; // the actual odds received
|
||||||
share_type guaranteed_winnings_returned; // same asset type as amount_bet
|
share_type guaranteed_winnings_returned; // same asset type as amount_bet
|
||||||
asset fee; // unimportant for a virtual op
|
asset fee; // unimportant for a virtual op
|
||||||
|
|
@ -332,17 +322,15 @@ struct bet_canceled_operation : public base_operation
|
||||||
|
|
||||||
bet_canceled_operation(){}
|
bet_canceled_operation(){}
|
||||||
bet_canceled_operation(account_id_type bettor_id, bet_id_type bet_id,
|
bet_canceled_operation(account_id_type bettor_id, bet_id_type bet_id,
|
||||||
asset stake_returned, share_type unused_fees_returned) :
|
asset stake_returned) :
|
||||||
bettor_id(bettor_id),
|
bettor_id(bettor_id),
|
||||||
bet_id(bet_id),
|
bet_id(bet_id),
|
||||||
stake_returned(stake_returned),
|
stake_returned(stake_returned)
|
||||||
unused_fees_returned(unused_fees_returned)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
account_id_type bettor_id;
|
account_id_type bettor_id;
|
||||||
bet_id_type bet_id;
|
bet_id_type bet_id;
|
||||||
asset stake_returned;
|
asset stake_returned;
|
||||||
share_type unused_fees_returned; // same asset type as stake_returned
|
|
||||||
asset fee; // unimportant for a virtual op
|
asset fee; // unimportant for a virtual op
|
||||||
|
|
||||||
account_id_type fee_payer()const { return bettor_id; }
|
account_id_type fee_payer()const { return bettor_id; }
|
||||||
|
|
@ -352,6 +340,35 @@ struct bet_canceled_operation : public base_operation
|
||||||
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
|
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virtual op generated when a bet amount is rounded down to an amount that can
|
||||||
|
* match evenly at a given odds (the blockchain does this automatically at the time
|
||||||
|
* the bet is placed on the order books). (note: there is no way a user can adjust their bet
|
||||||
|
* after placing it, aside from canceling the bet and placing a new one)
|
||||||
|
*/
|
||||||
|
struct bet_adjusted_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type {};
|
||||||
|
|
||||||
|
bet_adjusted_operation(){}
|
||||||
|
bet_adjusted_operation(account_id_type bettor_id, bet_id_type bet_id,
|
||||||
|
asset stake_returned) :
|
||||||
|
bettor_id(bettor_id),
|
||||||
|
bet_id(bet_id),
|
||||||
|
stake_returned(stake_returned)
|
||||||
|
{}
|
||||||
|
|
||||||
|
account_id_type bettor_id;
|
||||||
|
bet_id_type bet_id;
|
||||||
|
asset stake_returned;
|
||||||
|
asset fee; // unimportant for a virtual op
|
||||||
|
|
||||||
|
account_id_type fee_payer()const { return bettor_id; }
|
||||||
|
void validate()const { FC_ASSERT(false, "virtual operation"); }
|
||||||
|
|
||||||
|
/// This is a virtual operation; there is no fee
|
||||||
|
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
|
@ -396,13 +413,16 @@ FC_REFLECT( graphene::chain::betting_market_group_cancel_unmatched_bets_operatio
|
||||||
FC_REFLECT_ENUM( graphene::chain::bet_type, (back)(lay) )
|
FC_REFLECT_ENUM( graphene::chain::bet_type, (back)(lay) )
|
||||||
FC_REFLECT( graphene::chain::bet_place_operation::fee_parameters_type, (fee) )
|
FC_REFLECT( graphene::chain::bet_place_operation::fee_parameters_type, (fee) )
|
||||||
FC_REFLECT( graphene::chain::bet_place_operation,
|
FC_REFLECT( graphene::chain::bet_place_operation,
|
||||||
(fee)(bettor_id)(betting_market_id)(amount_to_bet)(backer_multiplier)(amount_reserved_for_fees)(back_or_lay)(extensions) )
|
(fee)(bettor_id)(betting_market_id)(amount_to_bet)(backer_multiplier)(back_or_lay)(extensions) )
|
||||||
|
|
||||||
FC_REFLECT( graphene::chain::bet_matched_operation::fee_parameters_type, )
|
FC_REFLECT( graphene::chain::bet_matched_operation::fee_parameters_type, )
|
||||||
FC_REFLECT( graphene::chain::bet_matched_operation, (bettor_id)(bet_id)(betting_market_id)(amount_bet)(fees_paid)(backer_multiplier)(guaranteed_winnings_returned) )
|
FC_REFLECT( graphene::chain::bet_matched_operation, (bettor_id)(bet_id)(amount_bet)(backer_multiplier)(guaranteed_winnings_returned) )
|
||||||
|
|
||||||
FC_REFLECT( graphene::chain::bet_cancel_operation::fee_parameters_type, (fee) )
|
FC_REFLECT( graphene::chain::bet_cancel_operation::fee_parameters_type, (fee) )
|
||||||
FC_REFLECT( graphene::chain::bet_cancel_operation, (bettor_id) (bet_to_cancel) (extensions) )
|
FC_REFLECT( graphene::chain::bet_cancel_operation, (bettor_id) (bet_to_cancel) (extensions) )
|
||||||
|
|
||||||
FC_REFLECT( graphene::chain::bet_canceled_operation::fee_parameters_type, )
|
FC_REFLECT( graphene::chain::bet_canceled_operation::fee_parameters_type, )
|
||||||
FC_REFLECT( graphene::chain::bet_canceled_operation, (bettor_id)(bet_id)(stake_returned)(unused_fees_returned) )
|
FC_REFLECT( graphene::chain::bet_canceled_operation, (bettor_id)(bet_id)(stake_returned) )
|
||||||
|
|
||||||
|
FC_REFLECT( graphene::chain::bet_adjusted_operation::fee_parameters_type, )
|
||||||
|
FC_REFLECT( graphene::chain::bet_adjusted_operation, (bettor_id)(bet_id)(stake_returned) )
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,8 @@ namespace graphene { namespace chain {
|
||||||
tournament_payout_operation, // VIRTUAL
|
tournament_payout_operation, // VIRTUAL
|
||||||
tournament_leave_operation,
|
tournament_leave_operation,
|
||||||
betting_market_group_update_operation,
|
betting_market_group_update_operation,
|
||||||
betting_market_update_operation
|
betting_market_update_operation,
|
||||||
|
bet_adjusted_operation // VIRTUAL
|
||||||
> operation;
|
> operation;
|
||||||
|
|
||||||
/// @} // operations group
|
/// @} // operations group
|
||||||
|
|
|
||||||
|
|
@ -80,13 +80,15 @@ binned_order_book bookie_api_impl::get_binned_order_book(graphene::chain::bettin
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// iterate through both sides of the order book (backs at increasing odds then lays at decreasing odds)
|
||||||
for (auto bet_odds_iter = bet_odds_idx.lower_bound(std::make_tuple(betting_market_id));
|
for (auto bet_odds_iter = bet_odds_idx.lower_bound(std::make_tuple(betting_market_id));
|
||||||
bet_odds_iter != bet_odds_idx.end() && betting_market_id == bet_odds_iter->betting_market_id;
|
bet_odds_iter != bet_odds_idx.end() && betting_market_id == bet_odds_iter->betting_market_id;
|
||||||
++bet_odds_iter)
|
++bet_odds_iter)
|
||||||
{
|
{
|
||||||
if (current_bin &&
|
if (current_bin &&
|
||||||
(bet_odds_iter->back_or_lay == current_bin->back_or_lay ||
|
(bet_odds_iter->back_or_lay == current_bin->back_or_lay /* we have switched from back to lay bets */ ||
|
||||||
bet_odds_iter->backer_multiplier > current_bin->backer_multiplier))
|
(bet_odds_iter->back_or_lay == bet_type::back ? bet_odds_iter->backer_multiplier > current_bin->backer_multiplier :
|
||||||
|
bet_odds_iter->backer_multiplier < current_bin->backer_multiplier)))
|
||||||
flush_current_bin();
|
flush_current_bin();
|
||||||
|
|
||||||
if (!current_bin)
|
if (!current_bin)
|
||||||
|
|
@ -94,9 +96,21 @@ binned_order_book bookie_api_impl::get_binned_order_book(graphene::chain::bettin
|
||||||
// if there is no current bin, create one appropriate for the bet we're processing
|
// if there is no current bin, create one appropriate for the bet we're processing
|
||||||
current_bin = graphene::chain::bet_object();
|
current_bin = graphene::chain::bet_object();
|
||||||
|
|
||||||
current_bin->backer_multiplier = (bet_odds_iter->backer_multiplier + bin_size - 1) / bin_size * bin_size;
|
// for back bets, we want to group all bets with odds from 3.0001 to 4 into the "4" bin
|
||||||
current_bin->backer_multiplier = std::min<graphene::chain::bet_multiplier_type>(current_bin->backer_multiplier, current_params.max_bet_multiplier);
|
// for lay bets, we want to group all bets with odds from 3 to 3.9999 into the "3" bin
|
||||||
current_bin->back_or_lay = bet_odds_iter->back_or_lay == bet_type::back ? bet_type::lay : bet_type::back;
|
if (bet_odds_iter->back_or_lay == bet_type::back)
|
||||||
|
{
|
||||||
|
current_bin->backer_multiplier = (bet_odds_iter->backer_multiplier + bin_size - 1) / bin_size * bin_size;
|
||||||
|
current_bin->backer_multiplier = std::min<graphene::chain::bet_multiplier_type>(current_bin->backer_multiplier, current_params.max_bet_multiplier);
|
||||||
|
current_bin->back_or_lay = bet_type::lay;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_bin->backer_multiplier = bet_odds_iter->backer_multiplier / bin_size * bin_size;
|
||||||
|
current_bin->backer_multiplier = std::max<graphene::chain::bet_multiplier_type>(current_bin->backer_multiplier, current_params.min_bet_multiplier);
|
||||||
|
current_bin->back_or_lay = bet_type::back;
|
||||||
|
}
|
||||||
|
|
||||||
current_bin->amount_to_bet.amount = 0;
|
current_bin->amount_to_bet.amount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ namespace graphene { namespace bookie {
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
class persistent_event_object : public graphene::db::abstract_object<event_object>
|
class persistent_event_object : public graphene::db::abstract_object<persistent_event_object>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const uint8_t space_id = bookie_objects;
|
static const uint8_t space_id = bookie_objects;
|
||||||
|
|
@ -124,6 +124,117 @@ void events_by_competitor_index::object_modified( const object& after )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//////////// betting_market_group_object //////////////////
|
||||||
|
class persistent_betting_market_group_object : public graphene::db::abstract_object<persistent_betting_market_group_object>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = bookie_objects;
|
||||||
|
static const uint8_t type_id = persistent_betting_market_group_object_type;
|
||||||
|
|
||||||
|
betting_market_group_object ephemeral_betting_market_group_object;
|
||||||
|
|
||||||
|
share_type total_matched_bets_amount;
|
||||||
|
|
||||||
|
betting_market_group_id_type get_betting_market_group_id() const { return ephemeral_betting_market_group_object.id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct by_betting_market_group_id;
|
||||||
|
typedef multi_index_container<
|
||||||
|
persistent_betting_market_group_object,
|
||||||
|
indexed_by<
|
||||||
|
ordered_unique<tag<by_id>, member<object, object_id_type, &object::id> >,
|
||||||
|
ordered_unique<tag<by_betting_market_group_id>, const_mem_fun<persistent_betting_market_group_object, betting_market_group_id_type, &persistent_betting_market_group_object::get_betting_market_group_id> > > > persistent_betting_market_group_multi_index_type;
|
||||||
|
|
||||||
|
typedef generic_index<persistent_betting_market_group_object, persistent_betting_market_group_multi_index_type> persistent_betting_market_group_index;
|
||||||
|
|
||||||
|
//////////// betting_market_object //////////////////
|
||||||
|
class persistent_betting_market_object : public graphene::db::abstract_object<persistent_betting_market_object>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = bookie_objects;
|
||||||
|
static const uint8_t type_id = persistent_betting_market_object_type;
|
||||||
|
|
||||||
|
betting_market_object ephemeral_betting_market_object;
|
||||||
|
|
||||||
|
share_type total_matched_bets_amount;
|
||||||
|
|
||||||
|
betting_market_id_type get_betting_market_id() const { return ephemeral_betting_market_object.id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct by_betting_market_id;
|
||||||
|
typedef multi_index_container<
|
||||||
|
persistent_betting_market_object,
|
||||||
|
indexed_by<
|
||||||
|
ordered_unique<tag<by_id>, member<object, object_id_type, &object::id> >,
|
||||||
|
ordered_unique<tag<by_betting_market_id>, const_mem_fun<persistent_betting_market_object, betting_market_id_type, &persistent_betting_market_object::get_betting_market_id> > > > persistent_betting_market_multi_index_type;
|
||||||
|
|
||||||
|
typedef generic_index<persistent_betting_market_object, persistent_betting_market_multi_index_type> persistent_betting_market_index;
|
||||||
|
|
||||||
|
//////////// bet_object //////////////////
|
||||||
|
class persistent_bet_object : public graphene::db::abstract_object<persistent_bet_object>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = bookie_objects;
|
||||||
|
static const uint8_t type_id = persistent_bet_object_type;
|
||||||
|
|
||||||
|
bet_object ephemeral_bet_object;
|
||||||
|
|
||||||
|
bet_id_type get_bet_id() const { return ephemeral_bet_object.id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct by_bet_id;
|
||||||
|
typedef multi_index_container<
|
||||||
|
persistent_bet_object,
|
||||||
|
indexed_by<
|
||||||
|
ordered_unique<tag<by_id>, member<object, object_id_type, &object::id> >,
|
||||||
|
ordered_unique<tag<by_bet_id>, const_mem_fun<persistent_bet_object, bet_id_type, &persistent_bet_object::get_bet_id> > > > persistent_bet_multi_index_type;
|
||||||
|
|
||||||
|
|
||||||
|
typedef generic_index<persistent_bet_object, persistent_bet_multi_index_type> persistent_bet_index;
|
||||||
|
|
||||||
|
/* As a plugin, we get notified of new/changed objects at the end of every block processed.
|
||||||
|
* For most objects, that's fine, because we expect them to always be around until the end of
|
||||||
|
* the block. However, with bet objects, it's possible that the user places a bet and it fills
|
||||||
|
* and is removed during the same block, so need another strategy to detect them immediately after
|
||||||
|
* they are created.
|
||||||
|
* We do this by creating a secondary index on bet_object. We don't actually use it
|
||||||
|
* to index any property of the bet, we just use it to register for callbacks.
|
||||||
|
*/
|
||||||
|
class persistent_bet_object_helper : public secondary_index
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~persistent_bet_object_helper() {}
|
||||||
|
|
||||||
|
virtual void object_inserted(const object& obj) override;
|
||||||
|
//virtual void object_removed( const object& obj ) override;
|
||||||
|
//virtual void about_to_modify( const object& before ) override;
|
||||||
|
virtual void object_modified(const object& after) override;
|
||||||
|
void set_plugin_instance(bookie_plugin* instance) { _bookie_plugin = instance; }
|
||||||
|
private:
|
||||||
|
bookie_plugin* _bookie_plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
void persistent_bet_object_helper::object_inserted(const object& obj)
|
||||||
|
{
|
||||||
|
const bet_object& bet_obj = *boost::polymorphic_downcast<const bet_object*>(&obj);
|
||||||
|
_bookie_plugin->database().create<persistent_bet_object>([&](persistent_bet_object& saved_bet_obj) {
|
||||||
|
saved_bet_obj.ephemeral_bet_object = bet_obj;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void persistent_bet_object_helper::object_modified(const object& after)
|
||||||
|
{
|
||||||
|
database& db = _bookie_plugin->database();
|
||||||
|
auto& persistent_bets_by_bet_id = db.get_index_type<persistent_bet_index>().indices().get<by_bet_id>();
|
||||||
|
const bet_object& bet_obj = *boost::polymorphic_downcast<const bet_object*>(&after);
|
||||||
|
auto iter = persistent_bets_by_bet_id.find(bet_obj.id);
|
||||||
|
assert (iter != persistent_bets_by_bet_id.end());
|
||||||
|
if (iter != persistent_bets_by_bet_id.end())
|
||||||
|
db.modify(*iter, [&](persistent_bet_object& saved_bet_obj) {
|
||||||
|
saved_bet_obj.ephemeral_bet_object = bet_obj;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////// end bet_object ///////////////////
|
||||||
class bookie_plugin_impl
|
class bookie_plugin_impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -175,13 +286,14 @@ class bookie_plugin_impl
|
||||||
|
|
||||||
bookie_plugin_impl::~bookie_plugin_impl()
|
bookie_plugin_impl::~bookie_plugin_impl()
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bookie_plugin_impl::on_objects_changed(const vector<object_id_type>& changed_object_ids)
|
void bookie_plugin_impl::on_objects_changed(const vector<object_id_type>& changed_object_ids)
|
||||||
{
|
{
|
||||||
graphene::chain::database& db = database();
|
graphene::chain::database& db = database();
|
||||||
auto& event_id_index = db.get_index_type<persistent_event_object_index>().indices().get<by_event_id>();
|
auto& event_id_index = db.get_index_type<persistent_event_object_index>().indices().get<by_event_id>();
|
||||||
|
auto& betting_market_group_id_index = db.get_index_type<persistent_betting_market_group_index>().indices().get<by_betting_market_group_id>();
|
||||||
|
auto& betting_market_id_index = db.get_index_type<persistent_betting_market_index>().indices().get<by_betting_market_id>();
|
||||||
|
|
||||||
for (const object_id_type& changed_object_id : changed_object_ids)
|
for (const object_id_type& changed_object_id : changed_object_ids)
|
||||||
{
|
{
|
||||||
|
|
@ -232,6 +344,78 @@ void bookie_plugin_impl::on_objects_changed(const vector<object_id_type>& change
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (changed_object_id.space() == betting_market_group_object::space_id &&
|
||||||
|
changed_object_id.type() == betting_market_group_object::type_id)
|
||||||
|
{
|
||||||
|
betting_market_group_id_type changed_betting_market_group_id = changed_object_id;
|
||||||
|
const betting_market_group_object* new_betting_market_group_obj = nullptr;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new_betting_market_group_obj = &changed_betting_market_group_id(db);
|
||||||
|
}
|
||||||
|
catch (fc::exception& e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
// new_betting_market_group_obj should point to the now-changed event_object, or null if it was removed from the database
|
||||||
|
|
||||||
|
const persistent_betting_market_group_object* old_betting_market_group_obj = nullptr;
|
||||||
|
|
||||||
|
auto persistent_betting_market_group_iter = betting_market_group_id_index.find(changed_betting_market_group_id);
|
||||||
|
if (persistent_betting_market_group_iter != betting_market_group_id_index.end())
|
||||||
|
old_betting_market_group_obj = &*persistent_betting_market_group_iter;
|
||||||
|
|
||||||
|
// and old_betting_market_group_obj is a pointer to our saved copy, or nullptr if it is a new object
|
||||||
|
if (old_betting_market_group_obj && new_betting_market_group_obj)
|
||||||
|
{
|
||||||
|
ilog("Modifying persistent betting_market_group object ${id}", ("id", changed_betting_market_group_id));
|
||||||
|
db.modify(*old_betting_market_group_obj, [&](persistent_betting_market_group_object& saved_betting_market_group_obj) {
|
||||||
|
saved_betting_market_group_obj.ephemeral_betting_market_group_object = *new_betting_market_group_obj;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (new_betting_market_group_obj)
|
||||||
|
{
|
||||||
|
ilog("Creating new persistent betting_market_group object ${id}", ("id", changed_betting_market_group_id));
|
||||||
|
db.create<persistent_betting_market_group_object>([&](persistent_betting_market_group_object& saved_betting_market_group_obj) {
|
||||||
|
saved_betting_market_group_obj.ephemeral_betting_market_group_object = *new_betting_market_group_obj;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (changed_object_id.space() == betting_market_object::space_id &&
|
||||||
|
changed_object_id.type() == betting_market_object::type_id)
|
||||||
|
{
|
||||||
|
betting_market_id_type changed_betting_market_id = changed_object_id;
|
||||||
|
const betting_market_object* new_betting_market_obj = nullptr;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new_betting_market_obj = &changed_betting_market_id(db);
|
||||||
|
}
|
||||||
|
catch (fc::exception& e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
// new_betting_market_obj should point to the now-changed event_object, or null if it was removed from the database
|
||||||
|
|
||||||
|
const persistent_betting_market_object* old_betting_market_obj = nullptr;
|
||||||
|
|
||||||
|
auto persistent_betting_market_iter = betting_market_id_index.find(changed_betting_market_id);
|
||||||
|
if (persistent_betting_market_iter != betting_market_id_index.end())
|
||||||
|
old_betting_market_obj = &*persistent_betting_market_iter;
|
||||||
|
|
||||||
|
// and old_betting_market_obj is a pointer to our saved copy, or nullptr if it is a new object
|
||||||
|
if (old_betting_market_obj && new_betting_market_obj)
|
||||||
|
{
|
||||||
|
ilog("Modifying persistent betting_market object ${id}", ("id", changed_betting_market_id));
|
||||||
|
db.modify(*old_betting_market_obj, [&](persistent_betting_market_object& saved_betting_market_obj) {
|
||||||
|
saved_betting_market_obj.ephemeral_betting_market_object = *new_betting_market_obj;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (new_betting_market_obj)
|
||||||
|
{
|
||||||
|
ilog("Creating new persistent betting_market object ${id}", ("id", changed_betting_market_id));
|
||||||
|
db.create<persistent_betting_market_object>([&](persistent_betting_market_object& saved_betting_market_obj) {
|
||||||
|
saved_betting_market_obj.ephemeral_betting_market_object = *new_betting_market_obj;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -239,29 +423,36 @@ void bookie_plugin_impl::on_block_applied( const signed_block& )
|
||||||
{
|
{
|
||||||
graphene::chain::database& db = database();
|
graphene::chain::database& db = database();
|
||||||
const vector<optional<operation_history_object> >& hist = db.get_applied_operations();
|
const vector<optional<operation_history_object> >& hist = db.get_applied_operations();
|
||||||
for( const optional< operation_history_object >& o_op : hist )
|
for( const optional<operation_history_object>& o_op : hist )
|
||||||
{
|
{
|
||||||
if( !o_op.valid() )
|
if( !o_op.valid() )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const operation_history_object& op = *o_op;
|
const operation_history_object& op = *o_op;
|
||||||
if( op.op.which() == operation::tag< bet_matched_operation >::value )
|
if( op.op.which() == operation::tag<bet_matched_operation>::value )
|
||||||
{
|
{
|
||||||
const bet_matched_operation& bet_matched_op = op.op.get<bet_matched_operation>();
|
const bet_matched_operation& bet_matched_op = op.op.get<bet_matched_operation>();
|
||||||
idump((bet_matched_op));
|
idump((bet_matched_op));
|
||||||
const asset& amount_bet = bet_matched_op.amount_bet;
|
const asset& amount_bet = bet_matched_op.amount_bet;
|
||||||
// object may no longer exist
|
// object may no longer exist
|
||||||
//const bet_object& bet = bet_matched_op.bet_id(db);
|
//const bet_object& bet = bet_matched_op.bet_id(db);
|
||||||
const betting_market_object& betting_market = bet_matched_op.betting_market_id(db);
|
auto& persistent_bets_by_bet_id = db.get_index_type<persistent_bet_index>().indices().get<by_bet_id>();
|
||||||
const betting_market_group_object& betting_market_group = betting_market.group_id(db);
|
auto bet_iter = persistent_bets_by_bet_id.find(bet_matched_op.bet_id);
|
||||||
db.modify( betting_market_group, [&]( betting_market_group_object& obj ){
|
assert(bet_iter != persistent_bets_by_bet_id.end());
|
||||||
obj.total_matched_bets_amount += amount_bet.amount;
|
if (bet_iter != persistent_bets_by_bet_id.end())
|
||||||
});
|
{
|
||||||
|
const bet_object& bet_obj = bet_iter->ephemeral_bet_object;
|
||||||
|
const betting_market_object& betting_market = bet_obj.betting_market_id(db); // TODO: this needs to look at the persistent version
|
||||||
|
const betting_market_group_object& betting_market_group = betting_market.group_id(db); // TODO: as does this
|
||||||
|
db.modify( betting_market_group, [&]( betting_market_group_object& obj ){
|
||||||
|
obj.total_matched_bets_amount += amount_bet.amount;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if( op.op.which() == operation::tag< event_create_operation >::value )
|
else if( op.op.which() == operation::tag<event_create_operation>::value )
|
||||||
{
|
{
|
||||||
FC_ASSERT(op.result.which() == operation_result::tag< object_id_type >::value);
|
FC_ASSERT(op.result.which() == operation_result::tag<object_id_type>::value);
|
||||||
//object_id_type object_id = op.result.get<object_id_type>();
|
//object_id_type object_id = op.result.get<object_id_type>();
|
||||||
event_id_type object_id = op.result.get<object_id_type>();
|
event_id_type object_id = op.result.get<object_id_type>();
|
||||||
FC_ASSERT( db.find_object(object_id), "invalid event specified" );
|
FC_ASSERT( db.find_object(object_id), "invalid event specified" );
|
||||||
|
|
@ -271,7 +462,7 @@ void bookie_plugin_impl::on_block_applied( const signed_block& )
|
||||||
localized_event_strings[pair.first].insert(event_string(object_id, pair.second));
|
localized_event_strings[pair.first].insert(event_string(object_id, pair.second));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( op.op.which() == operation::tag< event_update_operation >::value )
|
else if( op.op.which() == operation::tag<event_update_operation>::value )
|
||||||
{
|
{
|
||||||
const event_update_operation& event_create_op = op.op.get<event_update_operation>();
|
const event_update_operation& event_create_op = op.op.get<event_update_operation>();
|
||||||
if (!event_create_op.new_name.valid())
|
if (!event_create_op.new_name.valid())
|
||||||
|
|
@ -345,10 +536,8 @@ std::string bookie_plugin::plugin_name()const
|
||||||
return "bookie";
|
return "bookie";
|
||||||
}
|
}
|
||||||
|
|
||||||
void bookie_plugin::plugin_set_program_options(
|
void bookie_plugin::plugin_set_program_options(boost::program_options::options_description& cli,
|
||||||
boost::program_options::options_description& cli,
|
boost::program_options::options_description& cfg)
|
||||||
boost::program_options::options_description& cfg
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
//cli.add_options()
|
//cli.add_options()
|
||||||
// ("track-account", boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(), "Account ID to track history for (may specify multiple times)")
|
// ("track-account", boost::program_options::value<std::vector<std::string>>()->composing()->multitoken(), "Account ID to track history for (may specify multiple times)")
|
||||||
|
|
@ -363,8 +552,13 @@ void bookie_plugin::plugin_initialize(const boost::program_options::variables_ma
|
||||||
database().changed_objects.connect([&](const vector<object_id_type>& changed_object_ids, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts){ my->on_objects_changed(changed_object_ids); });
|
database().changed_objects.connect([&](const vector<object_id_type>& changed_object_ids, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts){ my->on_objects_changed(changed_object_ids); });
|
||||||
//auto event_index =
|
//auto event_index =
|
||||||
database().add_index<primary_index<detail::persistent_event_object_index> >();
|
database().add_index<primary_index<detail::persistent_event_object_index> >();
|
||||||
//event_index->add_secondary_index<detail::events_by_competitor_index>();
|
database().add_index<primary_index<detail::persistent_betting_market_group_index> >();
|
||||||
//LOAD_VALUE_SET(options, "tracked-accounts", my->_tracked_accounts, graphene::chain::account_id_type);
|
database().add_index<primary_index<detail::persistent_betting_market_index> >();
|
||||||
|
database().add_index<primary_index<detail::persistent_bet_index> >();
|
||||||
|
const primary_index<bet_object_index>& bet_object_idx = database().get_index_type<primary_index<bet_object_index> >();
|
||||||
|
primary_index<bet_object_index>& nonconst_bet_object_idx = const_cast<primary_index<bet_object_index>&>(bet_object_idx);
|
||||||
|
detail::persistent_bet_object_helper* persistent_bet_object_helper_index = nonconst_bet_object_idx.add_secondary_index<detail::persistent_bet_object_helper>();
|
||||||
|
persistent_bet_object_helper_index->set_plugin_instance(this);
|
||||||
|
|
||||||
ilog("bookie plugin: plugin_startup() end");
|
ilog("bookie plugin: plugin_startup() end");
|
||||||
}
|
}
|
||||||
|
|
@ -392,5 +586,8 @@ void bookie_plugin::get_events_containing_sub_string(std::vector<event_object>&
|
||||||
}
|
}
|
||||||
|
|
||||||
} }
|
} }
|
||||||
FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_event_object, (graphene::db::object), (event_object_id)(name)(season)(start_time)(event_group_id)(status)(scores) )
|
|
||||||
|
|
||||||
|
FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_event_object, (graphene::db::object), (event_object_id)(name)(season)(start_time)(event_group_id)(status)(scores) )
|
||||||
|
FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_betting_market_group_object, (graphene::db::object), (ephemeral_betting_market_group_object)(total_matched_bets_amount) )
|
||||||
|
FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_betting_market_object, (graphene::db::object), (ephemeral_betting_market_object) )
|
||||||
|
FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_bet_object, (graphene::db::object), (ephemeral_bet_object) )
|
||||||
|
|
|
||||||
|
|
@ -47,13 +47,16 @@ enum spaces {
|
||||||
enum bookie_object_type
|
enum bookie_object_type
|
||||||
{
|
{
|
||||||
persistent_event_object_type,
|
persistent_event_object_type,
|
||||||
|
persistent_betting_market_group_object_type,
|
||||||
|
persistent_betting_market_object_type,
|
||||||
|
persistent_bet_object_type,
|
||||||
BOOKIE_OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
BOOKIE_OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
class bookie_plugin_impl;
|
class bookie_plugin_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
class bookie_plugin : public graphene::app::plugin
|
class bookie_plugin : public graphene::app::plugin
|
||||||
|
|
@ -63,9 +66,8 @@ class bookie_plugin : public graphene::app::plugin
|
||||||
virtual ~bookie_plugin();
|
virtual ~bookie_plugin();
|
||||||
|
|
||||||
std::string plugin_name()const override;
|
std::string plugin_name()const override;
|
||||||
virtual void plugin_set_program_options(
|
virtual void plugin_set_program_options(boost::program_options::options_description& cli,
|
||||||
boost::program_options::options_description& cli,
|
boost::program_options::options_description& cfg) override;
|
||||||
boost::program_options::options_description& cfg) override;
|
|
||||||
virtual void plugin_initialize(const boost::program_options::variables_map& options) override;
|
virtual void plugin_initialize(const boost::program_options::variables_map& options) override;
|
||||||
virtual void plugin_startup() override;
|
virtual void plugin_startup() override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1686,7 +1686,6 @@ class wallet_api
|
||||||
bet_type back_or_lay,
|
bet_type back_or_lay,
|
||||||
asset amount_to_bet,
|
asset amount_to_bet,
|
||||||
bet_multiplier_type backer_multiplier,
|
bet_multiplier_type backer_multiplier,
|
||||||
share_type amount_reserved_for_fees,
|
|
||||||
bool broadcast = false);
|
bool broadcast = false);
|
||||||
|
|
||||||
signed_transaction propose_resolve_betting_market_group(
|
signed_transaction propose_resolve_betting_market_group(
|
||||||
|
|
|
||||||
|
|
@ -5408,7 +5408,6 @@ signed_transaction wallet_api::place_bet(
|
||||||
bet_type back_or_lay,
|
bet_type back_or_lay,
|
||||||
asset amount_to_bet,
|
asset amount_to_bet,
|
||||||
bet_multiplier_type backer_multiplier,
|
bet_multiplier_type backer_multiplier,
|
||||||
share_type amount_reserved_for_fees,
|
|
||||||
bool broadcast /*= false*/)
|
bool broadcast /*= false*/)
|
||||||
{
|
{
|
||||||
FC_ASSERT( !is_locked() );
|
FC_ASSERT( !is_locked() );
|
||||||
|
|
@ -5419,7 +5418,6 @@ signed_transaction wallet_api::place_bet(
|
||||||
bet_place_op.betting_market_id = betting_market_id;
|
bet_place_op.betting_market_id = betting_market_id;
|
||||||
bet_place_op.amount_to_bet = amount_to_bet;
|
bet_place_op.amount_to_bet = amount_to_bet;
|
||||||
bet_place_op.backer_multiplier = backer_multiplier;
|
bet_place_op.backer_multiplier = backer_multiplier;
|
||||||
bet_place_op.amount_reserved_for_fees = amount_reserved_for_fees;
|
|
||||||
bet_place_op.back_or_lay = back_or_lay;
|
bet_place_op.back_or_lay = back_or_lay;
|
||||||
|
|
||||||
signed_transaction tx;
|
signed_transaction tx;
|
||||||
|
|
|
||||||
|
|
@ -135,12 +135,12 @@ BOOST_AUTO_TEST_CASE(simple_bet_win)
|
||||||
transfer(account_id_type(), bob_id, asset(10000));
|
transfer(account_id_type(), bob_id, asset(10000));
|
||||||
|
|
||||||
// place bets at 10:1
|
// place bets at 10:1
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 11 * GRAPHENE_BETTING_ODDS_PRECISION, 2);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 11 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000, asset_id_type()), 11 * GRAPHENE_BETTING_ODDS_PRECISION, 20);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000, asset_id_type()), 11 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
// reverse positions at 1:1
|
// reverse positions at 1:1
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(1100, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 22);
|
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(1100, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(1100, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 22);
|
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(1100, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
@ -159,11 +159,11 @@ BOOST_AUTO_TEST_CASE(binned_order_books)
|
||||||
transfer(account_id_type(), bob_id, asset(10000));
|
transfer(account_id_type(), bob_id, asset(10000));
|
||||||
|
|
||||||
// place back bets at decimal odds of 1.55, 1.6, 1.65, 1.66, and 1.67
|
// place back bets at decimal odds of 1.55, 1.6, 1.65, 1.66, and 1.67
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 155 * GRAPHENE_BETTING_ODDS_PRECISION / 100, 2);
|
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 155 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 16 * GRAPHENE_BETTING_ODDS_PRECISION / 10, 2);
|
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 16 * GRAPHENE_BETTING_ODDS_PRECISION / 10);
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100, 2);
|
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 166 * GRAPHENE_BETTING_ODDS_PRECISION / 100, 2);
|
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 166 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 167 * GRAPHENE_BETTING_ODDS_PRECISION / 100, 2);
|
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 167 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||||
|
|
||||||
const auto& bet_odds_idx = db.get_index_type<bet_object_index>().indices().get<by_odds>();
|
const auto& bet_odds_idx = db.get_index_type<bet_object_index>().indices().get<by_odds>();
|
||||||
|
|
||||||
|
|
@ -187,7 +187,7 @@ BOOST_AUTO_TEST_CASE(binned_order_books)
|
||||||
// compute the matching lay order
|
// compute the matching lay order
|
||||||
share_type lay_amount = bet_object::get_approximate_matching_amount(binned_order.amount_to_bet, binned_order.backer_multiplier, bet_type::back, false /* round down */);
|
share_type lay_amount = bet_object::get_approximate_matching_amount(binned_order.amount_to_bet, binned_order.backer_multiplier, bet_type::back, false /* round down */);
|
||||||
ilog("Alice is laying with ${lay_amount} at odds ${odds} to match the binned back amount ${back_amount}", ("lay_amount", lay_amount)("odds", binned_order.backer_multiplier)("back_amount", binned_order.amount_to_bet));
|
ilog("Alice is laying with ${lay_amount} at odds ${odds} to match the binned back amount ${back_amount}", ("lay_amount", lay_amount)("odds", binned_order.backer_multiplier)("back_amount", binned_order.amount_to_bet));
|
||||||
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(lay_amount, asset_id_type()), binned_order.backer_multiplier, 2);
|
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(lay_amount, asset_id_type()), binned_order.backer_multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
bet_iter = bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id));
|
bet_iter = bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id));
|
||||||
|
|
@ -201,11 +201,11 @@ BOOST_AUTO_TEST_CASE(binned_order_books)
|
||||||
BOOST_CHECK(bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id)) == bet_odds_idx.end());
|
BOOST_CHECK(bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id)) == bet_odds_idx.end());
|
||||||
|
|
||||||
// place lay bets at decimal odds of 1.55, 1.6, 1.65, 1.66, and 1.67
|
// place lay bets at decimal odds of 1.55, 1.6, 1.65, 1.66, and 1.67
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 155 * GRAPHENE_BETTING_ODDS_PRECISION / 100, 2);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 155 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 16 * GRAPHENE_BETTING_ODDS_PRECISION / 10, 2);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 16 * GRAPHENE_BETTING_ODDS_PRECISION / 10);
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100, 2);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 165 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 166 * GRAPHENE_BETTING_ODDS_PRECISION / 100, 2);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 166 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 167 * GRAPHENE_BETTING_ODDS_PRECISION / 100, 2);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 167 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||||
|
|
||||||
binned_orders_point_one = bookie_api.get_binned_order_book(capitals_win_market.id, 1);
|
binned_orders_point_one = bookie_api.get_binned_order_book(capitals_win_market.id, 1);
|
||||||
idump((binned_orders_point_one));
|
idump((binned_orders_point_one));
|
||||||
|
|
@ -219,7 +219,7 @@ BOOST_AUTO_TEST_CASE(binned_order_books)
|
||||||
// compute the matching lay order
|
// compute the matching lay order
|
||||||
share_type back_amount = bet_object::get_approximate_matching_amount(binned_order.amount_to_bet, binned_order.backer_multiplier, bet_type::lay, false /* round down */);
|
share_type back_amount = bet_object::get_approximate_matching_amount(binned_order.amount_to_bet, binned_order.backer_multiplier, bet_type::lay, false /* round down */);
|
||||||
ilog("Alice is backing with ${back_amount} at odds ${odds} to match the binned lay amount ${lay_amount}", ("back_amount", back_amount)("odds", binned_order.backer_multiplier)("lay_amount", binned_order.amount_to_bet));
|
ilog("Alice is backing with ${back_amount} at odds ${odds} to match the binned lay amount ${lay_amount}", ("back_amount", back_amount)("odds", binned_order.backer_multiplier)("lay_amount", binned_order.amount_to_bet));
|
||||||
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(back_amount, asset_id_type()), binned_order.backer_multiplier, 2);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(back_amount, asset_id_type()), binned_order.backer_multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
bet_iter = bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id));
|
bet_iter = bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id));
|
||||||
|
|
@ -247,12 +247,12 @@ BOOST_AUTO_TEST_CASE( peerplays_sport_create_test )
|
||||||
transfer(account_id_type(), bob_id, asset(10000000));
|
transfer(account_id_type(), bob_id, asset(10000000));
|
||||||
|
|
||||||
// have bob lay a bet for 1M (+20k fees) at 1:1 odds
|
// have bob lay a bet for 1M (+20k fees) at 1:1 odds
|
||||||
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 */);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
// have alice back a matching bet at 1:1 odds (also costing 1.02M)
|
// have alice back a matching bet at 1:1 odds (also costing 1.02M)
|
||||||
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 */);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
// caps win
|
// caps win
|
||||||
resolve_betting_market_group(moneyline_betting_markets.id,
|
resolve_betting_market_group(moneyline_betting_markets.id,
|
||||||
|
|
@ -263,8 +263,8 @@ BOOST_AUTO_TEST_CASE( peerplays_sport_create_test )
|
||||||
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
|
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;
|
uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
||||||
BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value));
|
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(alice_id, asset_id_type()), 10000000 - 1000000 + 2000000 - rake_value);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
@ -281,25 +281,66 @@ BOOST_AUTO_TEST_CASE( cancel_unmatched_in_betting_group_test )
|
||||||
transfer(account_id_type(), bob_id, asset(10000000));
|
transfer(account_id_type(), bob_id, asset(10000000));
|
||||||
|
|
||||||
// have bob lay a bet for 1M (+20k fees) at 1:1 odds
|
// have bob lay a bet for 1M (+20k fees) at 1:1 odds
|
||||||
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 */);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
// have alice back a matching bet at 1:1 odds (also costing 1.02M)
|
// have alice back a matching bet at 1:1 odds (also costing 1.02M)
|
||||||
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 */);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
// place unmatched
|
// place unmatched
|
||||||
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(500, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 10);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(500, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
place_bet(bob_id, blackhawks_win_market.id, bet_type::lay, asset(600, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 20);
|
place_bet(bob_id, blackhawks_win_market.id, bet_type::lay, asset(600, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 - 500 - 10);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 500);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000 - 600 - 20);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 600);
|
||||||
|
|
||||||
// cancel unmatched
|
// cancel unmatched
|
||||||
cancel_unmatched_bets(moneyline_betting_markets.id);
|
cancel_unmatched_bets(moneyline_betting_markets.id);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(inexact_odds)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ACTORS( (alice)(bob) );
|
||||||
|
CREATE_ICE_HOCKEY_BETTING_MARKET();
|
||||||
|
|
||||||
|
transfer(account_id_type(), alice_id, asset(10000000));
|
||||||
|
share_type alice_expected_balance = 10000000;
|
||||||
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance.value);
|
||||||
|
|
||||||
|
// lay 47 at 1.94 odds (50:47) -- this is an exact amount, nothing surprising should happen here
|
||||||
|
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(47, asset_id_type()), 194 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||||
|
alice_expected_balance -= 47;
|
||||||
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance.value);
|
||||||
|
|
||||||
|
// lay 100 at 1.91 odds (100:91) -- this is an inexact match, we should get refunded 9 and leave a bet for 91 on the books
|
||||||
|
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(100, asset_id_type()), 191 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||||
|
alice_expected_balance -= 91;
|
||||||
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), alice_expected_balance.value);
|
||||||
|
|
||||||
|
|
||||||
|
transfer(account_id_type(), bob_id, asset(10000000));
|
||||||
|
share_type bob_expected_balance = 10000000;
|
||||||
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), bob_expected_balance.value);
|
||||||
|
|
||||||
|
// now have bob match it with a back of 300 at 1.91
|
||||||
|
// This should:
|
||||||
|
// match the full 47 @ 1.94 with 50
|
||||||
|
// match the full 91 @ 1.91 with 100
|
||||||
|
// leaving 150
|
||||||
|
// back bets at 100:91 must be a multiple of 100, so refund 50
|
||||||
|
// leaves a back bet of 100 @ 1.91 on the books
|
||||||
|
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(300, asset_id_type()), 191 * GRAPHENE_BETTING_ODDS_PRECISION / 100);
|
||||||
|
bob_expected_balance -= 250;
|
||||||
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), bob_expected_balance.value);
|
||||||
|
}
|
||||||
|
FC_LOG_AND_RETHROW()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE( chained_market_create_test )
|
BOOST_AUTO_TEST_CASE( chained_market_create_test )
|
||||||
{
|
{
|
||||||
// Often you will want to create several objects that reference each other at the same time.
|
// Often you will want to create several objects that reference each other at the same time.
|
||||||
|
|
@ -430,12 +471,12 @@ struct simple_bet_test_fixture : database_fixture {
|
||||||
transfer(account_id_type(), bob_id, asset(10000));
|
transfer(account_id_type(), bob_id, asset(10000));
|
||||||
|
|
||||||
// place bets at 10:1
|
// place bets at 10:1
|
||||||
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 11 * GRAPHENE_BETTING_ODDS_PRECISION, 2);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(100, asset_id_type()), 11 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000, asset_id_type()), 11 * GRAPHENE_BETTING_ODDS_PRECISION, 20);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000, asset_id_type()), 11 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
// reverse positions at 1:1
|
// reverse positions at 1:1
|
||||||
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(1100, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 22);
|
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(1100, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(1100, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 22);
|
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(1100, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
capitals_win_betting_market_id = capitals_win_market.id;
|
capitals_win_betting_market_id = capitals_win_market.id;
|
||||||
blackhawks_win_betting_market_id = blackhawks_win_market.id;
|
blackhawks_win_betting_market_id = blackhawks_win_market.id;
|
||||||
|
|
@ -459,13 +500,13 @@ BOOST_AUTO_TEST_CASE( win )
|
||||||
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
|
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
|
||||||
uint32_t rake_value;
|
uint32_t rake_value;
|
||||||
//rake_value = (-100 + 1100 - 1100) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
//rake_value = (-100 + 1100 - 1100) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
||||||
// alice starts with 10000, pays 100 (bet) + 2 (fee), wins 1100, then pays 1100 (bet) + 22 (fee), wins 0
|
// alice starts with 10000, pays 100 (bet), wins 1100, then pays 1100 (bet), wins 0
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000 - 100 - 2 + 1100 - 1100 - 22 + 0);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000 - 100 + 1100 - 1100 + 0);
|
||||||
|
|
||||||
rake_value = (-1000 - 1100 + 2200) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
rake_value = (-1000 - 1100 + 2200) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
||||||
// bob starts with 10000, pays 1000 (bet) + 20 (fee), wins 0, then pays 1100 (bet) + 22 (fee), wins 2200
|
// bob starts with 10000, pays 1000 (bet), wins 0, then pays 1100 (bet), wins 2200
|
||||||
BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value));
|
BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value));
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000 - 1000 - 20 + 0 - 1100 - 22 + 2200 - rake_value);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000 - 1000 + 0 - 1100 + 2200 - rake_value);
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -482,13 +523,13 @@ BOOST_AUTO_TEST_CASE( not_win )
|
||||||
|
|
||||||
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
|
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
|
||||||
uint32_t rake_value = (-100 - 1100 + 2200) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
uint32_t rake_value = (-100 - 1100 + 2200) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
||||||
// alice starts with 10000, pays 100 (bet) + 2 (fee), wins 0, then pays 1100 (bet) + 22 (fee), wins 2200
|
// alice starts with 10000, pays 100 (bet), wins 0, then pays 1100 (bet), wins 2200
|
||||||
BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value));
|
BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value));
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000 - 100 - 2 + 0 - 1100 - 22 + 2200 - rake_value);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000 - 100 + 0 - 1100 + 2200 - rake_value);
|
||||||
|
|
||||||
//rake_value = (-1000 + 1100 - 1100) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
//rake_value = (-1000 + 1100 - 1100) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
||||||
// bob starts with 10000, pays 1000 (bet) + 20 (fee), wins 1100, then pays 1100 (bet) + 22 (fee), wins 0
|
// bob starts with 10000, pays 1000 (bet), wins 1100, then pays 1100 (bet), wins 0
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000 - 1000 - 20 + 1100 - 1100 - 22 + 0);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000 - 1000 + 1100 - 1100 + 0);
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -523,21 +564,21 @@ struct simple_bet_test_fixture_2 : database_fixture {
|
||||||
transfer(account_id_type(), bob_id, asset(10000));
|
transfer(account_id_type(), bob_id, asset(10000));
|
||||||
|
|
||||||
// alice backs 1000 at 1:1, matches
|
// alice backs 1000 at 1:1, matches
|
||||||
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 20);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 20);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
// now alice lays at 2500 at 1:1. This should require a deposit of 500, with the remaining 200 being funded from exposure
|
// now alice lays at 2500 at 1:1. This should require a deposit of 500, with the remaining 200 being funded from exposure
|
||||||
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(2500, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 50);
|
place_bet(alice_id, capitals_win_market.id, bet_type::lay, asset(2500, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
// match the bet bit by bit. bob matches 500 of alice's 2500 bet. This effectively cancels half of bob's lay position
|
// match the bet bit by bit. bob matches 500 of alice's 2500 bet. This effectively cancels half of bob's lay position
|
||||||
// so he immediately gets 500 back. It reduces alice's back position, but doesn't return any money to her (all 2000 of her exposure
|
// so he immediately gets 500 back. It reduces alice's back position, but doesn't return any money to her (all 2000 of her exposure
|
||||||
// was already "promised" to her lay bet, so the 500 she would have received is placed in her refundable_unmatched_bets)
|
// was already "promised" to her lay bet, so the 500 she would have received is placed in her refundable_unmatched_bets)
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(500, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 10);
|
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(500, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
// match another 500, which will fully cancel bob's lay position and return the other 500 he had locked up in his position.
|
// match another 500, which will fully cancel bob's lay position and return the other 500 he had locked up in his position.
|
||||||
// alice's back position is now canceled, 1500 remains of her unmatched lay bet, and the 500 from canceling her position has
|
// alice's back position is now canceled, 1500 remains of her unmatched lay bet, and the 500 from canceling her position has
|
||||||
// been moved to her refundable_unmatched_bets
|
// been moved to her refundable_unmatched_bets
|
||||||
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(500, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 10);
|
place_bet(bob_id, capitals_win_market.id, bet_type::back, asset(500, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
capitals_win_betting_market_id = capitals_win_market.id;
|
capitals_win_betting_market_id = capitals_win_market.id;
|
||||||
}
|
}
|
||||||
|
|
@ -554,9 +595,9 @@ BOOST_AUTO_TEST_CASE(sport_update_test)
|
||||||
update_sport(ice_hockey.id, {{"en", "Hockey on Ice"}, {"zh_Hans", "冰"}, {"ja", "アイスホッケ"}});
|
update_sport(ice_hockey.id, {{"en", "Hockey on Ice"}, {"zh_Hans", "冰"}, {"ja", "アイスホッケ"}});
|
||||||
|
|
||||||
transfer(account_id_type(), alice_id, asset(10000000));
|
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 */);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
@ -571,7 +612,7 @@ BOOST_AUTO_TEST_CASE(event_group_update_test)
|
||||||
transfer(account_id_type(), alice_id, asset(10000000));
|
transfer(account_id_type(), alice_id, asset(10000000));
|
||||||
transfer(account_id_type(), bob_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 */);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
const sport_object& ice_on_hockey = create_sport({{"en", "Hockey on Ice"}, {"zh_Hans", "冰球"}, {"ja", "アイスホッケー"}}); \
|
const sport_object& ice_on_hockey = create_sport({{"en", "Hockey on Ice"}, {"zh_Hans", "冰球"}, {"ja", "アイスホッケー"}}); \
|
||||||
fc::optional<object_id_type> sport_id = ice_on_hockey.id;
|
fc::optional<object_id_type> sport_id = ice_on_hockey.id;
|
||||||
|
|
@ -582,10 +623,10 @@ BOOST_AUTO_TEST_CASE(event_group_update_test)
|
||||||
update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>());
|
update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>());
|
||||||
update_event_group(nhl.id, sport_id, name);
|
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 */);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
// caps win
|
// caps win
|
||||||
resolve_betting_market_group(moneyline_betting_markets.id,
|
resolve_betting_market_group(moneyline_betting_markets.id,
|
||||||
|
|
@ -596,8 +637,8 @@ BOOST_AUTO_TEST_CASE(event_group_update_test)
|
||||||
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
|
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;
|
uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
||||||
BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value));
|
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(alice_id, asset_id_type()), 10000000 - 1000000 + 2000000 - rake_value);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
@ -613,7 +654,7 @@ BOOST_AUTO_TEST_CASE(event_update_test)
|
||||||
transfer(account_id_type(), alice_id, asset(10000000));
|
transfer(account_id_type(), alice_id, asset(10000000));
|
||||||
transfer(account_id_type(), bob_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 */);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
fc::optional<internationalized_string_type> empty;
|
fc::optional<internationalized_string_type> empty;
|
||||||
fc::optional<internationalized_string_type> name = internationalized_string_type({{"en", "Washington Capitals vs. Chicago Blackhawks"}, {"zh_Hans", "華盛頓首都隊/芝加哥黑"}, {"ja", "ワシントン・キャピタルズ/シカゴ・ブラックホーク"}});
|
fc::optional<internationalized_string_type> name = internationalized_string_type({{"en", "Washington Capitals vs. Chicago Blackhawks"}, {"zh_Hans", "華盛頓首都隊/芝加哥黑"}, {"ja", "ワシントン・キャピタルズ/シカゴ・ブラックホーク"}});
|
||||||
|
|
@ -631,10 +672,10 @@ BOOST_AUTO_TEST_CASE(event_update_test)
|
||||||
|
|
||||||
update_event(capitals_vs_blackhawks.id, event_group_id , empty, empty, empty_bool);
|
update_event(capitals_vs_blackhawks.id, event_group_id , empty, empty, empty_bool);
|
||||||
|
|
||||||
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 */);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
// caps win
|
// caps win
|
||||||
resolve_betting_market_group(moneyline_betting_markets.id,
|
resolve_betting_market_group(moneyline_betting_markets.id,
|
||||||
|
|
@ -645,8 +686,8 @@ BOOST_AUTO_TEST_CASE(event_update_test)
|
||||||
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
|
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;
|
uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
||||||
BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value));
|
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(alice_id, asset_id_type()), 10000000 - 1000000 + 2000000 - rake_value);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
@ -667,9 +708,9 @@ BOOST_AUTO_TEST_CASE(betting_market_rules_update_test)
|
||||||
update_betting_market_rules(betting_market_rules.id, name, desc);
|
update_betting_market_rules(betting_market_rules.id, name, desc);
|
||||||
|
|
||||||
transfer(account_id_type(), alice_id, asset(10000000));
|
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 */);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
@ -682,7 +723,7 @@ BOOST_AUTO_TEST_CASE(betting_market_group_update_test)
|
||||||
CREATE_ICE_HOCKEY_BETTING_MARKET();
|
CREATE_ICE_HOCKEY_BETTING_MARKET();
|
||||||
|
|
||||||
transfer(account_id_type(), alice_id, asset(10000000));
|
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 */);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
fc::optional<internationalized_string_type> dempty;
|
fc::optional<internationalized_string_type> dempty;
|
||||||
fc::optional<object_id_type> empty_object_id;
|
fc::optional<object_id_type> empty_object_id;
|
||||||
|
|
@ -702,10 +743,10 @@ BOOST_AUTO_TEST_CASE(betting_market_group_update_test)
|
||||||
update_betting_market_group(moneyline_betting_markets.id, new_desc, new_event, new_rule, freeze);
|
update_betting_market_group(moneyline_betting_markets.id, new_desc, new_event, new_rule, freeze);
|
||||||
|
|
||||||
transfer(account_id_type(), bob_id, asset(10000000));
|
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 */);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
// caps win
|
// caps win
|
||||||
resolve_betting_market_group(moneyline_betting_markets.id,
|
resolve_betting_market_group(moneyline_betting_markets.id,
|
||||||
|
|
@ -716,8 +757,8 @@ BOOST_AUTO_TEST_CASE(betting_market_group_update_test)
|
||||||
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
|
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;
|
uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
||||||
BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value));
|
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(alice_id, asset_id_type()), 10000000 - 1000000 + 2000000 - rake_value);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
@ -730,7 +771,7 @@ BOOST_AUTO_TEST_CASE(betting_market_update_test)
|
||||||
CREATE_ICE_HOCKEY_BETTING_MARKET();
|
CREATE_ICE_HOCKEY_BETTING_MARKET();
|
||||||
|
|
||||||
transfer(account_id_type(), alice_id, asset(10000000));
|
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 */);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
const betting_market_group_object& new_moneyline_betting_markets = create_betting_market_group({{"en", "New Moneyline"}}, capitals_vs_blackhawks.id, betting_market_rules.id, asset_id_type()); \
|
const betting_market_group_object& new_moneyline_betting_markets = create_betting_market_group({{"en", "New Moneyline"}}, capitals_vs_blackhawks.id, betting_market_rules.id, asset_id_type()); \
|
||||||
fc::optional<object_id_type> betting_market_group = new_moneyline_betting_markets.id;
|
fc::optional<object_id_type> betting_market_group = new_moneyline_betting_markets.id;
|
||||||
|
|
@ -744,10 +785,10 @@ BOOST_AUTO_TEST_CASE(betting_market_update_test)
|
||||||
update_betting_market(blackhawks_win_market.id, betting_market_group, fc::optional<internationalized_string_type>());
|
update_betting_market(blackhawks_win_market.id, betting_market_group, fc::optional<internationalized_string_type>());
|
||||||
|
|
||||||
transfer(account_id_type(), bob_id, asset(10000000));
|
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 */);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
// caps win
|
// caps win
|
||||||
resolve_betting_market_group(new_moneyline_betting_markets.id,
|
resolve_betting_market_group(new_moneyline_betting_markets.id,
|
||||||
|
|
@ -758,8 +799,8 @@ BOOST_AUTO_TEST_CASE(betting_market_update_test)
|
||||||
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
|
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;
|
uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
||||||
BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value));
|
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(alice_id, asset_id_type()), 10000000 - 1000000 + 2000000 - rake_value);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
@ -780,9 +821,9 @@ BOOST_AUTO_TEST_SUITE(other_betting_tests)
|
||||||
{ \
|
{ \
|
||||||
if (1) \
|
if (1) \
|
||||||
{ \
|
{ \
|
||||||
edump(("###")); \
|
elog("###"); \
|
||||||
edump((e.to_detail_string())); \
|
edump((e.to_detail_string())); \
|
||||||
edump(("###")); \
|
elog("###"); \
|
||||||
} \
|
} \
|
||||||
FC_ASSERT(e.to_detail_string().find(reason) != \
|
FC_ASSERT(e.to_detail_string().find(reason) != \
|
||||||
std::string::npos, "expected error hasn't occured");\
|
std::string::npos, "expected error hasn't occured");\
|
||||||
|
|
@ -803,7 +844,7 @@ BOOST_FIXTURE_TEST_CASE( another_event_group_update_test, database_fixture)
|
||||||
transfer(account_id_type(), alice_id, asset(10000000));
|
transfer(account_id_type(), alice_id, asset(10000000));
|
||||||
transfer(account_id_type(), bob_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 */);
|
place_bet(alice_id, capitals_win_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
fc::optional<internationalized_string_type> name = internationalized_string_type({{"en", "IBM"}, {"zh_Hans", "國家冰球聯"}, {"ja", "ナショナルホッケーリー"}});
|
fc::optional<internationalized_string_type> name = internationalized_string_type({{"en", "IBM"}, {"zh_Hans", "國家冰球聯"}, {"ja", "ナショナルホッケーリー"}});
|
||||||
|
|
||||||
|
|
@ -832,10 +873,10 @@ BOOST_FIXTURE_TEST_CASE( another_event_group_update_test, database_fixture)
|
||||||
//GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception);
|
//GRAPHENE_REQUIRE_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception);
|
||||||
TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception, "invalid sport specified");
|
TRY_EXPECT_THROW(try_update_event_group(nhl.id, sport_id, fc::optional<internationalized_string_type>()), fc::exception, "invalid sport specified");
|
||||||
|
|
||||||
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 */);
|
place_bet(bob_id, capitals_win_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
// caps win
|
// caps win
|
||||||
resolve_betting_market_group(moneyline_betting_markets.id,
|
resolve_betting_market_group(moneyline_betting_markets.id,
|
||||||
|
|
@ -846,8 +887,8 @@ BOOST_FIXTURE_TEST_CASE( another_event_group_update_test, database_fixture)
|
||||||
uint16_t rake_fee_percentage = db.get_global_properties().parameters.betting_rake_fee_percentage;
|
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;
|
uint32_t rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
||||||
BOOST_TEST_MESSAGE("Rake value " + std::to_string(rake_value));
|
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(alice_id, asset_id_type()), 10000000 - 1000000 + 2000000 - rake_value);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
@ -895,17 +936,17 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_sf_test )
|
||||||
BOOST_TEST_MESSAGE("cilic_wins_market " << fc::variant(cilic_wins_market.id).as<std::string>());
|
BOOST_TEST_MESSAGE("cilic_wins_market " << fc::variant(cilic_wins_market.id).as<std::string>());
|
||||||
BOOST_TEST_MESSAGE("querrey_wins_market " << fc::variant(querrey_wins_market.id).as<std::string>());
|
BOOST_TEST_MESSAGE("querrey_wins_market " << fc::variant(querrey_wins_market.id).as<std::string>());
|
||||||
|
|
||||||
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(alice_id, berdych_wins_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
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 */);
|
place_bet(bob_id, berdych_wins_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
place_bet(alice_id, cilic_wins_market.id, bet_type::back, asset(100000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 100000 / 50 /* chain defaults to 2% fees */);
|
place_bet(alice_id, cilic_wins_market.id, bet_type::back, asset(100000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
place_bet(bob_id, cilic_wins_market.id, bet_type::lay, asset(100000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 100000 / 50 /* chain defaults to 2% fees */);
|
place_bet(bob_id, cilic_wins_market.id, bet_type::lay, asset(100000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 - 100000 - 2000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 100000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000 - 100000 - 2000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 100000);
|
||||||
|
|
||||||
// federer wins
|
// federer wins
|
||||||
resolve_betting_market_group(moneyline_berdych_vs_federer.id,
|
resolve_betting_market_group(moneyline_berdych_vs_federer.id,
|
||||||
|
|
@ -915,8 +956,8 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_sf_test )
|
||||||
uint32_t bob_rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
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_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 - 100000 - 2000);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 100000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000 - 100000 - 2000 + 2000000 - bob_rake_value);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 100000 + 2000000 - bob_rake_value);
|
||||||
|
|
||||||
// cilic wins
|
// cilic wins
|
||||||
resolve_betting_market_group(moneyline_cilic_vs_querrey.id,
|
resolve_betting_market_group(moneyline_cilic_vs_querrey.id,
|
||||||
|
|
@ -926,8 +967,8 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_sf_test )
|
||||||
uint32_t alice_rake_value = (-100000 + 200000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
uint32_t alice_rake_value = (-100000 + 200000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
||||||
BOOST_TEST_MESSAGE("Alice rake value " + std::to_string(alice_rake_value));
|
BOOST_TEST_MESSAGE("Alice rake value " + std::to_string(alice_rake_value));
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 - 100000 - 2000 + 200000 - alice_rake_value);
|
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 100000 + 200000 - alice_rake_value);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000 - 100000 - 2000 + 2000000 - bob_rake_value);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 100000 + 2000000 - bob_rake_value);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
@ -949,8 +990,8 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_final_test )
|
||||||
BOOST_TEST_MESSAGE("federer_wins_final_market " << fc::variant(federer_wins_final_market.id).as<std::string>());
|
BOOST_TEST_MESSAGE("federer_wins_final_market " << fc::variant(federer_wins_final_market.id).as<std::string>());
|
||||||
BOOST_TEST_MESSAGE("cilic_wins_final_market " << fc::variant(cilic_wins_final_market.id).as<std::string>());
|
BOOST_TEST_MESSAGE("cilic_wins_final_market " << fc::variant(cilic_wins_final_market.id).as<std::string>());
|
||||||
|
|
||||||
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(alice_id, cilic_wins_final_market.id, bet_type::back, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
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 */);
|
place_bet(bob_id, cilic_wins_final_market.id, bet_type::lay, asset(1000000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
|
||||||
|
|
||||||
betting_market_group_id_type moneyline_cilic_vs_federer_id = moneyline_cilic_vs_federer.id;
|
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 cilic_wins_final_market_id = cilic_wins_final_market.id;
|
||||||
|
|
@ -966,8 +1007,8 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_final_test )
|
||||||
const betting_market_group_object& betting_market_group = moneyline_cilic_vs_federer_id(db);
|
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(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(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000);
|
||||||
|
|
||||||
// federer wins
|
// federer wins
|
||||||
resolve_betting_market_group(moneyline_cilic_vs_federer_id,
|
resolve_betting_market_group(moneyline_cilic_vs_federer_id,
|
||||||
|
|
@ -977,8 +1018,8 @@ BOOST_AUTO_TEST_CASE( wimbledon_2017_gentelmen_singles_final_test )
|
||||||
uint32_t bob_rake_value = (-1000000 + 2000000) * rake_fee_percentage / GRAPHENE_1_PERCENT / 100;
|
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_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(alice_id, asset_id_type()), 10000000 - 1000000);
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000 + 2000000 - bob_rake_value);
|
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 + 2000000 - bob_rake_value);
|
||||||
|
|
||||||
} FC_LOG_AND_RETHROW()
|
} FC_LOG_AND_RETHROW()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,6 @@ void database_fixture::verify_asset_supplies( const database& db )
|
||||||
for (const bet_object& o : db.get_index_type<bet_object_index>().indices())
|
for (const bet_object& o : db.get_index_type<bet_object_index>().indices())
|
||||||
{
|
{
|
||||||
total_balances[o.amount_to_bet.asset_id] += o.amount_to_bet.amount;
|
total_balances[o.amount_to_bet.asset_id] += o.amount_to_bet.amount;
|
||||||
total_balances[o.amount_to_bet.asset_id] += o.amount_reserved_for_fees;
|
|
||||||
}
|
}
|
||||||
for (const betting_market_position_object& o : db.get_index_type<betting_market_position_index>().indices())
|
for (const betting_market_position_object& o : db.get_index_type<betting_market_position_index>().indices())
|
||||||
{
|
{
|
||||||
|
|
@ -1396,14 +1395,13 @@ void database_fixture::update_betting_market(betting_market_id_type betting_mark
|
||||||
} FC_CAPTURE_AND_RETHROW( (betting_market_id) (group_id) (payout_condition) ) }
|
} 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)
|
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)
|
||||||
{ try {
|
{ try {
|
||||||
bet_place_operation bet_place_op;
|
bet_place_operation bet_place_op;
|
||||||
bet_place_op.bettor_id = bettor_id;
|
bet_place_op.bettor_id = bettor_id;
|
||||||
bet_place_op.betting_market_id = betting_market_id;
|
bet_place_op.betting_market_id = betting_market_id;
|
||||||
bet_place_op.amount_to_bet = amount_to_bet;
|
bet_place_op.amount_to_bet = amount_to_bet;
|
||||||
bet_place_op.backer_multiplier = backer_multiplier;
|
bet_place_op.backer_multiplier = backer_multiplier;
|
||||||
bet_place_op.amount_reserved_for_fees = amount_reserved_for_fees;
|
|
||||||
bet_place_op.back_or_lay = back_or_lay;
|
bet_place_op.back_or_lay = back_or_lay;
|
||||||
|
|
||||||
trx.operations.push_back(bet_place_op);
|
trx.operations.push_back(bet_place_op);
|
||||||
|
|
|
||||||
|
|
@ -319,7 +319,7 @@ struct database_fixture {
|
||||||
/*fc::optional<internationalized_string_type> description,*/
|
/*fc::optional<internationalized_string_type> description,*/
|
||||||
fc::optional<internationalized_string_type> payout_condition);
|
fc::optional<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 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);
|
||||||
void resolve_betting_market_group(betting_market_group_id_type betting_market_group_id, std::map<betting_market_id_type, betting_market_resolution_type> resolutions);
|
void resolve_betting_market_group(betting_market_group_id_type betting_market_group_id, std::map<betting_market_id_type, betting_market_resolution_type> resolutions);
|
||||||
void cancel_unmatched_bets(betting_market_group_id_type betting_market_group_id);
|
void cancel_unmatched_bets(betting_market_group_id_type betting_market_group_id);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue