GRPH-57-CompilerWarningFixesDBTests

This commit is contained in:
satyakoneru 2019-08-23 08:35:44 +00:00
parent 4d426e1f5a
commit dea5a973ba
6 changed files with 261 additions and 0 deletions

View file

@ -113,8 +113,15 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
vector<bet_object> get_unmatched_bets_for_bettor(betting_market_id_type, account_id_type) const;
vector<bet_object> get_all_unmatched_bets_for_bettor(account_id_type) const;
const account_object* get_account_from_string( const std::string& name_or_id, bool throw_if_not_found = true ) const;
// Markets / feeds
vector<limit_order_object> get_limit_orders(asset_id_type a, asset_id_type b, uint32_t limit)const;
vector<limit_order_object> get_account_limit_orders( const string& account_name_or_id,
const string &base,
const string &quote, uint32_t limit,
optional<limit_order_id_type> ostart_id,
optional<price> ostart_price );
vector<call_order_object> get_call_orders(asset_id_type a, uint32_t limit)const;
vector<force_settlement_object> get_settle_orders(asset_id_type a, uint32_t limit)const;
vector<call_order_object> get_margin_positions( const account_id_type& id )const;
@ -623,6 +630,92 @@ vector<optional<account_object>> database_api_impl::get_accounts(const vector<ac
return result;
}
vector<limit_order_object> database_api::get_account_limit_orders( const string& account_name_or_id, const string &base,
const string &quote, uint32_t limit, optional<limit_order_id_type> ostart_id, optional<price> ostart_price)
{
return my->get_account_limit_orders( account_name_or_id, base, quote, limit, ostart_id, ostart_price );
}
vector<limit_order_object> database_api_impl::get_account_limit_orders( const string& account_name_or_id, const string &base,
const string &quote, uint32_t limit, optional<limit_order_id_type> ostart_id, optional<price> ostart_price)
{
FC_ASSERT( limit <= 101 );
vector<limit_order_object> results;
uint32_t count = 0;
const account_object* account = get_account_from_string(account_name_or_id);
if (account == nullptr)
return results;
auto assets = lookup_asset_symbols( {base, quote} );
FC_ASSERT( assets[0], "Invalid base asset symbol: ${s}", ("s",base) );
FC_ASSERT( assets[1], "Invalid quote asset symbol: ${s}", ("s",quote) );
auto base_id = assets[0]->id;
auto quote_id = assets[1]->id;
if (ostart_price.valid()) {
FC_ASSERT(ostart_price->base.asset_id == base_id, "Base asset inconsistent with start price");
FC_ASSERT(ostart_price->quote.asset_id == quote_id, "Quote asset inconsistent with start price");
}
const auto& index_by_account = _db.get_index_type<limit_order_index>().indices().get<by_account>();
limit_order_multi_index_type::index<by_account>::type::const_iterator lower_itr;
limit_order_multi_index_type::index<by_account>::type::const_iterator upper_itr;
// if both order_id and price are invalid, query the first page
if ( !ostart_id.valid() && !ostart_price.valid() )
{
lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, price::max(base_id, quote_id)));
}
else if ( ostart_id.valid() )
{
// in case of the order been deleted during page querying
const limit_order_object *p_loo = _db.find(*ostart_id);
if ( !p_loo )
{
if ( ostart_price.valid() )
{
lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, *ostart_price, *ostart_id));
}
else
{
// start order id been deleted, yet not provided price either
FC_THROW("Order id invalid (maybe just been canceled?), and start price not provided");
}
}
else
{
const limit_order_object &loo = *p_loo;
// in case of the order not belongs to specified account or market
FC_ASSERT(loo.sell_price.base.asset_id == base_id, "Order base asset inconsistent");
FC_ASSERT(loo.sell_price.quote.asset_id == quote_id, "Order quote asset inconsistent with order");
FC_ASSERT(loo.seller == account->get_id(), "Order not owned by specified account");
lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, loo.sell_price, *ostart_id));
}
}
else
{
// if reach here start_price must be valid
lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, *ostart_price));
}
upper_itr = index_by_account.upper_bound(std::make_tuple(account->id, price::min(base_id, quote_id)));
// Add the account's orders
for ( ; lower_itr != upper_itr && count < limit; ++lower_itr, ++count)
{
const limit_order_object &order = *lower_itr;
results.emplace_back(order);
}
return results;
}
std::map<string,full_account> database_api::get_full_accounts( const vector<string>& names_or_ids, bool subscribe )
{
return my->get_full_accounts( names_or_ids, subscribe );
@ -1094,6 +1187,25 @@ vector<bet_object> database_api_impl::get_all_unmatched_bets_for_bettor(account_
return boost::copy_range<vector<bet_object> >(bet_idx.equal_range(std::make_tuple(bettor_id)));
}
const account_object* database_api_impl::get_account_from_string( const std::string& name_or_id, bool throw_if_not_found) const
{
// TODO cache the result to avoid repeatly fetching from db
FC_ASSERT( name_or_id.size() > 0);
const account_object* account = nullptr;
if (std::isdigit(name_or_id[0]))
account = _db.find(fc::variant(name_or_id).as<account_id_type>());
else
{
const auto& idx = _db.get_index_type<account_index>().indices().get<by_name>();
auto itr = idx.find(name_or_id);
if (itr != idx.end())
account = &*itr;
}
if(throw_if_not_found)
FC_ASSERT( account, "no such account" );
return account;
}
//////////////////////////////////////////////////////////////////////
// //
// Markets / feeds //

View file

@ -255,6 +255,36 @@ class database_api
*/
vector<optional<account_object>> get_accounts(const vector<account_id_type>& account_ids)const;
/**
* @brief Fetch all orders relevant to the specified account and specified market, result orders
* are sorted descendingly by price
*
* @param account_name_or_id The name or ID of an account to retrieve
* @param base Base asset
* @param quote Quote asset
* @param limit The limitation of items each query can fetch, not greater than 101
* @param start_id Start order id, fetch orders which price lower than this order, or price equal to this order
* but order ID greater than this order
* @param start_price Fetch orders with price lower than or equal to this price
*
* @return List of orders from @ref account_name_or_id to the corresponding account
*
* @note
* 1. if @ref account_name_or_id cannot be tied to an account, empty result will be returned
* 2. @ref start_id and @ref start_price can be empty, if so the api will return the "first page" of orders;
* if start_id is specified, its price will be used to do page query preferentially, otherwise the start_price
* will be used; start_id and start_price may be used cooperatively in case of the order specified by start_id
* was just canceled accidentally, in such case, the result orders' price may lower or equal to start_price,
* but orders' id greater than start_id
*/
vector<limit_order_object> get_account_limit_orders( const string& account_name_or_id,
const string &base,
const string &quote,
uint32_t limit = 101,
optional<limit_order_id_type> ostart_id = optional<limit_order_id_type>(),
optional<price> ostart_price = optional<price>());
/**
* @brief Fetch all objects relevant to the specified accounts and subscribe to updates
* @param callback Function to call with updates
@ -737,6 +767,7 @@ FC_API(graphene::app::database_api,
// Markets / feeds
(get_order_book)
(get_limit_orders)
(get_account_limit_orders)
(get_call_orders)
(get_settle_orders)
(get_margin_positions)

View file

@ -89,6 +89,7 @@ typedef multi_index_container<
ordered_unique< tag<by_account>,
composite_key< limit_order_object,
member<limit_order_object, account_id_type, &limit_order_object::seller>,
member<limit_order_object, price, &limit_order_object::sell_price>,
member<object, object_id_type, &object::id>
>
>

View file

@ -372,6 +372,30 @@ class wallet_api
vector<account_balance_object> list_core_accounts()const;
vector<bucket_object> get_market_history(string symbol, string symbol2, uint32_t bucket, fc::time_point_sec start, fc::time_point_sec end)const;
/**
* @brief Fetch all orders relevant to the specified account sorted descendingly by price
*
* @param name_or_id The name or ID of an account to retrieve
* @param base Base asset
* @param quote Quote asset
* @param limit The limitation of items each query can fetch (max: 101)
* @param ostart_id Start order id, fetch orders which price are lower than or equal to this order
* @param ostart_price Fetch orders with price lower than or equal to this price
*
* @return List of orders from \c name_or_id to the corresponding account
*
* @note
* 1. if \c name_or_id cannot be tied to an account, empty result will be returned
* 2. \c ostart_id and \c ostart_price can be \c null, if so the api will return the "first page" of orders;
* if \c ostart_id is specified and valid, its price will be used to do page query preferentially,
* otherwise the \c ostart_price will be used
*/
vector<limit_order_object> get_account_limit_orders( const string& name_or_id,
const string &base,
const string &quote,
uint32_t limit = 101,
optional<limit_order_id_type> ostart_id = optional<limit_order_id_type>(),
optional<price> ostart_price = optional<price>());
vector<limit_order_object> get_limit_orders(string a, string b, uint32_t limit)const;
vector<call_order_object> get_call_orders(string a, uint32_t limit)const;
vector<force_settlement_object> get_settle_orders(string a, uint32_t limit)const;
@ -1984,6 +2008,7 @@ FC_API( graphene::wallet::wallet_api,
(get_private_key)
(load_wallet_file)
(normalize_brain_key)
(get_account_limit_orders)
(get_limit_orders)
(get_call_orders)
(get_settle_orders)

View file

@ -3522,6 +3522,17 @@ vector<bucket_object> wallet_api::get_market_history( string symbol1, string sym
return my->_remote_hist->get_market_history( get_asset_id(symbol1), get_asset_id(symbol2), bucket, start, end );
}
vector<limit_order_object> wallet_api::get_account_limit_orders(
const string& name_or_id,
const string &base,
const string &quote,
uint32_t limit,
optional<limit_order_id_type> ostart_id,
optional<price> ostart_price)
{
return my->_remote_db->get_account_limit_orders(name_or_id, base, quote, limit, ostart_id, ostart_price);
}
vector<limit_order_object> wallet_api::get_limit_orders(string a, string b, uint32_t limit)const
{
return my->_remote_db->get_limit_orders(get_asset(a).id, get_asset(b).id, limit);

View file

@ -68,4 +68,85 @@ BOOST_FIXTURE_TEST_SUITE(database_api_tests, database_fixture)
} FC_LOG_AND_RETHROW()
}
BOOST_AUTO_TEST_CASE(get_account_limit_orders)
{ try {
ACTORS((seller));
const auto& bitcny = create_bitasset("CNY");
const auto& core = asset_id_type()(db);
int64_t init_balance(10000000);
transfer(committee_account, seller_id, asset(init_balance));
BOOST_CHECK_EQUAL( 10000000, get_balance(seller, core) );
/// Create 250 versatile orders
for (size_t i = 0 ; i < 50 ; ++i) {
BOOST_CHECK(create_sell_order(seller, core.amount(100), bitcny.amount(250)));
}
for (size_t i = 1 ; i < 101 ; ++i) {
BOOST_CHECK(create_sell_order(seller, core.amount(100), bitcny.amount(250 + i)));
BOOST_CHECK(create_sell_order(seller, core.amount(100), bitcny.amount(250 - i)));
}
graphene::app::database_api db_api(db);
std::vector<limit_order_object> results;
limit_order_object o;
// query with no constraint, expected:
// 1. up to 101 orders returned
// 2. orders were sorted by price desendingly
results = db_api.get_account_limit_orders(seller.name, "BTS", "CNY");
BOOST_CHECK(results.size() == 101);
for (size_t i = 0 ; i < results.size() - 1 ; ++i) {
BOOST_CHECK(results[i].sell_price >= results[i+1].sell_price);
}
results.clear();
// query with specified limit, expected:
// 1. up to specified amount of orders returned
// 2. orders were sorted by price desendingly
results = db_api.get_account_limit_orders(seller.name, "BTS", "CNY", 50);
results = db_api.get_account_limit_orders(seller.name, "BTS", "CNY", 50);
BOOST_CHECK(results.size() == 50);
for (size_t i = 0 ; i < results.size() - 1 ; ++i) {
BOOST_CHECK(results[i].sell_price >= results[i+1].sell_price);
}
o = results.back();
results.clear();
// query with specified order id and limit, expected:
// same as before, but also the first order's id equal to specified
results = db_api.get_account_limit_orders(seller.name, "BTS", "CNY", 100,
limit_order_id_type(o.id));
BOOST_CHECK(results.size() == 100);
BOOST_CHECK(results.front().id == o.id);
for (size_t i = 0 ; i < results.size() - 1 ; ++i) {
BOOST_CHECK(results[i].sell_price >= results[i+1].sell_price);
}
o = results.back();
results.clear();
// query with specified price and an not exists order id, expected:
// 1. the canceled order should not exists in returned orders and first order's
// id should greater than specified
// 2. returned orders sorted by price desendingly
// 3. the first order's sell price equal to specified
cancel_limit_order(o); // NOTE 1: this canceled order was in scope of the
// first created 50 orders, so with price 2.5 BTS/CNY
results = db_api.get_account_limit_orders(seller.name, "BTS", "CNY", 101,
limit_order_id_type(o.id), o.sell_price);
BOOST_CHECK(results.size() <= 101);
BOOST_CHECK(results.front().id > o.id);
// NOTE 2: because of NOTE 1, here should be equal
BOOST_CHECK(results.front().sell_price == o.sell_price);
for (size_t i = 0 ; i < results.size() - 1 ; ++i) {
BOOST_CHECK(results[i].sell_price >= results[i+1].sell_price);
}
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()