Start implementing bettimg_market_resolve op
This commit is contained in:
parent
fd38d385ca
commit
784b11059f
9 changed files with 126 additions and 12 deletions
|
|
@ -209,6 +209,7 @@ struct get_impacted_account_visitor
|
|||
void operator()( const event_create_operation& op ) {}
|
||||
void operator()( const betting_market_group_create_operation& op ) {}
|
||||
void operator()( const betting_market_create_operation& op ) {}
|
||||
void operator()( const betting_market_resolve_operation& op ) {}
|
||||
void operator()( const bet_place_operation& op )
|
||||
{
|
||||
_impacted.insert( op.bettor_id );
|
||||
|
|
|
|||
|
|
@ -179,4 +179,17 @@ void_result bet_cancel_evaluator::do_apply(const bet_cancel_operation& op)
|
|||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
void_result betting_market_resolve_evaluator::do_evaluate(const betting_market_resolve_operation& op)
|
||||
{ try {
|
||||
const database& d = db();
|
||||
_betting_market = &op.betting_market_id(d);
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
void_result betting_market_resolve_evaluator::do_apply(const betting_market_resolve_operation& op)
|
||||
{ try {
|
||||
db().resolve_betting_market(*_betting_market, op.resolution);
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -19,17 +19,50 @@ void database::cancel_bet( const bet_object& bet, bool create_virtual_op )
|
|||
remove(bet);
|
||||
}
|
||||
|
||||
void database::resolve_betting_market(const betting_market_object& betting_market,
|
||||
betting_market_resolution_type resolution)
|
||||
{
|
||||
// TODO: cancel all unmatched bets on the books for this market
|
||||
auto& index = get_index_type<betting_market_position_index>().indices().get<by_bettor_betting_market>();
|
||||
auto position_itr = index.lower_bound(std::make_tuple(betting_market.id));
|
||||
while (position_itr != index.end() &&
|
||||
position_itr->betting_market_id == betting_market.id)
|
||||
{
|
||||
const betting_market_position_object& position = *position_itr;
|
||||
++position_itr;
|
||||
|
||||
share_type payout_amount = 0;
|
||||
switch (resolution)
|
||||
{
|
||||
case betting_market_resolution_type::win:
|
||||
payout_amount += position.pay_if_payout_condition;
|
||||
payout_amount += position.pay_if_not_canceled;
|
||||
break;
|
||||
case betting_market_resolution_type::not_win:
|
||||
payout_amount += position.pay_if_not_payout_condition;
|
||||
payout_amount += position.pay_if_not_canceled;
|
||||
break;
|
||||
case betting_market_resolution_type::cancel:
|
||||
payout_amount += position.pay_if_canceled;
|
||||
break;
|
||||
}
|
||||
|
||||
adjust_balance(position.bettor_id, asset(payout_amount, betting_market.asset_id));
|
||||
//TODO: pay the fees to the correct (dividend-distribution) account
|
||||
adjust_balance(account_id_type(), asset(position.fees_collected, betting_market.asset_id));
|
||||
//TODO: generate a virtual op to notify the bettor that they won or lost
|
||||
|
||||
remove(position);
|
||||
}
|
||||
remove(betting_market);
|
||||
}
|
||||
|
||||
bool maybe_cull_small_bet( database& db, const bet_object& bet_object_to_cull )
|
||||
{
|
||||
/**
|
||||
* There are times when the AMOUNT_FOR_SALE * SALE_PRICE == 0 which means that we
|
||||
* have hit the limit where the seller is asking for nothing in return. When this
|
||||
* happens we must refund any balance back to the seller, it is too small to be
|
||||
* sold at the sale price.
|
||||
*
|
||||
* If the order is a taker order (as opposed to a maker order), so the price is
|
||||
* set by the counterparty, this check is deferred until the order becomes unmatched
|
||||
* (see #555) -- however, detecting this condition is the responsibility of the caller.
|
||||
* There are times when this bet can't be matched (for example, it's now laying a 2:1 bet for
|
||||
* 1 satoshi, so it could only be matched by half a satoshi). Remove these bets from
|
||||
* the books.
|
||||
*/
|
||||
|
||||
if( bet_object_to_cull.get_matching_amount() == 0 )
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ void database::initialize_evaluators()
|
|||
register_evaluator<betting_market_group_create_evaluator>();
|
||||
register_evaluator<betting_market_create_evaluator>();
|
||||
register_evaluator<bet_place_evaluator>();
|
||||
register_evaluator<betting_market_resolve_evaluator>();
|
||||
}
|
||||
|
||||
void database::initialize_indexes()
|
||||
|
|
|
|||
|
|
@ -76,4 +76,15 @@ namespace graphene { namespace chain {
|
|||
const bet_object* _bet_to_cancel;
|
||||
};
|
||||
|
||||
class betting_market_resolve_evaluator : public evaluator<betting_market_resolve_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef betting_market_resolve_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const betting_market_resolve_operation& o );
|
||||
void_result do_apply( const betting_market_resolve_operation& o );
|
||||
private:
|
||||
const betting_market_object* _betting_market;
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ typedef multi_index_container<
|
|||
typedef generic_index<bet_object, bet_object_multi_index_type> bet_object_index;
|
||||
|
||||
struct by_bettor_betting_market{};
|
||||
struct by_betting_market_bettor{};
|
||||
typedef multi_index_container<
|
||||
betting_market_position_object,
|
||||
indexed_by<
|
||||
|
|
@ -243,8 +244,13 @@ typedef multi_index_container<
|
|||
composite_key<
|
||||
betting_market_position_object,
|
||||
member<betting_market_position_object, account_id_type, &betting_market_position_object::bettor_id>,
|
||||
member<betting_market_position_object, betting_market_id_type, &betting_market_position_object::betting_market_id>
|
||||
> > > > betting_market_position_multi_index_type;
|
||||
member<betting_market_position_object, betting_market_id_type, &betting_market_position_object::betting_market_id> > >,
|
||||
ordered_unique< tag<by_betting_market_bettor>,
|
||||
composite_key<
|
||||
betting_market_position_object,
|
||||
member<betting_market_position_object, betting_market_id_type, &betting_market_position_object::betting_market_id>,
|
||||
member<betting_market_position_object, account_id_type, &betting_market_position_object::bettor_id> > >
|
||||
> > betting_market_position_multi_index_type;
|
||||
|
||||
typedef generic_index<betting_market_position_object, betting_market_position_multi_index_type> betting_market_position_index;
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -365,6 +365,8 @@ namespace graphene { namespace chain {
|
|||
|
||||
/// @{ @group Betting Market Helpers
|
||||
void cancel_bet(const bet_object& bet, bool create_virtual_op = true);
|
||||
void resolve_betting_market(const betting_market_object& betting_market,
|
||||
betting_market_resolution_type resolution);
|
||||
/**
|
||||
* @brief Process a new bet
|
||||
* @param new_bet_object The new bet to process
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ namespace graphene { namespace chain {
|
|||
betting_market_group_create_operation,
|
||||
betting_market_create_operation,
|
||||
bet_place_operation,
|
||||
betting_market_resolve_operation,
|
||||
bet_matched_operation, // VIRTUAL
|
||||
bet_cancel_operation,
|
||||
bet_canceled_operation // VIRTUAL
|
||||
|
|
|
|||
|
|
@ -1809,7 +1809,7 @@ BOOST_AUTO_TEST_CASE( peerplays_sport_create_test )
|
|||
const betting_market_object& market = *db.get_index_type<betting_market_object_index>().indices().begin();
|
||||
|
||||
{
|
||||
// have bob lay a bet at 1:1 odds
|
||||
// have bob lay a bet for 1M (+20k fees) at 1:1 odds
|
||||
signed_transaction tx;
|
||||
bet_place_operation bet_op;
|
||||
bet_op.bettor_id = bob_id;
|
||||
|
|
@ -1826,7 +1826,7 @@ BOOST_AUTO_TEST_CASE( peerplays_sport_create_test )
|
|||
}
|
||||
|
||||
{
|
||||
// have alice back a matching bet at 1:1 odds
|
||||
// have alice back a matching bet at 1:1 odds (also costing 1.02M)
|
||||
signed_transaction tx;
|
||||
bet_place_operation bet_op;
|
||||
bet_op.bettor_id = alice_id;
|
||||
|
|
@ -1841,6 +1841,52 @@ BOOST_AUTO_TEST_CASE( peerplays_sport_create_test )
|
|||
sign(tx, alice_private_key);
|
||||
db.push_transaction(tx);
|
||||
}
|
||||
|
||||
// caps win
|
||||
{
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = (*active_witnesses.begin())(db).witness_account;
|
||||
betting_market_resolve_operation betting_market_resolve_op;
|
||||
betting_market_resolve_op.betting_market_id = market.id;
|
||||
betting_market_resolve_op.resolution = betting_market_resolution_type::win;
|
||||
proposal_op.proposed_ops.emplace_back(betting_market_resolve_op);
|
||||
proposal_op.expiration_time = db.head_block_time() + fc::days(1);
|
||||
signed_transaction tx;
|
||||
tx.operations.push_back(proposal_op);
|
||||
set_expiration(db, tx);
|
||||
sign(tx, init_account_priv_key);
|
||||
|
||||
db.push_transaction(tx);
|
||||
}
|
||||
|
||||
BOOST_REQUIRE_EQUAL(db.get_index_type<proposal_index>().indices().size(), 1);
|
||||
{
|
||||
const proposal_object& prop = *db.get_index_type<proposal_index>().indices().begin();
|
||||
|
||||
for (const witness_id_type& witness_id : active_witnesses)
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Approving market resolve witness " << fc::variant(witness_id).as<std::string>());
|
||||
const witness_object& witness = witness_id(db);
|
||||
const account_object& witness_account = witness.witness_account(db);
|
||||
|
||||
proposal_update_operation pup;
|
||||
pup.proposal = prop.id;
|
||||
pup.fee_paying_account = witness_account.id;
|
||||
pup.active_approvals_to_add.insert(witness_account.id);
|
||||
|
||||
signed_transaction tx;
|
||||
tx.operations.push_back( pup );
|
||||
set_expiration( db, tx );
|
||||
sign(tx, init_account_priv_key);
|
||||
|
||||
db.push_transaction(tx, ~0);
|
||||
if (db.get_index_type<proposal_index>().indices().size() == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), 10000000 - 1000000 - 20000 + 2000000);
|
||||
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), 10000000 - 1000000 - 20000);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue