implement payment splitter proposal
This commit is contained in:
parent
e4c29cbe78
commit
c6b848ef18
6 changed files with 399 additions and 2 deletions
|
|
@ -44,6 +44,7 @@
|
||||||
#include <graphene/chain/witness_evaluator.hpp>
|
#include <graphene/chain/witness_evaluator.hpp>
|
||||||
#include <graphene/chain/worker_evaluator.hpp>
|
#include <graphene/chain/worker_evaluator.hpp>
|
||||||
#include <graphene/chain/balance_evaluator.hpp>
|
#include <graphene/chain/balance_evaluator.hpp>
|
||||||
|
#include <graphene/chain/splitter_evaluator.hpp>
|
||||||
|
|
||||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||||
|
|
||||||
|
|
@ -150,6 +151,11 @@ void database::initialize_evaluators()
|
||||||
register_evaluator<withdraw_permission_delete_evaluator>();
|
register_evaluator<withdraw_permission_delete_evaluator>();
|
||||||
register_evaluator<worker_create_evaluator>();
|
register_evaluator<worker_create_evaluator>();
|
||||||
register_evaluator<balance_claim_evaluator>();
|
register_evaluator<balance_claim_evaluator>();
|
||||||
|
register_evaluator<splitter_create_evaluator>();
|
||||||
|
register_evaluator<splitter_update_evaluator>();
|
||||||
|
register_evaluator<splitter_pay_evaluator>();
|
||||||
|
register_evaluator<splitter_payout_evaluator>();
|
||||||
|
register_evaluator<splitter_delete_evaluator>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void database::initialize_indexes()
|
void database::initialize_indexes()
|
||||||
|
|
@ -177,6 +183,7 @@ void database::initialize_indexes()
|
||||||
add_index< primary_index<vesting_balance_index> >();
|
add_index< primary_index<vesting_balance_index> >();
|
||||||
add_index< primary_index<worker_index> >();
|
add_index< primary_index<worker_index> >();
|
||||||
add_index< primary_index<balance_index> >();
|
add_index< primary_index<balance_index> >();
|
||||||
|
add_index< primary_index<splitter_index> >();
|
||||||
|
|
||||||
//Implementation object indexes
|
//Implementation object indexes
|
||||||
add_index< primary_index<transaction_index > >();
|
add_index< primary_index<transaction_index > >();
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include <graphene/chain/protocol/withdraw_permission.hpp>
|
#include <graphene/chain/protocol/withdraw_permission.hpp>
|
||||||
#include <graphene/chain/protocol/witness.hpp>
|
#include <graphene/chain/protocol/witness.hpp>
|
||||||
#include <graphene/chain/protocol/worker.hpp>
|
#include <graphene/chain/protocol/worker.hpp>
|
||||||
|
#include <graphene/chain/protocol/splitter.hpp>
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
|
@ -59,7 +60,12 @@ namespace graphene { namespace chain {
|
||||||
custom_operation,
|
custom_operation,
|
||||||
assert_operation,
|
assert_operation,
|
||||||
balance_claim_operation,
|
balance_claim_operation,
|
||||||
override_transfer_operation
|
override_transfer_operation,
|
||||||
|
splitter_create_operation,
|
||||||
|
splitter_update_operation,
|
||||||
|
splitter_pay_operation,
|
||||||
|
splitter_payout_operation,
|
||||||
|
splitter_delete_operation
|
||||||
> operation;
|
> operation;
|
||||||
|
|
||||||
/// @} // operations group
|
/// @} // operations group
|
||||||
|
|
|
||||||
147
libraries/chain/include/graphene/chain/protocol/splitter.hpp
Normal file
147
libraries/chain/include/graphene/chain/protocol/splitter.hpp
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
/* Copyright (c) 2015, Cryptonomex, Inc. */
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/protocol/base.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
struct market_buyback
|
||||||
|
{
|
||||||
|
asset_id_type asset_to_buy;
|
||||||
|
price limit_price;
|
||||||
|
void validate()const {
|
||||||
|
limit_price.validate();
|
||||||
|
FC_ASSERT( limit_price.quote.asset_id == asset_to_buy );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef static_variant<account_id_type,market_buyback> payment_target_type;
|
||||||
|
|
||||||
|
struct payment_target
|
||||||
|
{
|
||||||
|
uint16_t weight = 0;
|
||||||
|
payment_target_type target;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct payment_target_validate
|
||||||
|
{
|
||||||
|
typedef void result_type;
|
||||||
|
void operator()( const account_id_type& id )const { }
|
||||||
|
void operator()( const market_buyback& t )const
|
||||||
|
{
|
||||||
|
FC_ASSERT( t.asset_to_buy == t.limit_price.quote.asset_id );
|
||||||
|
t.limit_price.validate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct splitter_create_operation : public base_operation
|
||||||
|
{
|
||||||
|
/// TODO: charge fee based upon size
|
||||||
|
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
account_id_type payer;
|
||||||
|
account_id_type owner;
|
||||||
|
vector<payment_target> targets;
|
||||||
|
asset min_payment;
|
||||||
|
share_type max_payment; ///< same asset_id as min_payment
|
||||||
|
share_type payout_threshold; ///< same asset_id as min_payment
|
||||||
|
|
||||||
|
void validate()const
|
||||||
|
{
|
||||||
|
FC_ASSERT( fee.amount >= 0 );
|
||||||
|
FC_ASSERT( min_payment.amount > 0 );
|
||||||
|
FC_ASSERT( min_payment.amount <= max_payment );
|
||||||
|
FC_ASSERT( payout_threshold >= 0 );
|
||||||
|
for( const auto& t : targets )
|
||||||
|
{
|
||||||
|
FC_ASSERT( t.weight > 0 );
|
||||||
|
t.target.visit( payment_target_validate() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
account_id_type fee_payer()const { return payer; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct splitter_update_operation : public base_operation
|
||||||
|
{
|
||||||
|
/// TODO: charge fee based upon size
|
||||||
|
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
splitter_id_type splitter_id;
|
||||||
|
account_id_type owner; ///< must match splitter_id->owner
|
||||||
|
account_id_type new_owner;
|
||||||
|
vector<payment_target> targets;
|
||||||
|
asset min_payment;
|
||||||
|
share_type max_payment; ///< same asset_id as min_payment
|
||||||
|
share_type payout_threshold; ///< same asset_id as min_payment
|
||||||
|
|
||||||
|
void validate()const
|
||||||
|
{
|
||||||
|
FC_ASSERT( fee.amount >= 0 );
|
||||||
|
FC_ASSERT( min_payment.amount > 0 );
|
||||||
|
FC_ASSERT( min_payment.amount <= max_payment );
|
||||||
|
FC_ASSERT( payout_threshold >= 0 );
|
||||||
|
for( const auto& t : targets ) FC_ASSERT( t.weight > 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
account_id_type fee_payer()const { return owner; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct splitter_pay_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
splitter_id_type splitter_id;
|
||||||
|
account_id_type paying_account; ///< also fee payer
|
||||||
|
asset payment;
|
||||||
|
|
||||||
|
void validate()const
|
||||||
|
{
|
||||||
|
FC_ASSERT( payment.amount > 0 );
|
||||||
|
FC_ASSERT( fee.amount >= 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
account_id_type fee_payer()const { return paying_account; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct splitter_payout_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
splitter_id_type splitter_id;
|
||||||
|
account_id_type owner; ///< must match splitter_id->owner
|
||||||
|
|
||||||
|
void validate()const { FC_ASSERT( fee.amount >= 0 ); }
|
||||||
|
account_id_type fee_payer()const { return owner; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct splitter_delete_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
splitter_id_type splitter_id;
|
||||||
|
account_id_type owner; ///< must match splitter_id->owner
|
||||||
|
|
||||||
|
void validate()const { FC_ASSERT( fee.amount >= 0 ); }
|
||||||
|
account_id_type fee_payer()const { return owner; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
FC_REFLECT( graphene::chain::market_buyback, (asset_to_buy)(limit_price) )
|
||||||
|
FC_REFLECT( graphene::chain::payment_target, (weight)(target) )
|
||||||
|
FC_REFLECT( graphene::chain::splitter_create_operation, (fee)(payer)(owner)(targets)(min_payment)(max_payment)(payout_threshold) )
|
||||||
|
FC_REFLECT( graphene::chain::splitter_update_operation, (fee)(owner)(new_owner)(targets)(min_payment)(max_payment)(payout_threshold) )
|
||||||
|
FC_REFLECT( graphene::chain::splitter_pay_operation, (fee)(splitter_id)(paying_account)(payment) )
|
||||||
|
FC_REFLECT( graphene::chain::splitter_payout_operation, (fee)(splitter_id)(owner) )
|
||||||
|
FC_REFLECT( graphene::chain::splitter_delete_operation, (fee)(splitter_id)(owner) )
|
||||||
|
FC_REFLECT( graphene::chain::splitter_create_operation::fee_parameters_type, (fee) );
|
||||||
|
FC_REFLECT( graphene::chain::splitter_update_operation::fee_parameters_type, (fee) );
|
||||||
|
FC_REFLECT( graphene::chain::splitter_pay_operation::fee_parameters_type, (fee) );
|
||||||
|
FC_REFLECT( graphene::chain::splitter_payout_operation::fee_parameters_type, (fee) );
|
||||||
|
FC_REFLECT( graphene::chain::splitter_delete_operation::fee_parameters_type, (fee) );
|
||||||
|
|
||||||
|
|
@ -123,6 +123,7 @@ namespace graphene { namespace chain {
|
||||||
vesting_balance_object_type,
|
vesting_balance_object_type,
|
||||||
worker_object_type,
|
worker_object_type,
|
||||||
balance_object_type,
|
balance_object_type,
|
||||||
|
splitter_object_type,
|
||||||
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -169,11 +170,12 @@ namespace graphene { namespace chain {
|
||||||
class witness_schedule_object;
|
class witness_schedule_object;
|
||||||
class worker_object;
|
class worker_object;
|
||||||
class balance_object;
|
class balance_object;
|
||||||
|
class splitter_object;
|
||||||
|
|
||||||
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
||||||
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
|
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
|
||||||
typedef object_id< protocol_ids, force_settlement_object_type, force_settlement_object> force_settlement_id_type;
|
typedef object_id< protocol_ids, force_settlement_object_type, force_settlement_object> force_settlement_id_type;
|
||||||
typedef object_id< protocol_ids, committee_member_object_type, committee_member_object> committee_member_id_type;
|
typedef object_id< protocol_ids, committee_member_object_type, committee_member_object> committee_member_id_type;
|
||||||
typedef object_id< protocol_ids, witness_object_type, witness_object> witness_id_type;
|
typedef object_id< protocol_ids, witness_object_type, witness_object> witness_id_type;
|
||||||
typedef object_id< protocol_ids, limit_order_object_type, limit_order_object> limit_order_id_type;
|
typedef object_id< protocol_ids, limit_order_object_type, limit_order_object> limit_order_id_type;
|
||||||
typedef object_id< protocol_ids, call_order_object_type, call_order_object> call_order_id_type;
|
typedef object_id< protocol_ids, call_order_object_type, call_order_object> call_order_id_type;
|
||||||
|
|
@ -184,6 +186,7 @@ namespace graphene { namespace chain {
|
||||||
typedef object_id< protocol_ids, vesting_balance_object_type, vesting_balance_object> vesting_balance_id_type;
|
typedef object_id< protocol_ids, vesting_balance_object_type, vesting_balance_object> vesting_balance_id_type;
|
||||||
typedef object_id< protocol_ids, worker_object_type, worker_object> worker_id_type;
|
typedef object_id< protocol_ids, worker_object_type, worker_object> worker_id_type;
|
||||||
typedef object_id< protocol_ids, balance_object_type, balance_object> balance_id_type;
|
typedef object_id< protocol_ids, balance_object_type, balance_object> balance_id_type;
|
||||||
|
typedef object_id< protocol_ids, splitter_object_type, splitter_object> splitter_id_type;
|
||||||
|
|
||||||
// implementation types
|
// implementation types
|
||||||
class global_property_object;
|
class global_property_object;
|
||||||
|
|
@ -376,6 +379,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type,
|
||||||
(vesting_balance_object_type)
|
(vesting_balance_object_type)
|
||||||
(worker_object_type)
|
(worker_object_type)
|
||||||
(balance_object_type)
|
(balance_object_type)
|
||||||
|
(splitter_object_type)
|
||||||
(OBJECT_TYPE_COUNT)
|
(OBJECT_TYPE_COUNT)
|
||||||
)
|
)
|
||||||
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
||||||
|
|
|
||||||
232
libraries/chain/include/graphene/chain/splitter_evaluator.hpp
Normal file
232
libraries/chain/include/graphene/chain/splitter_evaluator.hpp
Normal file
|
|
@ -0,0 +1,232 @@
|
||||||
|
/* Copyright (c) 2015, Cryptonomex, Inc. */
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/protocol/operations.hpp>
|
||||||
|
#include <graphene/chain/evaluator.hpp>
|
||||||
|
#include <graphene/chain/database.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
class splitter_object : public abstract_object<splitter_object>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = protocol_ids;
|
||||||
|
static const uint8_t type_id = splitter_object_type;
|
||||||
|
|
||||||
|
account_id_type owner;
|
||||||
|
asset balance;
|
||||||
|
vector<payment_target> targets;
|
||||||
|
asset min_payment;
|
||||||
|
share_type max_payment; ///< same asset_id as min_payment
|
||||||
|
share_type payout_threshold; ///< same asset_id as min_payment
|
||||||
|
|
||||||
|
|
||||||
|
struct payout_visitor
|
||||||
|
{
|
||||||
|
typedef void result_type;
|
||||||
|
database& db;
|
||||||
|
asset amount;
|
||||||
|
|
||||||
|
payout_visitor( database& d, asset a ):db(d),amount(a){}
|
||||||
|
|
||||||
|
void operator()( const account_id_type& id )const
|
||||||
|
{
|
||||||
|
db.adjust_balance( id(db), amount );
|
||||||
|
}
|
||||||
|
void operator()( const market_buyback& t )const
|
||||||
|
{
|
||||||
|
const auto& new_order_object = db.create<limit_order_object>([&](limit_order_object& obj){
|
||||||
|
obj.seller = GRAPHENE_NULL_ACCOUNT;
|
||||||
|
obj.for_sale = amount.amount;
|
||||||
|
obj.sell_price = t.limit_price;
|
||||||
|
assert( amount.asset_id == t.limit_price.base.asset_id );
|
||||||
|
});
|
||||||
|
db.apply_order(new_order_object);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void payout( database& db )const
|
||||||
|
{
|
||||||
|
uint64_t total_weight = 0;
|
||||||
|
for( auto& t : targets ) total_weight += t.weight;
|
||||||
|
|
||||||
|
asset remaining = balance;
|
||||||
|
|
||||||
|
for( uint32_t i = 0 ; i < targets.size(); ++i )
|
||||||
|
{
|
||||||
|
const auto& t = targets[i];
|
||||||
|
|
||||||
|
fc::uint128 tmp( balance.amount.value );
|
||||||
|
tmp *= t.weight;
|
||||||
|
tmp /= total_weight;
|
||||||
|
|
||||||
|
asset payout_amount( tmp.to_uint64(), balance.asset_id );
|
||||||
|
|
||||||
|
if( payout_amount > remaining || (i == (targets.size() - 1)) )
|
||||||
|
payout_amount = remaining;
|
||||||
|
|
||||||
|
if( payout_amount.amount > 0 )
|
||||||
|
{
|
||||||
|
t.target.visit( payout_visitor( db, payout_amount ) );
|
||||||
|
}
|
||||||
|
remaining -= payout_amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct by_account;
|
||||||
|
|
||||||
|
typedef multi_index_container<
|
||||||
|
splitter_object,
|
||||||
|
indexed_by<
|
||||||
|
hashed_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||||
|
ordered_non_unique< tag<by_account>, member< splitter_object, account_id_type, &splitter_object::owner > >
|
||||||
|
>
|
||||||
|
> splitter_multi_index_type;
|
||||||
|
typedef generic_index<splitter_object, splitter_multi_index_type> splitter_index;
|
||||||
|
|
||||||
|
|
||||||
|
struct target_evalautor
|
||||||
|
{
|
||||||
|
typedef void result_type;
|
||||||
|
const database& db;
|
||||||
|
|
||||||
|
target_evalautor( database& d ):db(d){}
|
||||||
|
|
||||||
|
void operator()( const account_id_type& id )const { id(db); }
|
||||||
|
void operator()( const market_buyback& t )const
|
||||||
|
{
|
||||||
|
/// dereference these objects to verify they exist
|
||||||
|
t.asset_to_buy(db);
|
||||||
|
t.limit_price.base.asset_id(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class splitter_create_evaluator : public evaluator<splitter_create_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef splitter_create_operation operation_type;
|
||||||
|
|
||||||
|
void_result do_evaluate( const splitter_create_operation& o )
|
||||||
|
{
|
||||||
|
o.owner(db()); // dereference to prove it exists
|
||||||
|
for( auto& t : o.targets )
|
||||||
|
t.target.visit( target_evalautor(db()) );
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
|
||||||
|
object_id_type do_apply( const splitter_create_operation& o )
|
||||||
|
{
|
||||||
|
const auto& new_splitter_object = db().create<splitter_object>( [&]( splitter_object& obj ){
|
||||||
|
obj.owner = o.owner;
|
||||||
|
obj.targets = o.targets;
|
||||||
|
obj.min_payment = o.min_payment;
|
||||||
|
obj.max_payment = o.max_payment;
|
||||||
|
obj.payout_threshold = o.payout_threshold;
|
||||||
|
obj.balance.asset_id = o.min_payment.asset_id;
|
||||||
|
});
|
||||||
|
return new_splitter_object.id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class splitter_update_evaluator : public evaluator<splitter_update_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef splitter_update_operation operation_type;
|
||||||
|
|
||||||
|
void_result do_evaluate( const splitter_update_operation& o )
|
||||||
|
{
|
||||||
|
const auto& sp = o.splitter_id(db()); // dereference to prove it exists
|
||||||
|
FC_ASSERT( sp.balance.amount == 0 );
|
||||||
|
FC_ASSERT( sp.owner == o.owner );
|
||||||
|
|
||||||
|
for( auto& t : o.targets )
|
||||||
|
t.target.visit( target_evalautor(db()) );
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
void_result do_apply( const splitter_update_operation& o )
|
||||||
|
{
|
||||||
|
const auto& sp = o.splitter_id(db()); // dereference to prove it exists
|
||||||
|
db().modify( sp, [&]( splitter_object& obj ){
|
||||||
|
obj.targets = o.targets;
|
||||||
|
obj.owner = o.new_owner;
|
||||||
|
obj.min_payment = o.min_payment;
|
||||||
|
obj.max_payment = o.max_payment;
|
||||||
|
obj.payout_threshold = o.payout_threshold;
|
||||||
|
obj.balance.asset_id = o.min_payment.asset_id;
|
||||||
|
});
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class splitter_pay_evaluator : public evaluator<splitter_pay_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef splitter_pay_operation operation_type;
|
||||||
|
|
||||||
|
void_result do_evaluate( const splitter_pay_operation& o )
|
||||||
|
{
|
||||||
|
const auto& sp = o.splitter_id(db()); // dereference to prove it exists
|
||||||
|
FC_ASSERT( o.payment.asset_id == sp.min_payment.asset_id );
|
||||||
|
FC_ASSERT( o.payment >= sp.min_payment );
|
||||||
|
FC_ASSERT( o.payment.amount <= sp.max_payment );
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
void_result do_apply( const splitter_pay_operation& o )
|
||||||
|
{
|
||||||
|
db().adjust_balance( o.paying_account, -o.payment );
|
||||||
|
const auto& sp = o.splitter_id(db()); // dereference to prove it exists
|
||||||
|
db().modify( sp, [&]( splitter_object& obj ){
|
||||||
|
obj.balance += o.payment;
|
||||||
|
});
|
||||||
|
|
||||||
|
if( sp.balance.amount > sp.payout_threshold )
|
||||||
|
sp.payout(db());
|
||||||
|
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class splitter_payout_evaluator : public evaluator<splitter_payout_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef splitter_payout_operation operation_type;
|
||||||
|
|
||||||
|
void_result do_evaluate( const splitter_payout_operation& o )
|
||||||
|
{
|
||||||
|
const auto& sp = o.splitter_id(db()); // dereference to prove it exists
|
||||||
|
FC_ASSERT( sp.owner == o.owner );
|
||||||
|
FC_ASSERT( sp.balance.amount > 0 );
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
|
||||||
|
void_result do_apply( const splitter_payout_operation& o )
|
||||||
|
{
|
||||||
|
const auto& sp = o.splitter_id(db()); // dereference to prove it exists
|
||||||
|
sp.payout(db());
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class splitter_delete_evaluator : public evaluator<splitter_delete_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef splitter_delete_operation operation_type;
|
||||||
|
|
||||||
|
void_result do_evaluate( const splitter_delete_operation& o )
|
||||||
|
{
|
||||||
|
const auto& sp = o.splitter_id(db()); // dereference to prove it exists
|
||||||
|
FC_ASSERT( sp.owner == o.owner );
|
||||||
|
FC_ASSERT( sp.balance.amount == 0 );
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
void_result do_apply( const splitter_delete_operation& o )
|
||||||
|
{
|
||||||
|
db().remove( o.splitter_id(db()) );
|
||||||
|
return void_result();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} } // graphene::chain
|
||||||
|
|
||||||
|
FC_REFLECT_DERIVED( graphene::chain::splitter_object,
|
||||||
|
(graphene::db::object),
|
||||||
|
(owner)(balance)(targets)(min_payment)(max_payment)(payout_threshold)
|
||||||
|
)
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include <graphene/chain/market_evaluator.hpp>
|
#include <graphene/chain/market_evaluator.hpp>
|
||||||
#include <graphene/chain/account_object.hpp>
|
#include <graphene/chain/account_object.hpp>
|
||||||
#include <graphene/chain/balance_object.hpp>
|
#include <graphene/chain/balance_object.hpp>
|
||||||
|
#include <graphene/chain/splitter_evaluator.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace graphene::chain;
|
using namespace graphene::chain;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue