Correctly generating virtual transactions for payouts
This commit is contained in:
parent
abc7853c99
commit
7857ac48a4
8 changed files with 141 additions and 21 deletions
|
|
@ -91,6 +91,11 @@ struct get_impacted_account_visitor
|
||||||
|
|
||||||
void operator()( const asset_update_bitasset_operation& op ) {}
|
void operator()( const asset_update_bitasset_operation& op ) {}
|
||||||
void operator()( const asset_update_dividend_operation& op ) {}
|
void operator()( const asset_update_dividend_operation& op ) {}
|
||||||
|
void operator()( const asset_dividend_distribution_operation& op )
|
||||||
|
{
|
||||||
|
_impacted.insert( op.account_id );
|
||||||
|
}
|
||||||
|
|
||||||
void operator()( const asset_update_feed_producers_operation& op ) {}
|
void operator()( const asset_update_feed_producers_operation& op ) {}
|
||||||
|
|
||||||
void operator()( const asset_issue_operation& op )
|
void operator()( const asset_issue_operation& op )
|
||||||
|
|
|
||||||
|
|
@ -799,8 +799,8 @@ void schedule_pending_dividend_balances(database& db,
|
||||||
|
|
||||||
dlog("Crediting account ${account} with ${amount}", ("account", holder_balance_object.owner(db).name)("amount", amount_to_credit));
|
dlog("Crediting account ${account} with ${amount}", ("account", holder_balance_object.owner(db).name)("amount", amount_to_credit));
|
||||||
auto pending_payout_iter =
|
auto pending_payout_iter =
|
||||||
pending_payout_balance_index.indices().get<by_dividend_asset_account_asset>().find(boost::make_tuple(dividend_holder_asset_obj.id, payout_asset_type, holder_balance_object.owner));
|
pending_payout_balance_index.indices().get<by_dividend_payout_account>().find(boost::make_tuple(dividend_holder_asset_obj.id, payout_asset_type, holder_balance_object.owner));
|
||||||
if (pending_payout_iter == pending_payout_balance_index.indices().get<by_dividend_asset_account_asset>().end())
|
if (pending_payout_iter == pending_payout_balance_index.indices().get<by_dividend_payout_account>().end())
|
||||||
db.create<pending_dividend_payout_balance_object>( [&]( pending_dividend_payout_balance_object& obj ){
|
db.create<pending_dividend_payout_balance_object>( [&]( pending_dividend_payout_balance_object& obj ){
|
||||||
obj.owner = holder_balance_object.owner;
|
obj.owner = holder_balance_object.owner;
|
||||||
obj.dividend_holder_asset_type = dividend_holder_asset_obj.id;
|
obj.dividend_holder_asset_type = dividend_holder_asset_obj.id;
|
||||||
|
|
@ -839,7 +839,7 @@ void schedule_pending_dividend_balances(database& db,
|
||||||
// Reduce all pending payouts proportionally
|
// Reduce all pending payouts proportionally
|
||||||
share_type total_pending_balances;
|
share_type total_pending_balances;
|
||||||
auto pending_payouts_range =
|
auto pending_payouts_range =
|
||||||
pending_payout_balance_index.indices().get<by_dividend_asset_account_asset>().equal_range(boost::make_tuple(dividend_holder_asset_obj.id, payout_asset_type));
|
pending_payout_balance_index.indices().get<by_dividend_payout_account>().equal_range(boost::make_tuple(dividend_holder_asset_obj.id, payout_asset_type));
|
||||||
|
|
||||||
for (const pending_dividend_payout_balance_object& pending_balance_object : boost::make_iterator_range(pending_payouts_range.first, pending_payouts_range.second))
|
for (const pending_dividend_payout_balance_object& pending_balance_object : boost::make_iterator_range(pending_payouts_range.first, pending_payouts_range.second))
|
||||||
total_pending_balances += pending_balance_object.pending_balance;
|
total_pending_balances += pending_balance_object.pending_balance;
|
||||||
|
|
@ -927,11 +927,28 @@ void process_dividend_assets(database& db)
|
||||||
// for debugging, sum up our payouts here
|
// for debugging, sum up our payouts here
|
||||||
std::map<asset_id_type, share_type> amounts_paid_out_by_asset;
|
std::map<asset_id_type, share_type> amounts_paid_out_by_asset;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto pending_payouts_range =
|
auto pending_payouts_range =
|
||||||
pending_payout_balance_index.indices().get<by_dividend_asset_account_asset>().equal_range(boost::make_tuple(dividend_holder_asset_obj.id));
|
pending_payout_balance_index.indices().get<by_dividend_account_payout>().equal_range(boost::make_tuple(dividend_holder_asset_obj.id));
|
||||||
|
// the pending_payouts_range is all payouts for this dividend asset, sorted by the holder's account
|
||||||
|
// we iterate in this order so we can build up a list of payouts for each account to put in the
|
||||||
|
// virtual op
|
||||||
|
flat_set<asset> payouts_for_this_holder;
|
||||||
|
fc::optional<account_id_type> last_holder_account_id;
|
||||||
for (auto pending_balance_object_iter = pending_payouts_range.first; pending_balance_object_iter != pending_payouts_range.second; )
|
for (auto pending_balance_object_iter = pending_payouts_range.first; pending_balance_object_iter != pending_payouts_range.second; )
|
||||||
{
|
{
|
||||||
const pending_dividend_payout_balance_object& pending_balance_object = *pending_balance_object_iter;
|
const pending_dividend_payout_balance_object& pending_balance_object = *pending_balance_object_iter;
|
||||||
|
|
||||||
|
if (last_holder_account_id && *last_holder_account_id != pending_balance_object.owner)
|
||||||
|
{
|
||||||
|
// we've moved on to a new account, generate the dividend payment virtual op for the previous one
|
||||||
|
db.push_applied_operation(asset_dividend_distribution_operation(dividend_holder_asset_obj.id,
|
||||||
|
*last_holder_account_id,
|
||||||
|
payouts_for_this_holder));
|
||||||
|
ilog("Just pushed virtual op for payout to ${account}", ("account", (*last_holder_account_id)(db).name));
|
||||||
|
payouts_for_this_holder.clear();
|
||||||
|
}
|
||||||
|
|
||||||
ilog("Processing payout of ${asset} to account ${account}",
|
ilog("Processing payout of ${asset} to account ${account}",
|
||||||
("asset", asset(pending_balance_object.pending_balance, pending_balance_object.dividend_payout_asset_type))
|
("asset", asset(pending_balance_object.pending_balance, pending_balance_object.dividend_payout_asset_type))
|
||||||
("account", pending_balance_object.owner(db).name));
|
("account", pending_balance_object.owner(db).name));
|
||||||
|
|
@ -939,6 +956,9 @@ void process_dividend_assets(database& db)
|
||||||
db.adjust_balance(pending_balance_object.owner,
|
db.adjust_balance(pending_balance_object.owner,
|
||||||
asset(pending_balance_object.pending_balance,
|
asset(pending_balance_object.pending_balance,
|
||||||
pending_balance_object.dividend_payout_asset_type));
|
pending_balance_object.dividend_payout_asset_type));
|
||||||
|
payouts_for_this_holder.insert(asset(pending_balance_object.pending_balance,
|
||||||
|
pending_balance_object.dividend_payout_asset_type));
|
||||||
|
last_holder_account_id = pending_balance_object.owner;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
amounts_paid_out_by_asset[pending_balance_object.dividend_payout_asset_type] += pending_balance_object.pending_balance;
|
amounts_paid_out_by_asset[pending_balance_object.dividend_payout_asset_type] += pending_balance_object.pending_balance;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -946,6 +966,15 @@ void process_dividend_assets(database& db)
|
||||||
++pending_balance_object_iter;
|
++pending_balance_object_iter;
|
||||||
db.remove(pending_balance_object);
|
db.remove(pending_balance_object);
|
||||||
}
|
}
|
||||||
|
// we will always be left with the last holder's data, generate the virtual op for it now.
|
||||||
|
if (last_holder_account_id)
|
||||||
|
{
|
||||||
|
// we've moved on to a new account, generate the dividend payment virtual op for the previous one
|
||||||
|
db.push_applied_operation(asset_dividend_distribution_operation(dividend_holder_asset_obj.id,
|
||||||
|
*last_holder_account_id,
|
||||||
|
payouts_for_this_holder));
|
||||||
|
ilog("Just pushed virtual op for payout to ${account}", ("account", (*last_holder_account_id)(db).name));
|
||||||
|
}
|
||||||
|
|
||||||
// now debit the total amount of dividends paid out from the distribution account
|
// now debit the total amount of dividends paid out from the distribution account
|
||||||
auto distributed_balance_range =
|
auto distributed_balance_range =
|
||||||
|
|
|
||||||
|
|
@ -389,7 +389,8 @@ namespace graphene { namespace chain {
|
||||||
*/
|
*/
|
||||||
typedef generic_index<account_object, account_multi_index_type> account_index;
|
typedef generic_index<account_object, account_multi_index_type> account_index;
|
||||||
|
|
||||||
struct by_dividend_asset_account_asset{};
|
struct by_dividend_payout_account{};
|
||||||
|
struct by_dividend_account_payout{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup object_index
|
* @ingroup object_index
|
||||||
|
|
@ -398,13 +399,21 @@ namespace graphene { namespace chain {
|
||||||
pending_dividend_payout_balance_object,
|
pending_dividend_payout_balance_object,
|
||||||
indexed_by<
|
indexed_by<
|
||||||
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||||
ordered_unique< tag<by_dividend_asset_account_asset>,
|
ordered_unique< tag<by_dividend_payout_account>,
|
||||||
composite_key<
|
composite_key<
|
||||||
pending_dividend_payout_balance_object,
|
pending_dividend_payout_balance_object,
|
||||||
member<pending_dividend_payout_balance_object, asset_id_type, &pending_dividend_payout_balance_object::dividend_holder_asset_type>,
|
member<pending_dividend_payout_balance_object, asset_id_type, &pending_dividend_payout_balance_object::dividend_holder_asset_type>,
|
||||||
member<pending_dividend_payout_balance_object, asset_id_type, &pending_dividend_payout_balance_object::dividend_payout_asset_type>,
|
member<pending_dividend_payout_balance_object, asset_id_type, &pending_dividend_payout_balance_object::dividend_payout_asset_type>,
|
||||||
member<pending_dividend_payout_balance_object, account_id_type, &pending_dividend_payout_balance_object::owner>
|
member<pending_dividend_payout_balance_object, account_id_type, &pending_dividend_payout_balance_object::owner>
|
||||||
>
|
>
|
||||||
|
>,
|
||||||
|
ordered_unique< tag<by_dividend_account_payout>,
|
||||||
|
composite_key<
|
||||||
|
pending_dividend_payout_balance_object,
|
||||||
|
member<pending_dividend_payout_balance_object, asset_id_type, &pending_dividend_payout_balance_object::dividend_holder_asset_type>,
|
||||||
|
member<pending_dividend_payout_balance_object, account_id_type, &pending_dividend_payout_balance_object::owner>,
|
||||||
|
member<pending_dividend_payout_balance_object, asset_id_type, &pending_dividend_payout_balance_object::dividend_payout_asset_type>
|
||||||
|
>
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
> pending_dividend_payout_balance_object_multi_index_type;
|
> pending_dividend_payout_balance_object_multi_index_type;
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,43 @@ namespace graphene { namespace chain {
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual op generated when a dividend asset pays out dividends
|
||||||
|
*/
|
||||||
|
struct asset_dividend_distribution_operation : public base_operation
|
||||||
|
{
|
||||||
|
asset_dividend_distribution_operation() {}
|
||||||
|
asset_dividend_distribution_operation(const asset_id_type& dividend_asset_id,
|
||||||
|
const account_id_type& account_id,
|
||||||
|
const flat_set<asset>& amounts) :
|
||||||
|
dividend_asset_id(dividend_asset_id),
|
||||||
|
account_id(account_id),
|
||||||
|
amounts(amounts)
|
||||||
|
{}
|
||||||
|
struct fee_parameters_type { };
|
||||||
|
|
||||||
|
asset fee;
|
||||||
|
|
||||||
|
/// The dividend-paying asset which triggered this payout
|
||||||
|
asset_id_type dividend_asset_id;
|
||||||
|
|
||||||
|
/// The user account receiving the dividends
|
||||||
|
account_id_type account_id;
|
||||||
|
|
||||||
|
/// The amounts received
|
||||||
|
flat_set<asset> amounts;
|
||||||
|
|
||||||
|
extensions_type extensions;
|
||||||
|
|
||||||
|
account_id_type fee_payer()const { return account_id; }
|
||||||
|
void validate()const {
|
||||||
|
FC_ASSERT( false, "virtual operation" );
|
||||||
|
}
|
||||||
|
|
||||||
|
share_type calculate_fee(const fee_parameters_type& params)const
|
||||||
|
{ return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup operations
|
* @ingroup operations
|
||||||
*/
|
*/
|
||||||
|
|
@ -545,7 +582,7 @@ FC_REFLECT( graphene::chain::asset_update_feed_producers_operation::fee_paramete
|
||||||
FC_REFLECT( graphene::chain::asset_publish_feed_operation::fee_parameters_type, (fee) )
|
FC_REFLECT( graphene::chain::asset_publish_feed_operation::fee_parameters_type, (fee) )
|
||||||
FC_REFLECT( graphene::chain::asset_issue_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
FC_REFLECT( graphene::chain::asset_issue_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||||
FC_REFLECT( graphene::chain::asset_reserve_operation::fee_parameters_type, (fee) )
|
FC_REFLECT( graphene::chain::asset_reserve_operation::fee_parameters_type, (fee) )
|
||||||
|
FC_REFLECT( graphene::chain::asset_dividend_distribution_operation::fee_parameters_type, )
|
||||||
|
|
||||||
FC_REFLECT( graphene::chain::asset_create_operation,
|
FC_REFLECT( graphene::chain::asset_create_operation,
|
||||||
(fee)
|
(fee)
|
||||||
|
|
@ -593,3 +630,4 @@ FC_REFLECT( graphene::chain::asset_reserve_operation,
|
||||||
(fee)(payer)(amount_to_reserve)(extensions) )
|
(fee)(payer)(amount_to_reserve)(extensions) )
|
||||||
|
|
||||||
FC_REFLECT( graphene::chain::asset_fund_fee_pool_operation, (fee)(from_account)(asset_id)(amount)(extensions) );
|
FC_REFLECT( graphene::chain::asset_fund_fee_pool_operation, (fee)(from_account)(asset_id)(amount)(extensions) );
|
||||||
|
FC_REFLECT( graphene::chain::asset_dividend_distribution_operation, (fee)(dividend_asset_id)(account_id)(amounts)(extensions) );
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,8 @@ namespace graphene { namespace chain {
|
||||||
asset_settle_cancel_operation, // VIRTUAL
|
asset_settle_cancel_operation, // VIRTUAL
|
||||||
asset_claim_fees_operation,
|
asset_claim_fees_operation,
|
||||||
fba_distribute_operation, // VIRTUAL
|
fba_distribute_operation, // VIRTUAL
|
||||||
asset_update_dividend_operation
|
asset_update_dividend_operation,
|
||||||
|
asset_dividend_distribution_operation // VIRTUAL
|
||||||
> operation;
|
> operation;
|
||||||
|
|
||||||
/// @} // operations group
|
/// @} // operations group
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
#include <boost/version.hpp>
|
#include <boost/version.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
#include <boost/algorithm/string/join.hpp>
|
||||||
|
|
||||||
#include <boost/range/adaptor/map.hpp>
|
#include <boost/range/adaptor/map.hpp>
|
||||||
#include <boost/range/algorithm_ext/erase.hpp>
|
#include <boost/range/algorithm_ext/erase.hpp>
|
||||||
|
|
@ -123,6 +124,7 @@ public:
|
||||||
std::string operator()(const account_create_operation& op)const;
|
std::string operator()(const account_create_operation& op)const;
|
||||||
std::string operator()(const account_update_operation& op)const;
|
std::string operator()(const account_update_operation& op)const;
|
||||||
std::string operator()(const asset_create_operation& op)const;
|
std::string operator()(const asset_create_operation& op)const;
|
||||||
|
std::string operator()(const asset_dividend_distribution_operation& op)const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|
@ -2639,9 +2641,7 @@ std::string operation_printer::operator()(const T& op)const
|
||||||
operation_result_printer rprinter(wallet);
|
operation_result_printer rprinter(wallet);
|
||||||
std::string str_result = result.visit(rprinter);
|
std::string str_result = result.visit(rprinter);
|
||||||
if( str_result != "" )
|
if( str_result != "" )
|
||||||
{
|
|
||||||
out << " result: " << str_result;
|
out << " result: " << str_result;
|
||||||
}
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
std::string operation_printer::operator()(const transfer_from_blind_operation& op)const
|
std::string operation_printer::operator()(const transfer_from_blind_operation& op)const
|
||||||
|
|
@ -2721,6 +2721,22 @@ std::string operation_printer::operator()(const asset_create_operation& op) cons
|
||||||
return fee(op.fee);
|
return fee(op.fee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string operation_printer::operator()(const asset_dividend_distribution_operation& op)const
|
||||||
|
{
|
||||||
|
asset_object dividend_paying_asset = wallet.get_asset(op.dividend_asset_id);
|
||||||
|
account_object receiver = wallet.get_account(op.account_id);
|
||||||
|
|
||||||
|
out << receiver.name << " received dividend payments for " << dividend_paying_asset.symbol << ": ";
|
||||||
|
std::vector<std::string> pretty_payout_amounts;
|
||||||
|
for (const asset& payment : op.amounts)
|
||||||
|
{
|
||||||
|
asset_object payout_asset = wallet.get_asset(payment.asset);
|
||||||
|
pretty_payout_amounts.push_back(payout_asset.amount_to_pretty_string(payout_asset.amount));
|
||||||
|
}
|
||||||
|
out << boost::algorithm::join(pretty_payout_amounts, ", ");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
std::string operation_result_printer::operator()(const void_result& x) const
|
std::string operation_result_printer::operator()(const void_result& x) const
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
|
|
|
||||||
|
|
@ -1042,13 +1042,9 @@ int64_t database_fixture::get_dividend_pending_payout_balance(asset_id_type divi
|
||||||
{
|
{
|
||||||
const pending_dividend_payout_balance_object_index& pending_payout_balance_index =
|
const pending_dividend_payout_balance_object_index& pending_payout_balance_index =
|
||||||
db.get_index_type<pending_dividend_payout_balance_object_index>();
|
db.get_index_type<pending_dividend_payout_balance_object_index>();
|
||||||
dlog("searching ${a}", ("a", dividend_holder_asset_type(db).symbol));
|
|
||||||
dlog("searching ${b}", ("b", dividend_payout_asset_type(db).symbol));
|
|
||||||
dlog("searching ${c}", ("c", dividend_holder_account_id(db).name));
|
|
||||||
dlog("searching ${a} ${b} ${c}", ("a", dividend_holder_asset_type(db).symbol)("b", dividend_payout_asset_type(db).symbol)("c", dividend_holder_account_id(db).name));
|
|
||||||
auto pending_payout_iter =
|
auto pending_payout_iter =
|
||||||
pending_payout_balance_index.indices().get<by_dividend_asset_account_asset>().find(boost::make_tuple(dividend_holder_asset_type, dividend_payout_asset_type, dividend_holder_account_id));
|
pending_payout_balance_index.indices().get<by_dividend_payout_account>().find(boost::make_tuple(dividend_holder_asset_type, dividend_payout_asset_type, dividend_holder_account_id));
|
||||||
if (pending_payout_iter == pending_payout_balance_index.indices().get<by_dividend_asset_account_asset>().end())
|
if (pending_payout_iter == pending_payout_balance_index.indices().get<by_dividend_payout_account>().end())
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return pending_payout_iter->pending_balance.value;
|
return pending_payout_iter->pending_balance.value;
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include <graphene/chain/vesting_balance_object.hpp>
|
#include <graphene/chain/vesting_balance_object.hpp>
|
||||||
#include <graphene/chain/withdraw_permission_object.hpp>
|
#include <graphene/chain/withdraw_permission_object.hpp>
|
||||||
#include <graphene/chain/witness_object.hpp>
|
#include <graphene/chain/witness_object.hpp>
|
||||||
|
#include <graphene/account_history/account_history_plugin.hpp>
|
||||||
|
|
||||||
#include <fc/crypto/digest.hpp>
|
#include <fc/crypto/digest.hpp>
|
||||||
|
|
||||||
|
|
@ -1143,7 +1144,7 @@ BOOST_AUTO_TEST_CASE( create_dividend_uia )
|
||||||
asset_update_dividend_operation op;
|
asset_update_dividend_operation op;
|
||||||
op.issuer = dividend_holder_asset_object.issuer;
|
op.issuer = dividend_holder_asset_object.issuer;
|
||||||
op.asset_to_update = dividend_holder_asset_object.id;
|
op.asset_to_update = dividend_holder_asset_object.id;
|
||||||
op.new_options.next_payout_time = fc::time_point::now() + fc::minutes(1);
|
op.new_options.next_payout_time = db.head_block_time() + fc::minutes(1);
|
||||||
op.new_options.payout_interval = 60 * 60 * 24 * 7; // one week
|
op.new_options.payout_interval = 60 * 60 * 24 * 7; // one week
|
||||||
|
|
||||||
trx.operations.push_back(op);
|
trx.operations.push_back(op);
|
||||||
|
|
@ -1286,10 +1287,16 @@ BOOST_AUTO_TEST_CASE( create_dividend_uia )
|
||||||
generate_blocks(next_payout_scheduled_time);
|
generate_blocks(next_payout_scheduled_time);
|
||||||
// if the scheduled time fell on a maintenance interval, then we should have paid out.
|
// if the scheduled time fell on a maintenance interval, then we should have paid out.
|
||||||
// if not, we need to advance to the next maintenance interval to trigger the payout
|
// if not, we need to advance to the next maintenance interval to trigger the payout
|
||||||
BOOST_REQUIRE(dividend_data.options.next_payout_time);
|
if (dividend_data.options.next_payout_time)
|
||||||
if (*dividend_data.options.next_payout_time == next_payout_scheduled_time)
|
{
|
||||||
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
// we know there was a next_payout_time set when we entered this, so if
|
||||||
generate_block(); // get the maintenance skip slots out of the way
|
// it has been cleared, we must have already processed payouts, no need to
|
||||||
|
// further advance time.
|
||||||
|
BOOST_REQUIRE(dividend_data.options.next_payout_time);
|
||||||
|
if (*dividend_data.options.next_payout_time == next_payout_scheduled_time)
|
||||||
|
generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
|
||||||
|
generate_block(); // get the maintenance skip slots out of the way
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fc::time_point_sec old_next_payout_scheduled_time = *dividend_data.options.next_payout_time;
|
fc::time_point_sec old_next_payout_scheduled_time = *dividend_data.options.next_payout_time;
|
||||||
|
|
@ -1302,14 +1309,33 @@ BOOST_AUTO_TEST_CASE( create_dividend_uia )
|
||||||
BOOST_CHECK_MESSAGE(old_next_payout_scheduled_time + *dividend_data.options.payout_interval == *dividend_data.options.next_payout_time,
|
BOOST_CHECK_MESSAGE(old_next_payout_scheduled_time + *dividend_data.options.payout_interval == *dividend_data.options.next_payout_time,
|
||||||
"New payout was not scheduled for the expected time");
|
"New payout was not scheduled for the expected time");
|
||||||
|
|
||||||
|
auto verify_dividend_payout_operations = [&](const account_object& destination_account, const asset& expected_payout)
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Verifying the virtual op was created");
|
||||||
|
const account_transaction_history_index& hist_idx = db.get_index_type<account_transaction_history_index>();
|
||||||
|
auto account_history_range = hist_idx.indices().get<by_seq>().equal_range(boost::make_tuple(destination_account.id));
|
||||||
|
BOOST_REQUIRE(account_history_range.first != account_history_range.second);
|
||||||
|
const operation_history_object& history_object = std::prev(account_history_range.second)->operation_id(db);
|
||||||
|
const asset_dividend_distribution_operation& distribution_operation = history_object.op.get<asset_dividend_distribution_operation>();
|
||||||
|
BOOST_CHECK(distribution_operation.account_id == destination_account.id);
|
||||||
|
BOOST_CHECK(distribution_operation.amounts.find(expected_payout) != distribution_operation.amounts.end());
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("Verifying the payouts");
|
||||||
BOOST_CHECK_EQUAL(get_balance(alice, test_asset_object), 20000);
|
BOOST_CHECK_EQUAL(get_balance(alice, test_asset_object), 20000);
|
||||||
|
verify_dividend_payout_operations(alice, asset(20000, test_asset_object.id));
|
||||||
verify_pending_balance(alice, test_asset_object, 0);
|
verify_pending_balance(alice, test_asset_object, 0);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(bob, test_asset_object), 20000);
|
BOOST_CHECK_EQUAL(get_balance(bob, test_asset_object), 20000);
|
||||||
|
verify_dividend_payout_operations(bob, asset(20000, test_asset_object.id));
|
||||||
verify_pending_balance(bob, test_asset_object, 0);
|
verify_pending_balance(bob, test_asset_object, 0);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(get_balance(carol, test_asset_object), 30000);
|
BOOST_CHECK_EQUAL(get_balance(carol, test_asset_object), 30000);
|
||||||
|
verify_dividend_payout_operations(carol, asset(30000, test_asset_object.id));
|
||||||
verify_pending_balance(carol, test_asset_object, 0);
|
verify_pending_balance(carol, test_asset_object, 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_TEST_MESSAGE("Removing the payout interval");
|
BOOST_TEST_MESSAGE("Removing the payout interval");
|
||||||
{
|
{
|
||||||
asset_update_dividend_operation op;
|
asset_update_dividend_operation op;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue