Merge remote-tracking branch 'origin/sport_n_events_api_extension_release' into beatrice

This commit is contained in:
Fabian Schuh 2018-10-11 14:08:23 +02:00
commit 7d6432e4bf
No known key found for this signature in database
GPG key ID: F2538A4B282D6238
26 changed files with 641 additions and 8 deletions

View file

@ -211,8 +211,10 @@ struct get_impacted_account_visitor
void operator()( const sport_create_operation& op ) {}
void operator()( const sport_update_operation& op ) {}
void operator()( const sport_delete_operation& op ) {}
void operator()( const event_group_create_operation& op ) {}
void operator()( const event_group_update_operation& op ) {}
void operator()( const event_group_delete_operation& op ) {}
void operator()( const event_create_operation& op ) {}
void operator()( const event_update_operation& op ) {}
void operator()( const event_update_status_operation& op ) {}

View file

@ -100,6 +100,7 @@ add_library( graphene_chain
sport_evaluator.cpp
protocol/event_group.cpp
event_group_evaluator.cpp
event_group_object.cpp
protocol/event.cpp
event_evaluator.cpp
event_object.cpp

View file

@ -316,12 +316,19 @@ namespace
// +-------------------+------------------+---------------------+------------------------------+----------------------+
> {};
template <class Fsm,class Event>
void no_transition(Event const& e, Fsm& ,int state)
template <class Fsm, class Event>
void no_transition(Event const& e, Fsm&, int state)
{
FC_THROW_EXCEPTION(graphene::chain::no_transition, "No transition");
}
template <class Fsm>
void no_transition(canceled_event const& e, Fsm&, int state)
{
//ignore transitions from settled to canceled state
//and from canceled to canceled state
}
betting_market_group_object* betting_market_group_obj;
betting_market_group_state_machine_(betting_market_group_object* betting_market_group_obj) : betting_market_group_obj(betting_market_group_obj) {}
};

View file

@ -219,6 +219,7 @@ namespace
void on_entry(const canceled_event& event, betting_market_state_machine_& fsm) {
dlog("betting market ${id} -> canceled", ("id", fsm.betting_market_obj->id));
fsm.betting_market_obj->resolution = betting_market_resolution_type::cancel;
fsm.betting_market_obj->cancel_all_bets(event.db);
}
};
@ -246,11 +247,18 @@ namespace
// +---------------------------+-----------------------------+----------------------------+---------------------+----------------------+
> {};
template <class Fsm,class Event>
template <class Fsm, class Event>
void no_transition(Event const& e, Fsm& ,int state)
{
FC_THROW_EXCEPTION(graphene::chain::no_transition, "No transition");
}
template <class Fsm>
void no_transition(canceled_event const& e, Fsm&, int state)
{
//ignore transitions from settled to canceled state
//and from canceled to canceled state
}
betting_market_object* betting_market_obj;
betting_market_state_machine_(betting_market_object* betting_market_obj) : betting_market_obj(betting_market_obj) {}
@ -399,6 +407,20 @@ void betting_market_object::cancel_all_unmatched_bets(database& db) const
db.cancel_bet(*old_book_itr, true);
}
}
void betting_market_object::cancel_all_bets(database& db) const
{
const auto& bets_by_market_id = db.get_index_type<bet_object_index>().indices().get<by_betting_market_id>();
auto bet_it = bets_by_market_id.lower_bound(id);
auto bet_it_end = bets_by_market_id.upper_bound(id);
while (bet_it != bet_it_end)
{
auto old_bet_it = bet_it;
++bet_it;
db.cancel_bet(*old_bet_it, true);
}
}
void betting_market_object::pack_impl(std::ostream& stream) const
{

View file

@ -216,8 +216,10 @@ void database::initialize_evaluators()
register_evaluator<asset_claim_fees_evaluator>();
register_evaluator<sport_create_evaluator>();
register_evaluator<sport_update_evaluator>();
register_evaluator<sport_delete_evaluator>();
register_evaluator<event_group_create_evaluator>();
register_evaluator<event_group_update_evaluator>();
register_evaluator<event_group_delete_evaluator>();
register_evaluator<event_create_evaluator>();
register_evaluator<event_update_evaluator>();
register_evaluator<event_update_status_evaluator>();

View file

@ -217,8 +217,10 @@ struct get_impacted_account_visitor
}
void operator()(const sport_create_operation&){}
void operator()(const sport_update_operation&){}
void operator()(const sport_delete_operation&){}
void operator()(const event_group_create_operation&){}
void operator()(const event_group_update_operation& op ) {}
void operator()(const event_group_delete_operation& op ) {}
void operator()(const event_create_operation&){}
void operator()(const event_update_operation& op ) {}
void operator()(const event_update_status_operation& op ) {}

View file

@ -23,6 +23,7 @@
*/
#include <graphene/chain/event_group_evaluator.hpp>
#include <graphene/chain/event_group_object.hpp>
#include <graphene/chain/event_object.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/exceptions.hpp>
@ -96,5 +97,25 @@ void_result event_group_update_evaluator::do_apply(const event_group_update_oper
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
void_result event_group_delete_evaluator::do_evaluate(const event_group_delete_operation& op)
{ try {
FC_ASSERT(db().head_block_time() >= HARDFORK_1001_TIME);
FC_ASSERT(trx_state->_is_proposed_trx);
//check for event group existence
_event_group = &op.event_group_id(db());
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
void_result event_group_delete_evaluator::do_apply(const event_group_delete_operation& op)
{ try {
database& _db = db();
_event_group->cancel_events(_db);
_db.remove(*_event_group);
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
} } // graphene::chain

View file

@ -0,0 +1,22 @@
#define DEFAULT_LOGGER "betting"
#include <graphene/chain/event_group_object.hpp>
#include <graphene/chain/event_object.hpp>
#include <graphene/chain/database.hpp>
namespace graphene { namespace chain {
void event_group_object::cancel_events(database& db) const
{
const auto& events_for_group = db.get_index_type<event_object_index>().indices().get<by_event_group_id>();
auto event_it = events_for_group.lower_bound(id);
auto event_end_it = events_for_group.upper_bound(id);
for (; event_it != event_end_it; ++event_it)
{
db.modify( *event_it, [&](event_object& event_obj) {
event_obj.dispatch_new_status(db, event_status::canceled);
});
}
}
}}

View file

@ -340,10 +340,17 @@ namespace graphene { namespace chain {
> {};
template <class Fsm,class Event>
void no_transition(Event const& e, Fsm& ,int state)
void no_transition(Event const& e, Fsm&, int state)
{
FC_THROW_EXCEPTION(graphene::chain::no_transition, "No transition");
}
template <class Fsm>
void no_transition(canceled_event const& e, Fsm&, int state)
{
//ignore transitions from settled to canceled state
//and from canceled to canceled state
}
event_object* event_obj;
event_state_machine_(event_object* event_obj) : event_obj(event_obj) {}

View file

@ -1,4 +1,3 @@
// #615 Fix price feed expiration check, so websocket server will never spam too much data
#ifndef HARDFORK_1000_TIME
#define HARDFORK_1000_TIME (fc::time_point_sec( 1577750400 )) // 2019-12-31
#endif

View file

@ -0,0 +1,4 @@
// added delete sport and delete event group operations
#ifndef HARDFORK_1001_TIME
#define HARDFORK_1001_TIME (fc::time_point_sec( 1458752400 ))
#endif

View file

@ -154,6 +154,7 @@ class betting_market_object : public graphene::db::abstract_object< betting_mark
betting_market_status get_status() const;
void cancel_all_unmatched_bets(database& db) const;
void cancel_all_bets(database& db) const;
// serialization functions:
// for serializing to raw, go through a temporary sstream object to avoid
@ -585,12 +586,14 @@ struct compare_bet_by_bettor_then_odds {
};
struct by_odds {};
struct by_betting_market_id {};
struct by_bettor_and_odds {};
typedef multi_index_container<
bet_object,
indexed_by<
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
ordered_unique< tag<by_odds>, identity<bet_object>, compare_bet_by_odds >,
ordered_non_unique< tag<by_betting_market_id>, member<bet_object, betting_market_id_type, &bet_object::betting_market_id> >,
ordered_unique< tag<by_bettor_and_odds>, identity<bet_object>, compare_bet_by_bettor_then_odds > > > bet_object_multi_index_type;
typedef generic_index<bet_object, bet_object_multi_index_type> bet_object_index;

View file

@ -28,6 +28,8 @@
#include <graphene/chain/database.hpp>
namespace graphene { namespace chain {
class event_group_object;
class event_group_create_evaluator : public evaluator<event_group_create_evaluator>
{
@ -52,4 +54,16 @@ namespace graphene { namespace chain {
private:
sport_id_type sport_id;
};
class event_group_delete_evaluator : public evaluator<event_group_delete_evaluator>
{
public:
typedef event_group_delete_operation operation_type;
void_result do_evaluate( const event_group_delete_operation& o );
void_result do_apply( const event_group_delete_operation& o );
private:
const event_group_object* _event_group = nullptr;
};
} } // graphene::chain

View file

@ -41,6 +41,8 @@ class event_group_object : public graphene::db::abstract_object< event_group_obj
internationalized_string_type name;
sport_id_type sport_id;
void cancel_events(database& db) const;
};
typedef multi_index_container<

View file

@ -71,6 +71,18 @@ struct event_group_update_operation : public base_operation
void validate()const;
};
struct event_group_delete_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
asset fee;
event_group_id_type event_group_id;
extensions_type extensions;
account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; }
void validate()const;
};
} }
@ -81,3 +93,7 @@ FC_REFLECT( graphene::chain::event_group_create_operation,
FC_REFLECT( graphene::chain::event_group_update_operation::fee_parameters_type, (fee) )
FC_REFLECT( graphene::chain::event_group_update_operation,
(fee)(new_sport_id)(new_name)(event_group_id)(extensions) )
FC_REFLECT( graphene::chain::event_group_delete_operation::fee_parameters_type, (fee) )
FC_REFLECT( graphene::chain::event_group_delete_operation,
(fee)(event_group_id)(extensions) )

View file

@ -126,6 +126,8 @@ namespace graphene { namespace chain {
betting_market_group_update_operation,
betting_market_update_operation,
event_update_status_operation,
sport_delete_operation,
event_group_delete_operation,
affiliate_payout_operation, // VIRTUAL
affiliate_referral_payout_operation // VIRTUAL
> operation;

View file

@ -58,6 +58,19 @@ struct sport_update_operation : public base_operation
account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; }
void validate()const;
};
struct sport_delete_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
asset fee;
sport_id_type sport_id;
extensions_type extensions;
account_id_type fee_payer()const { return GRAPHENE_WITNESS_ACCOUNT; }
void validate()const;
};
} }
@ -68,3 +81,7 @@ FC_REFLECT( graphene::chain::sport_create_operation,
FC_REFLECT( graphene::chain::sport_update_operation::fee_parameters_type, (fee) )
FC_REFLECT( graphene::chain::sport_update_operation,
(fee)(sport_id)(new_name)(extensions) )
FC_REFLECT( graphene::chain::sport_delete_operation::fee_parameters_type, (fee) )
FC_REFLECT( graphene::chain::sport_delete_operation,
(fee)(sport_id)(extensions) )

View file

@ -29,6 +29,8 @@
namespace graphene { namespace chain {
class sport_object;
class sport_create_evaluator : public evaluator<sport_create_evaluator>
{
public:
@ -47,4 +49,16 @@ namespace graphene { namespace chain {
void_result do_apply( const sport_update_operation& o );
};
class sport_delete_evaluator : public evaluator<sport_delete_evaluator>
{
public:
typedef sport_delete_operation operation_type;
void_result do_evaluate( const sport_delete_operation& o );
void_result do_apply( const sport_delete_operation& o );
private:
const sport_object* _sport = nullptr;
};
} } // graphene::chain

View file

@ -35,5 +35,10 @@ void event_group_update_operation::validate() const
FC_ASSERT( fee.amount >= 0 );
}
void event_group_delete_operation::validate() const
{
FC_ASSERT( fee.amount >= 0 );
}
} } // graphene::chain

View file

@ -35,6 +35,10 @@ void sport_update_operation::validate() const
FC_ASSERT( fee.amount >= 0 );
}
void sport_delete_operation::validate() const
{
FC_ASSERT( fee.amount >= 0 );
}
} } // graphene::chain

View file

@ -23,6 +23,7 @@
*/
#include <graphene/chain/sport_evaluator.hpp>
#include <graphene/chain/sport_object.hpp>
#include <graphene/chain/event_group_object.hpp>
#include <graphene/chain/account_object.hpp>
#include <graphene/chain/database.hpp>
#include <graphene/chain/exceptions.hpp>
@ -57,7 +58,7 @@ void_result sport_update_evaluator::do_evaluate(const sport_update_operation& op
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
void_result sport_update_evaluator::do_apply(const sport_update_operation& op)
void_result sport_update_evaluator::do_apply(const sport_update_operation& op)
{ try {
database& _db = db();
_db.modify(
@ -70,5 +71,41 @@ void_result sport_update_evaluator::do_evaluate(const sport_update_operation& op
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
void_result sport_delete_evaluator::do_evaluate( const sport_delete_operation& op )
{ try {
FC_ASSERT(db().head_block_time() >= HARDFORK_1001_TIME);
FC_ASSERT(trx_state->_is_proposed_trx);
//check for sport existence
_sport = &op.sport_id(db());
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
void_result sport_delete_evaluator::do_apply( const sport_delete_operation& op )
{ try {
database& _db = db();
std::vector<const event_group_object*> event_groups_to_remove;
const auto& event_group_by_sport_id = _db.get_index_type<event_group_object_index>().indices().get<by_sport_id>();
auto event_group_it = event_group_by_sport_id.lower_bound(op.sport_id);
auto event_group_end_it = event_group_by_sport_id.upper_bound(op.sport_id);
for (; event_group_it != event_group_end_it; ++event_group_it)
{
event_group_it->cancel_events(_db);
event_groups_to_remove.push_back(&*event_group_it);
}
for (auto event_group: event_groups_to_remove)
{
_db.remove(*event_group);
}
_db.remove(*_sport);
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
} } // graphene::chain

View file

@ -1606,6 +1606,12 @@ class wallet_api
sport_id_type sport_id,
fc::optional<internationalized_string_type> name,
bool broadcast = false);
signed_transaction propose_delete_sport(
const string& proposing_account,
fc::time_point_sec expiration_time,
sport_id_type sport_id,
bool broadcast = false);
signed_transaction propose_create_event_group(
const string& proposing_account,
@ -1622,6 +1628,12 @@ class wallet_api
fc::optional<internationalized_string_type> name,
bool broadcast = false);
signed_transaction propose_delete_event_group(
const string& proposing_account,
fc::time_point_sec expiration_time,
event_group_id_type event_group,
bool broadcast = false);
signed_transaction propose_create_event(
const string& proposing_account,
fc::time_point_sec expiration_time,
@ -2010,6 +2022,8 @@ FC_API( graphene::wallet::wallet_api,
(propose_update_event)
(propose_update_betting_market_group)
(propose_update_betting_market)
(propose_delete_sport)
(propose_delete_event_group)
(place_bet)
(cancel_bet)
(propose_resolve_betting_market_group)

View file

@ -5138,6 +5138,33 @@ signed_transaction wallet_api::propose_update_sport(
return my->sign_transaction(tx, broadcast);
}
signed_transaction wallet_api::propose_delete_sport(
const string& proposing_account,
fc::time_point_sec expiration_time,
sport_id_type sport_id,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
const chain_parameters& current_params = get_global_properties().parameters;
sport_delete_operation sport_delete_op;
sport_delete_op.sport_id = sport_id;
proposal_create_operation prop_op;
prop_op.expiration_time = expiration_time;
prop_op.review_period_seconds = current_params.committee_proposal_review_period;
prop_op.fee_paying_account = get_account(proposing_account).id;
prop_op.proposed_ops.emplace_back( sport_delete_op );
current_params.current_fees->set_fee( prop_op.proposed_ops.back().op );
signed_transaction tx;
tx.operations.push_back(prop_op);
my->set_operation_fees(tx, current_params.current_fees);
tx.validate();
return my->sign_transaction(tx, broadcast);
}
signed_transaction wallet_api::propose_create_event_group(
const string& proposing_account,
fc::time_point_sec expiration_time,
@ -5197,6 +5224,33 @@ signed_transaction wallet_api::propose_update_event_group(
return my->sign_transaction(tx, broadcast);
}
signed_transaction wallet_api::propose_delete_event_group(
const string& proposing_account,
fc::time_point_sec expiration_time,
event_group_id_type event_group,
bool broadcast /*= false*/)
{
FC_ASSERT( !is_locked() );
const chain_parameters& current_params = get_global_properties().parameters;
event_group_delete_operation event_group_delete_op;
event_group_delete_op.event_group_id = event_group;
proposal_create_operation prop_op;
prop_op.expiration_time = expiration_time;
prop_op.review_period_seconds = current_params.committee_proposal_review_period;
prop_op.fee_paying_account = get_account(proposing_account).id;
prop_op.proposed_ops.emplace_back( event_group_delete_op );
current_params.current_fees->set_fee( prop_op.proposed_ops.back().op );
signed_transaction tx;
tx.operations.push_back(prop_op);
my->set_operation_fees(tx, current_params.current_fees);
tx.validate();
return my->sign_transaction(tx, broadcast);
}
signed_transaction wallet_api::propose_create_event(
const string& proposing_account,

View file

@ -1149,7 +1149,7 @@ BOOST_AUTO_TEST_CASE(delayed_bets_test) // test live betting
// bob's bet will still be delayed, so the active order book will only contain alice's bet
first_bet_in_market = bet_odds_idx.lower_bound(std::make_tuple(capitals_win_market.id));
last_bet_in_market = bet_odds_idx.upper_bound(std::make_tuple(capitals_win_market.id));
edump((std::distance(first_bet_in_market, last_bet_in_market)));
// edump((std::distance(first_bet_in_market, last_bet_in_market)));
BOOST_CHECK(std::distance(first_bet_in_market, last_bet_in_market) == 1);
for (const auto& bet : boost::make_iterator_range(first_bet_in_market, last_bet_in_market))
edump((bet));
@ -1499,6 +1499,51 @@ BOOST_AUTO_TEST_CASE(sport_update_test)
} FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(sport_delete_test)
{
try
{
CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
const auto& event_group_1 = create_event_group({{"en", "group1"}}, ice_hockey.id);
const auto& event_group_2 = create_event_group({{"en", "group2"}}, ice_hockey.id);
delete_sport(ice_hockey.id);
const auto& sport_by_id = db.get_index_type<sport_object_index>().indices().get<by_id>();
BOOST_CHECK(sport_by_id.end() == sport_by_id.find(ice_hockey.id));
const auto& event_group_by_id = db.get_index_type<event_group_object_index>().indices().get<by_id>();
BOOST_CHECK(event_group_by_id.end() == event_group_by_id.find(event_group_1.id));
BOOST_CHECK(event_group_by_id.end() == event_group_by_id.find(event_group_2.id));
} FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(sport_delete_test_not_proposal)
{
try
{
CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
sport_delete_operation sport_delete_op;
sport_delete_op.sport_id = ice_hockey.id;
BOOST_CHECK_THROW(force_operation_by_witnesses(sport_delete_op), fc::exception);
} FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(sport_delete_test_not_existed_sport)
{
try
{
CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
delete_sport(ice_hockey.id);
BOOST_CHECK_THROW(delete_sport(ice_hockey.id), fc::exception);
} FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(event_group_update_test)
{
try
@ -1543,6 +1588,305 @@ BOOST_AUTO_TEST_CASE(event_group_update_test)
} FC_LOG_AND_RETHROW()
}
struct test_events
{
const event_object* event_upcoming = nullptr;
const event_object* event_in_progress = nullptr;
const event_object* event_frozen_upcoming = nullptr;
const event_object* event_frozen_in_progress = nullptr;
const event_object* event_finished = nullptr;
const event_object* event_canceled = nullptr;
const event_object* event_settled = nullptr;
test_events(database_fixture& db_fixture, event_group_id_type event_group_id)
{
event_upcoming = &db_fixture.create_event({{"en", "event upcoming"}}, {{"en", "2016-17"}}, event_group_id);
event_in_progress = &db_fixture.create_event({{"en", "event in_progress"}}, {{"en", "2016-17"}}, event_group_id);
db_fixture.db.modify(*event_in_progress, [&](event_object& event)
{
event.on_in_progress_event(db_fixture.db);
});
event_frozen_upcoming = &db_fixture.create_event({{"en", "event frozen_upcoming"}}, {{"en", "2016-17"}}, event_group_id);
db_fixture.db.modify(*event_frozen_upcoming, [&](event_object& event)
{
event.on_frozen_event(db_fixture.db);
});
event_frozen_in_progress = &db_fixture.create_event({{"en", "event frozen_in_progress"}}, {{"en", "2016-17"}}, event_group_id);
db_fixture.db.modify(*event_frozen_in_progress, [&](event_object& event)
{
event.on_in_progress_event(db_fixture.db);
event.on_frozen_event(db_fixture.db);
});
event_finished = &db_fixture.create_event({{"en", "event finished"}}, {{"en", "2016-17"}}, event_group_id);
db_fixture.db.modify(*event_finished, [&](event_object& event)
{
event.on_frozen_event(db_fixture.db);
event.on_finished_event(db_fixture.db);
});
event_canceled = &db_fixture.create_event({{"en", "event canceled"}}, {{"en", "2016-17"}}, event_group_id);
db_fixture.db.modify(*event_canceled, [&](event_object& event)
{
event.on_canceled_event(db_fixture.db);
});
event_settled = &db_fixture.create_event({{"en", "event settled"}}, {{"en", "2016-17"}}, event_group_id);
db_fixture.db.modify(*event_settled, [&](event_object& event)
{
event.on_finished_event(db_fixture.db);
event.on_betting_market_group_resolved(db_fixture.db, betting_market_group_id_type(), false);
});
}
};
struct test_markets_groups
{
const betting_market_group_object* market_group_upcoming = nullptr;
const betting_market_group_object* market_group_frozen_upcoming = nullptr;
const betting_market_group_object* market_group_in_play = nullptr;
const betting_market_group_object* market_group_frozen_in_play = nullptr;
const betting_market_group_object* market_group_closed = nullptr;
const betting_market_group_object* market_group_graded = nullptr;
const betting_market_group_object* market_group_canceled = nullptr;
const betting_market_group_object* market_group_settled = nullptr;
test_markets_groups(database_fixture& db_fixture, event_id_type event_id, betting_market_rules_id_type betting_market_rules_id)
{
market_group_upcoming = &db_fixture.create_betting_market_group({{"en", "market group upcoming"}}, event_id, betting_market_rules_id, asset_id_type(), false, 0);
market_group_frozen_upcoming = &db_fixture.create_betting_market_group({{"en", "market group frozen_upcoming"}}, event_id, betting_market_rules_id, asset_id_type(), false, 0);
db_fixture.db.modify(*market_group_frozen_upcoming, [&](betting_market_group_object& market_group)
{
market_group.on_frozen_event(db_fixture.db);
});
market_group_in_play = &db_fixture.create_betting_market_group({{"en", "market group in_play"}}, event_id, betting_market_rules_id, asset_id_type(), false, 0);
db_fixture.db.modify(*market_group_in_play, [&](betting_market_group_object& market_group)
{
market_group.on_in_play_event(db_fixture.db);
});
market_group_frozen_in_play = &db_fixture.create_betting_market_group({{"en", "market group frozen_in_play"}}, event_id, betting_market_rules_id, asset_id_type(), false, 0);
db_fixture.db.modify(*market_group_frozen_in_play, [&](betting_market_group_object& market_group)
{
market_group.on_in_play_event(db_fixture.db);
market_group.on_frozen_event(db_fixture.db);
});
market_group_closed = &db_fixture.create_betting_market_group({{"en", "market group closed"}}, event_id, betting_market_rules_id, asset_id_type(), false, 0);
db_fixture.db.modify(*market_group_closed, [&](betting_market_group_object& market_group)
{
market_group.on_closed_event(db_fixture.db, true);
});
market_group_graded = &db_fixture.create_betting_market_group({{"en", "market group graded"}}, event_id, betting_market_rules_id, asset_id_type(), false, 0);
db_fixture.db.modify(*market_group_graded, [&](betting_market_group_object& market_group)
{
market_group.on_closed_event(db_fixture.db, true);
market_group.on_graded_event(db_fixture.db);
});
market_group_canceled = &db_fixture.create_betting_market_group({{"en", "market group canceled"}}, event_id, betting_market_rules_id, asset_id_type(), false, 0);
db_fixture.db.modify(*market_group_canceled, [&](betting_market_group_object& market_group)
{
market_group.on_canceled_event(db_fixture.db, true);
});
market_group_settled = &db_fixture.create_betting_market_group({{"en", "market group settled"}}, event_id, betting_market_rules_id, asset_id_type(), false, 0);
db_fixture.db.modify(*market_group_settled, [&](betting_market_group_object& market_group)
{
market_group.on_closed_event(db_fixture.db, true);
market_group.on_graded_event(db_fixture.db);
market_group.on_settled_event(db_fixture.db);
});
}
};
struct test_markets
{
const betting_market_object* market_unresolved = nullptr;
const betting_market_object* market_frozen = nullptr;
const betting_market_object* market_closed = nullptr;
const betting_market_object* market_graded = nullptr;
const betting_market_object* market_canceled = nullptr;
const betting_market_object* market_settled = nullptr;
test_markets(database_fixture& db_fixture, betting_market_group_id_type market_group_id)
{
market_unresolved = &db_fixture.create_betting_market(market_group_id, {{"en", "market unresolved"}});
market_frozen = &db_fixture.create_betting_market(market_group_id, {{"en", "market frozen"}});
db_fixture.db.modify(*market_frozen, [&](betting_market_object& market)
{
market.on_frozen_event(db_fixture.db);
});
market_closed = &db_fixture.create_betting_market(market_group_id, {{"en", "market closed"}});
db_fixture.db.modify(*market_closed, [&](betting_market_object& market)
{
market.on_closed_event(db_fixture.db);
});
market_graded = &db_fixture.create_betting_market(market_group_id, {{"en", "market graded"}});
db_fixture.db.modify(*market_graded, [&](betting_market_object& market)
{
market.on_closed_event(db_fixture.db);
market.on_graded_event(db_fixture.db, betting_market_resolution_type::win);
});
market_canceled = &db_fixture.create_betting_market(market_group_id, {{"en", "market canceled"}});
db_fixture.db.modify(*market_canceled, [&](betting_market_object& market)
{
market.on_canceled_event(db_fixture.db);
});
market_settled = &db_fixture.create_betting_market(market_group_id, {{"en", "market settled"}});
db_fixture.db.modify(*market_settled, [&](betting_market_object& market)
{
market.on_closed_event(db_fixture.db);
market.on_graded_event(db_fixture.db, betting_market_resolution_type::win);
market.on_settled_event(db_fixture.db);
});
}
};
BOOST_AUTO_TEST_CASE(event_group_delete_test)
{
try
{
ACTORS( (alice)(bob) )
CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
const int initialAccountAsset = 10000000;
const int betAsset = 1000000;
transfer(account_id_type(), alice_id, asset(initialAccountAsset));
transfer(account_id_type(), bob_id, asset(initialAccountAsset));
const auto& event = create_event({{"en", "event"}}, {{"en", "2016-17"}}, nhl.id);
const auto& market_group = create_betting_market_group({{"en", "market group"}}, event.id, betting_market_rules.id, asset_id_type(), false, 0);
//to make bets be not removed immediately
update_betting_market_group_impl(market_group.id,
fc::optional<internationalized_string_type>(),
fc::optional<object_id_type>(),
betting_market_group_status::in_play,
false);
const auto& market = create_betting_market(market_group.id, {{"en", "market"}});
test_events events(*this, nhl.id);
test_markets_groups markets_groups(*this, event.id, betting_market_rules.id);
test_markets markets(*this, market_group.id);
const auto& bet_1_id = place_bet(alice_id, market.id, bet_type::back, asset(betAsset, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
const auto& bet_2_id = place_bet(bob_id, market.id, bet_type::lay, asset(betAsset, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
delete_event_group(nhl.id);
const auto& event_group_by_id = db.get_index_type<event_group_object_index>().indices().get<by_id>();
BOOST_CHECK(event_group_by_id.end() == event_group_by_id.find(nhl.id));
BOOST_CHECK(event_status::canceled == event.get_status());
BOOST_CHECK(event_status::canceled == events.event_upcoming->get_status());
BOOST_CHECK(event_status::canceled == events.event_in_progress->get_status());
BOOST_CHECK(event_status::canceled == events.event_frozen_in_progress->get_status());
BOOST_CHECK(event_status::canceled == events.event_frozen_upcoming->get_status());
BOOST_CHECK(event_status::canceled == events.event_finished->get_status());
BOOST_CHECK(event_status::canceled == events.event_canceled->get_status());
BOOST_CHECK(event_status::settled == events.event_settled->get_status());
BOOST_CHECK(betting_market_group_status::canceled == market_group.get_status());
BOOST_CHECK(betting_market_group_status::canceled == markets_groups.market_group_upcoming->get_status());
BOOST_CHECK(betting_market_group_status::canceled == markets_groups.market_group_frozen_upcoming->get_status());
BOOST_CHECK(betting_market_group_status::canceled == markets_groups.market_group_in_play->get_status());
BOOST_CHECK(betting_market_group_status::canceled == markets_groups.market_group_frozen_in_play->get_status());
BOOST_CHECK(betting_market_group_status::canceled == markets_groups.market_group_closed->get_status());
BOOST_CHECK(betting_market_group_status::canceled == markets_groups.market_group_graded->get_status());
BOOST_CHECK(betting_market_group_status::canceled == markets_groups.market_group_canceled->get_status());
BOOST_CHECK(betting_market_group_status::settled == markets_groups.market_group_settled->get_status());
BOOST_CHECK(betting_market_status::canceled == market.get_status());
BOOST_CHECK(betting_market_status::canceled == markets.market_unresolved->get_status());
BOOST_CHECK(betting_market_status::canceled == markets.market_frozen->get_status());
BOOST_CHECK(betting_market_status::canceled == markets.market_closed->get_status());
BOOST_CHECK(betting_market_status::canceled == markets.market_graded->get_status());
BOOST_CHECK(betting_market_status::canceled == markets.market_canceled->get_status());
BOOST_CHECK(betting_market_status::settled == markets.market_settled->get_status()); //settled market should not be canceled
//check canceled bets and reverted balance changes
const auto& bet_by_id = db.get_index_type<bet_object_index>().indices().get<by_id>();
BOOST_CHECK(bet_by_id.end() == bet_by_id.find(bet_1_id));
BOOST_CHECK(bet_by_id.end() == bet_by_id.find(bet_2_id));
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), initialAccountAsset);
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), initialAccountAsset);
} FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(event_group_delete_test_with_matched_bets)
{
try
{
ACTORS( (alice)(bob) )
CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
const int initialAccountAsset = 10000000;
const int betAsset = 100000;
transfer(account_id_type(), alice_id, asset(initialAccountAsset));
transfer(account_id_type(), bob_id, asset(initialAccountAsset));
generate_blocks(1);
const auto& event = create_event({{"en", "event"}}, {{"en", "2016-17"}}, nhl.id);
generate_blocks(1);
const auto& market_group = create_betting_market_group({{"en", "market group"}}, event.id, betting_market_rules.id, asset_id_type(), false, 0);
generate_blocks(1);
const auto& market = create_betting_market(market_group.id, {{"en", "market"}});
generate_blocks(1);
place_bet(alice_id, market.id, bet_type::back, asset(betAsset, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
place_bet(bob_id, market.id, bet_type::lay, asset(betAsset, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION);
generate_blocks(1);
delete_event_group(nhl.id);
generate_blocks(1);
BOOST_CHECK_EQUAL(get_balance(alice_id, asset_id_type()), initialAccountAsset);
BOOST_CHECK_EQUAL(get_balance(bob_id, asset_id_type()), initialAccountAsset);
} FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(event_group_delete_test_not_proposal)
{
try
{
CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
event_group_delete_operation event_group_delete_op;
event_group_delete_op.event_group_id = nhl.id;
BOOST_CHECK_THROW(force_operation_by_witnesses(event_group_delete_op), fc::exception);
} FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(event_group_delete_test_not_existed_event_group)
{
try
{
CREATE_ICE_HOCKEY_BETTING_MARKET(false, 0);
delete_event_group(nhl.id);
BOOST_CHECK_THROW(delete_event_group(nhl.id), fc::exception);
} FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(event_update_test)
{
@ -1590,6 +1934,8 @@ BOOST_AUTO_TEST_CASE(event_update_test)
} FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(betting_market_rules_update_test)
{
try

View file

@ -1305,6 +1305,13 @@ void database_fixture::update_sport(sport_id_type sport_id, internationalized_st
process_operation_by_witnesses(sport_update_op);
} FC_CAPTURE_AND_RETHROW( (sport_id)(name) ) }
void database_fixture::delete_sport(sport_id_type sport_id)
{ try {
sport_delete_operation sport_delete_op;
sport_delete_op.sport_id = sport_id;
process_operation_by_witnesses(sport_delete_op);
} FC_CAPTURE_AND_RETHROW( (sport_id) ) }
const event_group_object& database_fixture::create_event_group(internationalized_string_type name, sport_id_type sport_id)
{ try {
event_group_create_operation event_group_create_op;
@ -1315,7 +1322,6 @@ const event_group_object& database_fixture::create_event_group(internationalized
return *event_group_index.rbegin();
} FC_CAPTURE_AND_RETHROW( (name) ) }
void database_fixture::update_event_group(event_group_id_type event_group_id,
fc::optional<object_id_type> sport_id,
fc::optional<internationalized_string_type> name)
@ -1328,6 +1334,14 @@ void database_fixture::update_event_group(event_group_id_type event_group_id,
} FC_CAPTURE_AND_RETHROW( (name) )
}
void database_fixture::delete_event_group(event_group_id_type event_group_id)
{ try {
event_group_delete_operation event_group_delete_op;
event_group_delete_op.event_group_id = event_group_id;
process_operation_by_witnesses(event_group_delete_op);
} FC_CAPTURE_AND_RETHROW( (event_group_id) )
}
void database_fixture::try_update_event_group(event_group_id_type event_group_id,
fc::optional<object_id_type> sport_id,
fc::optional<internationalized_string_type> name,

View file

@ -304,10 +304,12 @@ struct database_fixture {
void set_is_proposed_trx(operation op);
const sport_object& create_sport(internationalized_string_type name);
void update_sport(sport_id_type sport_id, internationalized_string_type name);
void delete_sport(sport_id_type sport_id);
const event_group_object& create_event_group(internationalized_string_type name, sport_id_type sport_id);
void update_event_group(event_group_id_type event_group_id,
fc::optional<object_id_type> sport_id,
fc::optional<internationalized_string_type> name);
void delete_event_group(event_group_id_type event_group_id);
void try_update_event_group(event_group_id_type event_group_id,
fc::optional<object_id_type> sport_id,
fc::optional<internationalized_string_type> name,