Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit 76c3104

Browse files
Alexey FrolovOpenLedgerApp
Alexey Frolov
authored andcommitted
Merge pull request bitshares#39 in DEV/bitshares-worker from dynamic-market-fee/CORE-841 to dynamic-market-fee/develop
Squashed commit of the following: commit 7ea2755b10b366736444246752c0ee33a127ecfe Author: Dmitry Yakovitsky <[email protected]> Date: Fri Jan 25 16:55:48 2019 +0300 CORE-841 Add trade_statistics_object + index. Fix notes. commit 1fa547cb8a7eaa15262b48d8e0b1647d2e6327aa Merge: 34a43a4 9fcdccd Author: Dmitry Yakovitsky <[email protected]> Date: Fri Jan 25 16:26:49 2019 +0300 Merge branch 'dynamic-market-fee/CORE-841' of https://bitbucket.aeteh.com/scm/dev/bitshares-worker into dynamic-market-fee/CORE-841 commit 34a43a47952ca59542e1c43506044026e11f0235 Author: Dmitry Yakovitsky <[email protected]> Date: Fri Jan 25 16:22:46 2019 +0300 CORE-841 Add trade_statistics_object + index. Fix notes. Use HARDFORK_DYNAMIC_FEE_TIME. commit 17aa3757879e2e2c221858028682192987275d45 Author: Dmitry Yakovitsky <[email protected]> Date: Fri Jan 25 14:11:34 2019 +0300 CORE-841 Add trade_statistics_object + index. Fix notes commit 6bf0b31954aa3e03a8f50733bf55cb5b1bfcc86c Author: Dmitry Yakovitsky <[email protected]> Date: Mon Jan 21 19:37:51 2019 +0300 CORE-841 Add trade_statistics_object + index. commit 21109a0a54679b39133de7e4d7a47d30cdb74e26 Author: Dmitry Yakovitsky <[email protected]> Date: Mon Jan 21 18:52:13 2019 +0300 CORE-841 Add trade_statistics_object + index. commit 3f3ce0ee35869c8b75886f14d968374bd8ba4b0d Author: Dmitry Yakovitsky <[email protected]> Date: Mon Jan 21 16:40:48 2019 +0300 CORE-841 Add trade_statistics_object + index. revert account_object.hpp commit 0e1575e3bbab5c19e06e4df8f3d1a7d788674d51 Author: Dmitry Yakovitsky <[email protected]> Date: Mon Jan 21 11:39:24 2019 +0300 CORE-841 Add trade_statistics_object + index. Fix UT commit 2e910da2f74f1b5d4d4aa4cb011f1230c5e27651 Author: Dmitry Yakovitsky <[email protected]> Date: Wed Jan 16 13:11:56 2019 +0300 CORE-841 Add trade_statistics_object + index commit 3463741040614b7155fcf76a1db3d11bc89ac3cd Author: Dmitry Yakovitsky <[email protected]> Date: Fri Jan 25 12:37:16 2019 +0300 CORE-851 Create dynamic market fee hardfork commit 9fcdccd572428792bff5e139b83abcc621510399 Author: Dmitry Yakovitsky <[email protected]> Date: Mon Jan 21 19:37:51 2019 +0300 CORE-841 Add trade_statistics_object + index. commit f2c69b0ef323a648532e13d3446808dce566d901 Author: Dmitry Yakovitsky <[email protected]> Date: Mon Jan 21 18:52:13 2019 +0300 CORE-841 Add trade_statistics_object + index. commit af7a2bd1ac438bcc3e6a4a6aa3d205ef4c52e05a Author: Dmitry Yakovitsky <[email protected]> Date: Mon Jan 21 16:40:48 2019 +0300 CORE-841 Add trade_statistics_object + index. revert account_object.hpp commit 19846687698b31d8b8c78893ed183e679dceab11 Author: Dmitry Yakovitsky <[email protected]> Date: Mon Jan 21 11:39:24 2019 +0300 CORE-841 Add trade_statistics_object + index. Fix UT commit 74cfda21f3e3cbfb12a5e5f9de0dd47ad060d878 Author: Dmitry Yakovitsky <[email protected]> Date: Wed Jan 16 13:11:56 2019 +0300 CORE-841 Add trade_statistics_object + index
1 parent 1ab5ff4 commit 76c3104

File tree

6 files changed

+234
-2
lines changed

6 files changed

+234
-2
lines changed

libraries/chain/db_init.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ void database::initialize_indexes()
230230
add_index< primary_index< buyback_index > >();
231231
add_index< primary_index<collateral_bid_index > >();
232232
add_index< primary_index< simple_index< fba_accumulator_object > > >();
233+
add_index< primary_index< trade_statistics_index > >();
233234
}
234235

235236
void database::init_genesis(const genesis_state_type& genesis_state)

libraries/chain/db_market.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,48 @@ namespace graphene { namespace chain { namespace detail {
4444

4545
} //detail
4646

47+
namespace detail {
48+
49+
const trade_statistics_object* get_trade_statistics(const database &db, const account_id_type& account_id, const asset_id_type &asset_id)
50+
{
51+
auto& trade_statistics = db.get_index_type<trade_statistics_index>().indices().get<by_account_asset>();
52+
auto statistic_it = trade_statistics.find( boost::make_tuple(account_id, asset_id) );
53+
54+
if( statistic_it != trade_statistics.end() )
55+
{
56+
return &*statistic_it;
57+
}
58+
return nullptr;
59+
}
60+
61+
void adjust_trade_statistics(database &db, const account_id_type& account_id, const asset& amount)
62+
{
63+
try {
64+
if( amount.amount == 0 )
65+
return;
66+
67+
FC_ASSERT( amount.amount > 0, "Asset amount should be positive");
68+
69+
auto trade_statistic = get_trade_statistics(db, account_id, amount.asset_id);
70+
if( trade_statistic )
71+
{
72+
db.modify( *trade_statistic, [&amount]( trade_statistics_object& o)
73+
{
74+
o.total_volume += amount;
75+
});
76+
} else {
77+
auto block_time = db.head_block_time();
78+
79+
db.create<trade_statistics_object>([&account_id, &amount, &block_time](trade_statistics_object &o) {
80+
o.account_id = account_id;
81+
o.total_volume = amount;
82+
o.first_trade_date = block_time;
83+
});
84+
}
85+
} FC_CAPTURE_AND_RETHROW( (account_id)(amount))
86+
}
87+
}
88+
4789
/**
4890
* All margin positions are force closed at the swan price
4991
* Collateral received goes into a force-settlement fund
@@ -836,6 +878,11 @@ bool database::fill_limit_order( const limit_order_object& order, const asset& p
836878
assert( pays.asset_id != receives.asset_id );
837879
push_applied_operation( fill_order_operation( order.id, order.seller, pays, receives, issuer_fees, fill_price, is_maker ) );
838880

881+
if ( head_block_time() >= HARDFORK_DYNAMIC_FEE_TIME )
882+
{
883+
detail::adjust_trade_statistics(*this, seller.id, asset{ receives.amount, receives.asset_id });
884+
}
885+
839886
// conditional because cheap integer comparison may allow us to avoid two expensive modify() and object lookups
840887
if( order.deferred_fee > 0 )
841888
{

libraries/chain/db_notify.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,9 @@ void get_relevant_accounts( const object* obj, flat_set<account_id_type>& accoun
434434
FC_ASSERT( aobj != nullptr );
435435
accounts.insert( aobj->bidder );
436436
break;
437-
}
437+
}
438+
case impl_trade_statistics_object_type:
439+
break;
438440
}
439441
}
440442
} // end get_relevant_accounts( const object* obj, flat_set<account_id_type>& accounts )

libraries/chain/include/graphene/chain/market_object.hpp

+41
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,42 @@ typedef generic_index<call_order_object, call_order_multi_index_type>
270270
typedef generic_index<force_settlement_object, force_settlement_object_multi_index_type> force_settlement_index;
271271
typedef generic_index<collateral_bid_object, collateral_bid_object_multi_index_type> collateral_bid_index;
272272

273+
/**
274+
* @brief This class accumulates statistics for trading
275+
*/
276+
class trade_statistics_object : public graphene::db::abstract_object<trade_statistics_object>
277+
{
278+
public:
279+
static const uint8_t space_id = implementation_ids;
280+
static const uint8_t type_id = impl_trade_statistics_object_type;
281+
282+
account_id_type account_id;
283+
fc::time_point_sec first_trade_date; //first trade date for this asset
284+
asset total_volume; //total bought/sold assets volume
285+
asset_id_type get_asset_id() const { return total_volume.asset_id; }
286+
};
287+
288+
struct by_account_asset;
289+
struct by_id;
290+
/**
291+
* @ingroup object_index
292+
*/
293+
typedef multi_index_container<
294+
trade_statistics_object,
295+
indexed_by<
296+
ordered_unique< tag< by_id >, member< object, object_id_type, &object::id > >,
297+
ordered_unique< tag<by_account_asset>,
298+
composite_key<
299+
trade_statistics_object,
300+
member< trade_statistics_object, account_id_type, &trade_statistics_object::account_id >,
301+
const_mem_fun< trade_statistics_object, asset_id_type, &trade_statistics_object::get_asset_id >
302+
>
303+
>
304+
>
305+
> trade_statistics_multi_index_type;
306+
307+
typedef generic_index<trade_statistics_object, trade_statistics_multi_index_type> trade_statistics_index;
308+
273309
} } // graphene::chain
274310

275311
FC_REFLECT_DERIVED( graphene::chain::limit_order_object,
@@ -287,3 +323,8 @@ FC_REFLECT_DERIVED( graphene::chain::force_settlement_object,
287323

288324
FC_REFLECT_DERIVED( graphene::chain::collateral_bid_object, (graphene::db::object),
289325
(bidder)(inv_swan_price) )
326+
327+
FC_REFLECT_DERIVED( graphene::chain::trade_statistics_object,
328+
(graphene::db::object),
329+
(account_id)(first_trade_date)(total_volume)
330+
)

libraries/chain/include/graphene/chain/protocol/types.hpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ namespace graphene { namespace chain {
179179
impl_special_authority_object_type,
180180
impl_buyback_object_type,
181181
impl_fba_accumulator_object_type,
182-
impl_collateral_bid_object_type
182+
impl_collateral_bid_object_type,
183+
impl_trade_statistics_object_type
183184
};
184185

185186
//typedef fc::unsigned_int object_id_type;
@@ -234,6 +235,7 @@ namespace graphene { namespace chain {
234235
class buyback_object;
235236
class fba_accumulator_object;
236237
class collateral_bid_object;
238+
class trade_statistics_object;
237239

238240
typedef object_id< implementation_ids, impl_global_property_object_type, global_property_object> global_property_id_type;
239241
typedef object_id< implementation_ids, impl_dynamic_global_property_object_type, dynamic_global_property_object> dynamic_global_property_id_type;
@@ -255,6 +257,7 @@ namespace graphene { namespace chain {
255257
typedef object_id< implementation_ids, impl_buyback_object_type, buyback_object > buyback_id_type;
256258
typedef object_id< implementation_ids, impl_fba_accumulator_object_type, fba_accumulator_object > fba_accumulator_id_type;
257259
typedef object_id< implementation_ids, impl_collateral_bid_object_type, collateral_bid_object > collateral_bid_id_type;
260+
typedef object_id< implementation_ids, impl_trade_statistics_object_type, trade_statistics_object > trade_statistics_object_id_type;
258261

259262
typedef fc::ripemd160 block_id_type;
260263
typedef fc::ripemd160 checksum_type;
@@ -394,6 +397,7 @@ FC_REFLECT_ENUM( graphene::chain::impl_object_type,
394397
(impl_buyback_object_type)
395398
(impl_fba_accumulator_object_type)
396399
(impl_collateral_bid_object_type)
400+
(impl_trade_statistics_object_type)
397401
)
398402

399403
FC_REFLECT_TYPENAME( graphene::chain::share_type )
@@ -427,6 +431,7 @@ FC_REFLECT_TYPENAME( graphene::chain::buyback_id_type )
427431
FC_REFLECT_TYPENAME( graphene::chain::fba_accumulator_id_type )
428432
FC_REFLECT_TYPENAME( graphene::chain::collateral_bid_id_type )
429433
FC_REFLECT_TYPENAME( graphene::chain::htlc_id_type )
434+
FC_REFLECT_TYPENAME( graphene::chain::trade_statistics_object_id_type )
430435

431436
FC_REFLECT( graphene::chain::void_t, )
432437

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#include <boost/test/unit_test.hpp>
2+
#include <graphene/chain/market_object.hpp>
3+
#include <graphene/chain/hardfork.hpp>
4+
#include "../common/database_fixture.hpp"
5+
6+
7+
using namespace graphene::chain;
8+
using namespace graphene::chain::test;
9+
using namespace graphene::chain::detail;
10+
11+
namespace graphene { namespace chain {namespace detail {
12+
const trade_statistics_object* get_trade_statistics(const database &db, const account_id_type& account_id, const asset_id_type &asset_id);
13+
}}}
14+
15+
namespace fc
16+
{
17+
template<typename Ch, typename T>
18+
std::basic_ostream<Ch>& operator<<(std::basic_ostream<Ch>& os, safe<T> const& sf)
19+
{
20+
os << sf.value;
21+
return os;
22+
}
23+
}
24+
25+
struct dynamic_market_fee_database_fixture : database_fixture
26+
{
27+
const share_type core_precision = asset::scaled_precision( asset_id_type()(db).precision );
28+
29+
dynamic_market_fee_database_fixture()
30+
: database_fixture(HARDFORK_DYNAMIC_FEE_TIME - 100 )
31+
{}
32+
33+
asset core_asset(int64_t x )
34+
{
35+
return asset( x*core_precision );
36+
};
37+
38+
void issue_asset()
39+
{
40+
try
41+
{
42+
ACTORS((alice)(bob)(izzy)(jill));
43+
44+
fund( alice, core_asset(1000000) );
45+
fund( bob, core_asset(1000000) );
46+
fund( izzy, core_asset(1000000) );
47+
fund( jill, core_asset(1000000) );
48+
49+
price price(asset(1, asset_id_type(1)), asset(1));
50+
51+
asset_object izzycoin = create_user_issued_asset( "IZZYCOIN", izzy, charge_market_fee, price, 2 );
52+
53+
asset_object jillcoin = create_user_issued_asset( "JILLCOIN", jill, charge_market_fee, price, 2 );
54+
55+
// Alice and Bob create some coins
56+
issue_uia( alice, izzycoin.amount( 100000 ) );
57+
issue_uia( bob, jillcoin.amount( 100000 ) );
58+
}
59+
FC_LOG_AND_RETHROW()
60+
}
61+
};
62+
63+
BOOST_FIXTURE_TEST_SUITE( dynamic_market_fee_tests, dynamic_market_fee_database_fixture )
64+
65+
BOOST_AUTO_TEST_CASE(adjust_trade_statistics_test_before_HARDFORK_DYNAMIC_FEE_TIME_hf)
66+
{
67+
try
68+
{
69+
issue_asset();
70+
return;
71+
const asset_object &jillcoin = get_asset("JILLCOIN");
72+
const asset_object &izzycoin = get_asset("IZZYCOIN");
73+
74+
GET_ACTOR(alice);
75+
GET_ACTOR(bob);
76+
77+
// Alice and Bob place orders which match
78+
create_sell_order( alice_id, izzycoin.amount(100), jillcoin.amount(300) );
79+
create_sell_order( bob_id, jillcoin.amount(300), izzycoin.amount(100) );
80+
{
81+
const auto alice_izzycoin_tso = get_trade_statistics(db, alice_id, izzycoin.get_id());
82+
const auto alice_jillcoin_tso = get_trade_statistics(db, alice_id, jillcoin.get_id());
83+
84+
BOOST_CHECK(alice_izzycoin_tso == nullptr);
85+
BOOST_CHECK(alice_jillcoin_tso == nullptr);
86+
87+
const auto bob_izzycoin_tso = get_trade_statistics(db, bob_id, izzycoin.get_id());
88+
const auto bob_jillcoin_tso = get_trade_statistics(db, bob_id, jillcoin.get_id());
89+
90+
BOOST_CHECK(bob_izzycoin_tso == nullptr);
91+
BOOST_CHECK(bob_jillcoin_tso == nullptr);
92+
}
93+
} FC_LOG_AND_RETHROW()
94+
}
95+
96+
BOOST_AUTO_TEST_CASE(adjust_trade_statistics_test_after_HARDFORK_DYNAMIC_FEE_TIME_hf)
97+
{
98+
try
99+
{
100+
issue_asset();
101+
102+
generate_blocks(HARDFORK_DYNAMIC_FEE_TIME);
103+
104+
const asset_object &jillcoin = get_asset("JILLCOIN");
105+
const asset_object &izzycoin = get_asset("IZZYCOIN");
106+
107+
GET_ACTOR(alice);
108+
GET_ACTOR(bob);
109+
110+
set_expiration( db, trx );
111+
112+
// Alice and Bob place orders which match
113+
create_sell_order( alice_id, izzycoin.amount(100), jillcoin.amount(300) );
114+
create_sell_order( bob_id, jillcoin.amount(300), izzycoin.amount(100) );
115+
{
116+
const auto alice_jillcoin_tso = get_trade_statistics(db, alice_id, jillcoin.get_id());
117+
BOOST_CHECK_EQUAL(alice_jillcoin_tso->total_volume.amount, 300);
118+
119+
const auto bob_izzycoin_tso = get_trade_statistics(db, bob_id, izzycoin.get_id());
120+
BOOST_CHECK_EQUAL(bob_izzycoin_tso->total_volume.amount, 100);
121+
}
122+
// Alice and Bob place orders which match
123+
// trade_statistics should be updated
124+
create_sell_order( alice_id, izzycoin.amount(100), jillcoin.amount(300) );
125+
create_sell_order( bob_id, jillcoin.amount(300), izzycoin.amount(100) );
126+
{
127+
const auto alice_jillcoin_tso = get_trade_statistics(db, alice_id, jillcoin.get_id());
128+
BOOST_CHECK_EQUAL(alice_jillcoin_tso->total_volume.amount, 600);
129+
130+
const auto bob_izzycoin_tso = get_trade_statistics(db, bob_id, izzycoin.get_id());
131+
BOOST_CHECK_EQUAL(bob_izzycoin_tso->total_volume.amount, 200);
132+
}
133+
}
134+
FC_LOG_AND_RETHROW()
135+
}
136+
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)