Start of a plugin to track deleted events (and other deleted objects) needed by the
bookie ui
This commit is contained in:
parent
6045b8b096
commit
672fad6d40
10 changed files with 654 additions and 7 deletions
|
|
@ -126,6 +126,18 @@ void_result bet_place_evaluator::do_evaluate(const bet_place_operation& op)
|
|||
FC_ASSERT(bet_object::get_matching_amount(op.amount_to_bet.amount, op.backer_multiplier, op.back_or_lay) != 0,
|
||||
"Bet cannot be matched");
|
||||
|
||||
#if 0
|
||||
bet_object simulated_bet;
|
||||
simulated_bet.bettor_id = op.bettor_id;
|
||||
simulated_bet.betting_market_id = op.betting_market_id;
|
||||
simulated_bet.amount_to_bet = op.amount_to_bet;
|
||||
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;
|
||||
|
||||
share_type required_deposit = get_required_deposit_for_bet(simulated_bet);
|
||||
#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;
|
||||
|
|
|
|||
|
|
@ -104,6 +104,13 @@ void database::resolve_betting_market(const betting_market_object& betting_marke
|
|||
remove(betting_market);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void database::get_required_deposit_for_bet(const betting_market_object& betting_market,
|
||||
betting_market_resolution_type resolution)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
bool maybe_cull_small_bet( database& db, const bet_object& bet_object_to_cull )
|
||||
{
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -225,13 +225,160 @@ struct compare_bet_by_odds {
|
|||
}
|
||||
};
|
||||
|
||||
struct compare_bet_by_bettor_then_odds {
|
||||
bool operator()(const bet_object& lhs, const bet_object& rhs) const
|
||||
{
|
||||
return compare(lhs.betting_market_id, lhs.bettor_id, lhs.back_or_lay, lhs.backer_multiplier, lhs.id,
|
||||
rhs.betting_market_id, rhs.bettor_id, rhs.back_or_lay, rhs.backer_multiplier, rhs.id);
|
||||
}
|
||||
|
||||
template<typename T0>
|
||||
bool operator() (const std::tuple<T0>& lhs, const bet_object& rhs) const
|
||||
{
|
||||
return compare(std::get<0>(lhs), rhs.betting_market_id);
|
||||
}
|
||||
|
||||
template<typename T0>
|
||||
bool operator() (const bet_object& lhs, const std::tuple<T0>& rhs) const
|
||||
{
|
||||
return compare(lhs.betting_market_id, std::get<0>(rhs));
|
||||
}
|
||||
|
||||
template<typename T0, typename T1>
|
||||
bool operator() (const std::tuple<T0, T1>& lhs, const bet_object& rhs) const
|
||||
{
|
||||
return compare(std::get<0>(lhs), std::get<1>(lhs), rhs.betting_market_id, rhs.bettor_id);
|
||||
}
|
||||
|
||||
template<typename T0, typename T1>
|
||||
bool operator() (const bet_object& lhs, const std::tuple<T0, T1>& rhs) const
|
||||
{
|
||||
return compare(lhs.betting_market_id, lhs.bettor_id, std::get<0>(rhs), std::get<1>(rhs));
|
||||
}
|
||||
|
||||
template<typename T0, typename T1, typename T2>
|
||||
bool operator() (const std::tuple<T0, T1, T2>& lhs, const bet_object& rhs) const
|
||||
{
|
||||
return compare(std::get<0>(lhs), std::get<1>(lhs), std::get<2>(lhs),
|
||||
rhs.betting_market_id, rhs.bettor_id, rhs.back_or_lay);
|
||||
}
|
||||
|
||||
template<typename T0, typename T1, typename T2>
|
||||
bool operator() (const bet_object& lhs, const std::tuple<T0, T1, T2>& rhs) const
|
||||
{
|
||||
return compare(lhs.betting_market_id, lhs.bettor_id, lhs.back_or_lay,
|
||||
std::get<0>(rhs), std::get<1>(rhs), std::get<2>(rhs));
|
||||
}
|
||||
template<typename T0, typename T1, typename T2, typename T3>
|
||||
bool operator() (const std::tuple<T0, T1, T2, T3>& lhs, const bet_object& rhs) const
|
||||
{
|
||||
return compare(std::get<0>(lhs), std::get<1>(lhs), std::get<2>(lhs), std::get<3>(lhs),
|
||||
rhs.betting_market_id, rhs.bettor_id, rhs.back_or_lay, rhs.backer_multiplier);
|
||||
}
|
||||
|
||||
template<typename T0, typename T1, typename T2, typename T3>
|
||||
bool operator() (const bet_object& lhs, const std::tuple<T0, T1, T2, T3>& rhs) const
|
||||
{
|
||||
return compare(lhs.betting_market_id, lhs.bettor_id, lhs.back_or_lay, lhs.backer_multiplier, lhs.id,
|
||||
std::get<0>(rhs), std::get<1>(rhs), std::get<2>(rhs), std::get<3>(rhs));
|
||||
}
|
||||
template<typename T0, typename T1, typename T2, typename T3, typename T4>
|
||||
bool operator() (const std::tuple<T0, T1, T2, T3, T4>& lhs, const bet_object& rhs) const
|
||||
{
|
||||
return compare(std::get<0>(lhs), std::get<1>(lhs), std::get<2>(lhs), std::get<3>(lhs), std::get<4>(lhs),
|
||||
rhs.betting_market_id, rhs.bettor_id, rhs.back_or_lay, rhs.backer_multiplier, rhs.id);
|
||||
}
|
||||
template<typename T0, typename T1, typename T2, typename T3, typename T4>
|
||||
bool operator() (const bet_object& lhs, const std::tuple<T0, T1, T2, T3, T4>& rhs) const
|
||||
{
|
||||
return compare(lhs.betting_market_id, lhs.bettor_id, lhs.back_or_lay, lhs.backer_multiplier, lhs.id,
|
||||
std::get<0>(rhs), std::get<1>(rhs), std::get<2>(rhs), std::get<3>(rhs), std::get<4>(rhs));
|
||||
}
|
||||
bool compare(const betting_market_id_type& lhs_betting_market_id, const betting_market_id_type& rhs_betting_market_id) const
|
||||
{
|
||||
return lhs_betting_market_id < rhs_betting_market_id;
|
||||
}
|
||||
bool compare(const betting_market_id_type& lhs_betting_market_id, const account_id_type& lhs_bettor_id,
|
||||
const betting_market_id_type& rhs_betting_market_id, const account_id_type& rhs_bettor_id) const
|
||||
{
|
||||
if (lhs_betting_market_id < rhs_betting_market_id)
|
||||
return true;
|
||||
if (lhs_betting_market_id > rhs_betting_market_id)
|
||||
return false;
|
||||
return lhs_bettor_id < rhs_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,
|
||||
const betting_market_id_type& rhs_betting_market_id, const account_id_type& rhs_bettor_id,
|
||||
bet_type rhs_bet_type) const
|
||||
{
|
||||
if (lhs_betting_market_id < rhs_betting_market_id)
|
||||
return true;
|
||||
if (lhs_betting_market_id > rhs_betting_market_id)
|
||||
return false;
|
||||
if (lhs_bettor_id < rhs_bettor_id)
|
||||
return true;
|
||||
if (lhs_bettor_id > rhs_bettor_id)
|
||||
return false;
|
||||
return lhs_bet_type < rhs_bet_type;
|
||||
}
|
||||
bool compare(const betting_market_id_type& lhs_betting_market_id, const account_id_type& lhs_bettor_id,
|
||||
bet_type lhs_bet_type,
|
||||
bet_multiplier_type lhs_backer_multiplier,
|
||||
const betting_market_id_type& rhs_betting_market_id, const account_id_type& rhs_bettor_id,
|
||||
bet_type rhs_bet_type,
|
||||
bet_multiplier_type rhs_backer_multiplier) const
|
||||
{
|
||||
if (lhs_betting_market_id < rhs_betting_market_id)
|
||||
return true;
|
||||
if (lhs_betting_market_id > rhs_betting_market_id)
|
||||
return false;
|
||||
if (lhs_bettor_id < rhs_bettor_id)
|
||||
return true;
|
||||
if (lhs_bettor_id > rhs_bettor_id)
|
||||
return false;
|
||||
if (lhs_bet_type < rhs_bet_type)
|
||||
return true;
|
||||
if (lhs_bet_type > rhs_bet_type)
|
||||
return false;
|
||||
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,
|
||||
bet_type lhs_bet_type,
|
||||
bet_multiplier_type lhs_backer_multiplier, const bet_id_type& lhs_bet_id,
|
||||
const betting_market_id_type& rhs_betting_market_id, const account_id_type& rhs_bettor_id,
|
||||
bet_type rhs_bet_type,
|
||||
bet_multiplier_type rhs_backer_multiplier, const bet_id_type& rhs_bet_id) const
|
||||
{
|
||||
if (lhs_betting_market_id < rhs_betting_market_id)
|
||||
return true;
|
||||
if (lhs_betting_market_id > rhs_betting_market_id)
|
||||
return false;
|
||||
if (lhs_bettor_id < rhs_bettor_id)
|
||||
return true;
|
||||
if (lhs_bettor_id > rhs_bettor_id)
|
||||
return false;
|
||||
if (lhs_bet_type < rhs_bet_type)
|
||||
return true;
|
||||
if (lhs_bet_type > rhs_bet_type)
|
||||
return false;
|
||||
if (lhs_backer_multiplier < rhs_backer_multiplier)
|
||||
return true;
|
||||
if (lhs_backer_multiplier > rhs_backer_multiplier)
|
||||
return false;
|
||||
return lhs_bet_id < rhs_bet_id;
|
||||
}
|
||||
};
|
||||
|
||||
struct by_odds {};
|
||||
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 > > > bet_object_multi_index_type;
|
||||
|
||||
ordered_unique< tag<by_odds>, identity<bet_object>, compare_bet_by_odds >,
|
||||
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;
|
||||
|
||||
struct by_bettor_betting_market{};
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@ add_subdirectory( witness )
|
|||
add_subdirectory( account_history )
|
||||
add_subdirectory( market_history )
|
||||
add_subdirectory( delayed_node )
|
||||
add_subdirectory( bookie )
|
||||
|
|
|
|||
21
libraries/plugins/bookie/CMakeLists.txt
Normal file
21
libraries/plugins/bookie/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
file(GLOB HEADERS "include/graphene/bookie/*.hpp")
|
||||
|
||||
add_library( graphene_bookie
|
||||
bookie_plugin.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( graphene_bookie graphene_chain graphene_app )
|
||||
target_include_directories( graphene_bookie
|
||||
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
|
||||
|
||||
if(MSVC)
|
||||
set_source_files_properties( bookie_plugin.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||
endif(MSVC)
|
||||
|
||||
install( TARGETS
|
||||
graphene_bookie
|
||||
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
342
libraries/plugins/bookie/bookie_plugin.cpp
Normal file
342
libraries/plugins/bookie/bookie_plugin.cpp
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Cryptonomex, Inc., and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <graphene/bookie/bookie_plugin.hpp>
|
||||
|
||||
#include <graphene/app/impacted.hpp>
|
||||
|
||||
#include <graphene/chain/account_evaluator.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/config.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/event_object.hpp>
|
||||
#include <graphene/chain/operation_history_object.hpp>
|
||||
#include <graphene/chain/transaction_evaluation_state.hpp>
|
||||
|
||||
#include <fc/smart_ref_impl.hpp>
|
||||
#include <fc/thread/thread.hpp>
|
||||
|
||||
#include <boost/polymorphic_cast.hpp>
|
||||
|
||||
#if 0
|
||||
# ifdef DEFAULT_LOGGER
|
||||
# undef DEFAULT_LOGGER
|
||||
# endif
|
||||
# define DEFAULT_LOGGER "bookie_plugin"
|
||||
#endif
|
||||
|
||||
namespace graphene { namespace bookie {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class persistent_event_object : public graphene::db::abstract_object<event_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = bookie_objects;
|
||||
static const uint8_t type_id = persistent_event_object_type;
|
||||
|
||||
event_id_type event_object_id;
|
||||
|
||||
internationalized_string_type name;
|
||||
|
||||
internationalized_string_type season;
|
||||
|
||||
optional<time_point_sec> start_time;
|
||||
|
||||
event_group_id_type event_group_id;
|
||||
|
||||
vector<competitor_id_type> competitors;
|
||||
|
||||
event_status status;
|
||||
vector<string> scores;
|
||||
};
|
||||
typedef object_id<bookie_objects, persistent_event_object_type, persistent_event_object> persistent_event_id_type;
|
||||
|
||||
struct by_event_id;
|
||||
typedef multi_index_container<
|
||||
persistent_event_object,
|
||||
indexed_by<
|
||||
ordered_unique<tag<by_id>, member<object, object_id_type, &object::id> >,
|
||||
ordered_unique<tag<by_event_id>, member<persistent_event_object, event_id_type, &persistent_event_object::event_object_id> > > > persistent_event_object_multi_index_type;
|
||||
|
||||
typedef generic_index<persistent_event_object, persistent_event_object_multi_index_type> persistent_event_object_index;
|
||||
|
||||
|
||||
class events_by_competitor_index : public secondary_index
|
||||
{
|
||||
public:
|
||||
virtual ~events_by_competitor_index() {}
|
||||
|
||||
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;
|
||||
protected:
|
||||
|
||||
map<competitor_id_type, set<persistent_event_id_type> > competitor_to_events;
|
||||
};
|
||||
|
||||
void events_by_competitor_index::object_inserted( const object& obj )
|
||||
{
|
||||
const persistent_event_object& event_obj = *boost::polymorphic_downcast<const persistent_event_object*>(&obj);
|
||||
for (const competitor_id_type& competitor_id : event_obj.competitors)
|
||||
competitor_to_events[competitor_id].insert(event_obj.id);
|
||||
for (const competitor_id_type& competitor_id : event_obj.competitors)
|
||||
competitor_to_events[competitor_id].insert(event_obj.id);
|
||||
}
|
||||
void events_by_competitor_index::object_removed( const object& obj )
|
||||
{
|
||||
const persistent_event_object& event_obj = *boost::polymorphic_downcast<const persistent_event_object*>(&obj);
|
||||
for (const competitor_id_type& competitor_id : event_obj.competitors)
|
||||
competitor_to_events[competitor_id].erase(event_obj.id);
|
||||
}
|
||||
void events_by_competitor_index::about_to_modify( const object& before )
|
||||
{
|
||||
object_removed(before);
|
||||
}
|
||||
void events_by_competitor_index::object_modified( const object& after )
|
||||
{
|
||||
object_inserted(after);
|
||||
}
|
||||
|
||||
|
||||
class bookie_plugin_impl
|
||||
{
|
||||
public:
|
||||
bookie_plugin_impl(bookie_plugin& _plugin)
|
||||
: _self( _plugin )
|
||||
{ }
|
||||
virtual ~bookie_plugin_impl();
|
||||
|
||||
|
||||
/**
|
||||
* Called After a block has been applied and committed. The callback
|
||||
* should not yield and should execute quickly.
|
||||
*/
|
||||
void on_objects_changed(const vector<object_id_type>& changed_object_ids);
|
||||
|
||||
/** this method is called as a callback after a block is applied
|
||||
* and will process/index all operations that were applied in the block.
|
||||
*/
|
||||
void on_block_applied( const signed_block& b );
|
||||
|
||||
graphene::chain::database& database()
|
||||
{
|
||||
return _self.database();
|
||||
}
|
||||
|
||||
bookie_plugin& _self;
|
||||
flat_set<account_id_type> _tracked_accounts;
|
||||
};
|
||||
|
||||
bookie_plugin_impl::~bookie_plugin_impl()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void bookie_plugin_impl::on_objects_changed(const vector<object_id_type>& changed_object_ids)
|
||||
{
|
||||
graphene::chain::database& db = database();
|
||||
auto& event_id_index = db.get_index_type<persistent_event_object_index>().indices().get<by_event_id>();
|
||||
|
||||
for (const object_id_type& changed_object_id : changed_object_ids)
|
||||
{
|
||||
if (changed_object_id.space() == event_id_type::space_id &&
|
||||
changed_object_id.type() == event_id_type::type_id)
|
||||
{
|
||||
event_id_type changed_event_id = changed_object_id;
|
||||
const event_object* new_event_obj = nullptr;
|
||||
try
|
||||
{
|
||||
new_event_obj = &changed_event_id(db);
|
||||
}
|
||||
catch (fc::exception& e)
|
||||
{
|
||||
}
|
||||
// new_event_obj should point to the now-changed event_object, or null if it was removed from the database
|
||||
|
||||
const persistent_event_object* old_event_obj = nullptr;
|
||||
|
||||
auto persistent_event_iter = event_id_index.find(changed_event_id);
|
||||
if (persistent_event_iter != event_id_index.end())
|
||||
old_event_obj = &*persistent_event_iter;
|
||||
|
||||
// and old_event_obj is a pointer to our saved copy, or nullptr if it is a new object
|
||||
if (old_event_obj && new_event_obj)
|
||||
{
|
||||
ilog("Modifying persistent event object ${id}", ("id", changed_event_id));
|
||||
db.modify(*old_event_obj, [&](persistent_event_object& saved_event_obj) {
|
||||
saved_event_obj.name = new_event_obj->name;
|
||||
saved_event_obj.season = new_event_obj->season;
|
||||
saved_event_obj.start_time = new_event_obj->start_time;;
|
||||
saved_event_obj.event_group_id = new_event_obj->event_group_id;
|
||||
saved_event_obj.competitors = new_event_obj->competitors;
|
||||
saved_event_obj.status = new_event_obj->status;
|
||||
saved_event_obj.scores = new_event_obj->scores;
|
||||
});
|
||||
}
|
||||
else if (new_event_obj)
|
||||
{
|
||||
ilog("Creating new persistent event object ${id}", ("id", changed_event_id));
|
||||
db.create<persistent_event_object>([&](persistent_event_object& saved_event_obj) {
|
||||
saved_event_obj.event_object_id = new_event_obj->id;
|
||||
saved_event_obj.name = new_event_obj->name;
|
||||
saved_event_obj.season = new_event_obj->season;
|
||||
saved_event_obj.start_time = new_event_obj->start_time;;
|
||||
saved_event_obj.event_group_id = new_event_obj->event_group_id;
|
||||
saved_event_obj.competitors = new_event_obj->competitors;
|
||||
saved_event_obj.status = new_event_obj->status;
|
||||
saved_event_obj.scores = new_event_obj->scores;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bookie_plugin_impl::on_block_applied( const signed_block& )
|
||||
{
|
||||
graphene::chain::database& db = database();
|
||||
const vector<optional< operation_history_object > >& hist = db.get_applied_operations();
|
||||
for( const optional< operation_history_object >& o_op : hist )
|
||||
{
|
||||
// add to the operation history index
|
||||
const auto& oho = db.create<operation_history_object>( [&]( operation_history_object& h )
|
||||
{
|
||||
if( o_op.valid() )
|
||||
h = *o_op;
|
||||
} );
|
||||
|
||||
if( !o_op.valid() )
|
||||
{
|
||||
ilog( "removing failed operation with ID: ${id}", ("id", oho.id) );
|
||||
db.remove( oho );
|
||||
continue;
|
||||
}
|
||||
|
||||
const operation_history_object& op = *o_op;
|
||||
|
||||
// get the set of accounts this operation applies to
|
||||
flat_set<account_id_type> impacted;
|
||||
vector<authority> other;
|
||||
operation_get_required_authorities( op.op, impacted, impacted, other );
|
||||
|
||||
if( op.op.which() == operation::tag< account_create_operation >::value )
|
||||
impacted.insert( oho.result.get<object_id_type>() );
|
||||
else
|
||||
graphene::app::operation_get_impacted_accounts( op.op, impacted );
|
||||
|
||||
for( auto& a : other )
|
||||
for( auto& item : a.account_auths )
|
||||
impacted.insert( item.first );
|
||||
|
||||
// for each operation this account applies to that is in the config link it into the history
|
||||
if( _tracked_accounts.size() == 0 )
|
||||
{
|
||||
for( auto& account_id : impacted )
|
||||
{
|
||||
// we don't do index_account_keys here anymore, because
|
||||
// that indexing now happens in observers' post_evaluate()
|
||||
|
||||
// add history
|
||||
const auto& stats_obj = account_id(db).statistics(db);
|
||||
const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){
|
||||
obj.operation_id = oho.id;
|
||||
obj.next = stats_obj.most_recent_op;
|
||||
});
|
||||
db.modify( stats_obj, [&]( account_statistics_object& obj ){
|
||||
obj.most_recent_op = ath.id;
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( auto account_id : _tracked_accounts )
|
||||
{
|
||||
if( impacted.find( account_id ) != impacted.end() )
|
||||
{
|
||||
// add history
|
||||
const auto& stats_obj = account_id(db).statistics(db);
|
||||
const auto& ath = db.create<account_transaction_history_object>( [&]( account_transaction_history_object& obj ){
|
||||
obj.operation_id = oho.id;
|
||||
obj.next = stats_obj.most_recent_op;
|
||||
});
|
||||
db.modify( stats_obj, [&]( account_statistics_object& obj ){
|
||||
obj.most_recent_op = ath.id;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end namespace detail
|
||||
|
||||
bookie_plugin::bookie_plugin() :
|
||||
my( new detail::bookie_plugin_impl(*this) )
|
||||
{
|
||||
}
|
||||
|
||||
bookie_plugin::~bookie_plugin()
|
||||
{
|
||||
}
|
||||
|
||||
std::string bookie_plugin::plugin_name()const
|
||||
{
|
||||
return "bookie";
|
||||
}
|
||||
|
||||
void bookie_plugin::plugin_set_program_options(
|
||||
boost::program_options::options_description& cli,
|
||||
boost::program_options::options_description& cfg
|
||||
)
|
||||
{
|
||||
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)")
|
||||
;
|
||||
cfg.add(cli);
|
||||
}
|
||||
|
||||
void bookie_plugin::plugin_initialize(const boost::program_options::variables_map& options)
|
||||
{
|
||||
database().applied_block.connect( [&]( const signed_block& b){ my->on_block_applied(b); } );
|
||||
database().changed_objects.connect([&](const vector<object_id_type>& changed_object_ids){ my->on_objects_changed(changed_object_ids); });
|
||||
auto event_index = database().add_index<primary_index<detail::persistent_event_object_index> >();
|
||||
event_index->add_secondary_index<detail::events_by_competitor_index>();
|
||||
|
||||
LOAD_VALUE_SET(options, "tracked-accounts", my->_tracked_accounts, graphene::chain::account_id_type);
|
||||
}
|
||||
|
||||
void bookie_plugin::plugin_startup()
|
||||
{
|
||||
}
|
||||
|
||||
flat_set<account_id_type> bookie_plugin::tracked_accounts() const
|
||||
{
|
||||
return my->_tracked_accounts;
|
||||
}
|
||||
|
||||
} }
|
||||
FC_REFLECT_DERIVED( graphene::bookie::detail::persistent_event_object, (graphene::db::object), (event_object_id)(name)(season)(start_time)(event_group_id)(status)(competitors)(scores) )
|
||||
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Cryptonomex, Inc., and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <graphene/app/plugin.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
#include <fc/thread/future.hpp>
|
||||
|
||||
namespace graphene { namespace bookie {
|
||||
using namespace chain;
|
||||
|
||||
//
|
||||
// Plugins should #define their SPACE_ID's so plugins with
|
||||
// conflicting SPACE_ID assignments can be compiled into the
|
||||
// same binary (by simply re-assigning some of the conflicting #defined
|
||||
// SPACE_ID's in a build script).
|
||||
//
|
||||
// Assignment of SPACE_ID's cannot be done at run-time because
|
||||
// various template automagic depends on them being known at compile
|
||||
// time.
|
||||
//
|
||||
enum spaces {
|
||||
bookie_objects = 6
|
||||
};
|
||||
enum bookie_object_type
|
||||
{
|
||||
persistent_event_object_type,
|
||||
BOOKIE_OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||
};
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class bookie_plugin_impl;
|
||||
}
|
||||
|
||||
class bookie_plugin : public graphene::app::plugin
|
||||
{
|
||||
public:
|
||||
bookie_plugin();
|
||||
virtual ~bookie_plugin();
|
||||
|
||||
std::string plugin_name()const override;
|
||||
virtual void plugin_set_program_options(
|
||||
boost::program_options::options_description& cli,
|
||||
boost::program_options::options_description& cfg) override;
|
||||
virtual void plugin_initialize(const boost::program_options::variables_map& options) override;
|
||||
virtual void plugin_startup() override;
|
||||
|
||||
flat_set<account_id_type> tracked_accounts()const;
|
||||
|
||||
friend class detail::bookie_plugin_impl;
|
||||
std::unique_ptr<detail::bookie_plugin_impl> my;
|
||||
};
|
||||
|
||||
} } //graphene::bookie
|
||||
|
||||
|
|
@ -8,25 +8,25 @@ endif()
|
|||
|
||||
file(GLOB UNIT_TESTS "tests/*.cpp")
|
||||
add_executable( chain_test ${UNIT_TESTS} ${COMMON_SOURCES} )
|
||||
target_link_libraries( chain_test graphene_chain graphene_app graphene_account_history graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
|
||||
target_link_libraries( chain_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
|
||||
if(MSVC)
|
||||
set_source_files_properties( tests/serialization_tests.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||
endif(MSVC)
|
||||
|
||||
file(GLOB PERFORMANCE_TESTS "performance/*.cpp")
|
||||
add_executable( performance_test ${PERFORMANCE_TESTS} ${COMMON_SOURCES} )
|
||||
target_link_libraries( performance_test graphene_chain graphene_app graphene_account_history graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
|
||||
target_link_libraries( performance_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
|
||||
|
||||
file(GLOB BENCH_MARKS "benchmarks/*.cpp")
|
||||
add_executable( chain_bench ${BENCH_MARKS} ${COMMON_SOURCES} )
|
||||
target_link_libraries( chain_bench graphene_chain graphene_app graphene_account_history graphene_time graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
|
||||
target_link_libraries( chain_bench graphene_chain graphene_app graphene_account_history graphene_bookie graphene_time graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
|
||||
|
||||
file(GLOB APP_SOURCES "app/*.cpp")
|
||||
add_executable( app_test ${APP_SOURCES} )
|
||||
target_link_libraries( app_test graphene_app graphene_account_history graphene_net graphene_chain graphene_time graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
|
||||
target_link_libraries( app_test graphene_app graphene_account_history graphene_bookie graphene_net graphene_chain graphene_time graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
|
||||
|
||||
file(GLOB INTENSE_SOURCES "intense/*.cpp")
|
||||
add_executable( intense_test ${INTENSE_SOURCES} ${COMMON_SOURCES} )
|
||||
target_link_libraries( intense_test graphene_chain graphene_app graphene_account_history graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
|
||||
target_link_libraries( intense_test graphene_chain graphene_app graphene_account_history graphene_bookie graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} )
|
||||
|
||||
add_subdirectory( generate_empty_blocks )
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <graphene/account_history/account_history_plugin.hpp>
|
||||
#include <graphene/market_history/market_history_plugin.hpp>
|
||||
#include <graphene/bookie/bookie_plugin.hpp>
|
||||
|
||||
#include <graphene/db/simple_index.hpp>
|
||||
|
||||
|
|
@ -79,6 +80,7 @@ database_fixture::database_fixture()
|
|||
}
|
||||
auto ahplugin = app.register_plugin<graphene::account_history::account_history_plugin>();
|
||||
auto mhplugin = app.register_plugin<graphene::market_history::market_history_plugin>();
|
||||
auto bookieplugin = app.register_plugin<graphene::bookie::bookie_plugin>();
|
||||
init_account_pub_key = init_account_priv_key.get_public_key();
|
||||
|
||||
boost::program_options::variables_map options;
|
||||
|
|
@ -104,9 +106,12 @@ database_fixture::database_fixture()
|
|||
ahplugin->plugin_initialize(options);
|
||||
mhplugin->plugin_set_app(&app);
|
||||
mhplugin->plugin_initialize(options);
|
||||
bookieplugin->plugin_set_app(&app);
|
||||
bookieplugin->plugin_initialize(options);
|
||||
|
||||
ahplugin->plugin_startup();
|
||||
mhplugin->plugin_startup();
|
||||
bookieplugin->plugin_startup();
|
||||
|
||||
generate_block();
|
||||
|
||||
|
|
|
|||
|
|
@ -1891,3 +1891,36 @@ BOOST_AUTO_TEST_CASE( cancel )
|
|||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
struct simple_bet_test_fixture_2 : database_fixture {
|
||||
betting_market_id_type capitals_win_betting_market_id;
|
||||
simple_bet_test_fixture_2()
|
||||
{
|
||||
ACTORS( (alice)(bob) );
|
||||
CREATE_ICE_HOCKEY_BETTING_MARKET();
|
||||
|
||||
// give alice and bob 10k each
|
||||
transfer(account_id_type(), alice_id, asset(10000));
|
||||
transfer(account_id_type(), bob_id, asset(10000));
|
||||
|
||||
// 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(bob_id, capitals_win_market.id, bet_type::lay, asset(1000, asset_id_type()), 2 * GRAPHENE_BETTING_ODDS_PRECISION, 20);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
// 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);
|
||||
|
||||
capitals_win_betting_market_id = capitals_win_market.id;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue