GRPH-57-CompilerWarningFixesDBTests
This commit is contained in:
parent
4d426e1f5a
commit
dea5a973ba
6 changed files with 261 additions and 0 deletions
|
|
@ -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 "e, 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 "e, 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 "e, 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 //
|
||||
|
|
|
|||
|
|
@ -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 "e,
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
>
|
||||
>
|
||||
|
|
|
|||
|
|
@ -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 "e,
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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 "e,
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in a new issue