Skip to content

Commit

Permalink
Add APIs to query for general asset info
Browse files Browse the repository at this point in the history
- Add a `symbol` field in asset_bitasset_data_object
- Add indices related to asset symbol
- Add `get_assets_general_info` API
- Add `list_assets_general_info` API
  • Loading branch information
abitmore committed Aug 15, 2019
1 parent d51305c commit 5c4c32a
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 13 deletions.
17 changes: 17 additions & 0 deletions libraries/app/api_objects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,21 @@ market_ticker::market_ticker(const fc::time_point_sec& now,
quote_volume = "0";
}

general_asset_info::general_asset_info( const asset_object& a, const asset_bitasset_data_object* b )
: id(a.id), symbol(a.symbol), precision(a.precision), issuer(a.issuer)
{
if( id == asset_id_type() )
type = CORE;
else if( !b )
type = UIA;
else
{
if( b->is_prediction_market )
type = PM;
else
type = MPA;
backing_asset_id = b->options.short_backing_asset;
}
}

} } // graphene::app
150 changes: 150 additions & 0 deletions libraries/app/database_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,30 @@ vector<optional<extended_asset_object>> database_api_impl::get_assets(
return result;
}

vector<optional<general_asset_info>> database_api::get_assets_general_info(
const vector<std::string>& asset_symbols_or_ids ) const
{
return my->get_assets_general_info( asset_symbols_or_ids );
}

vector<optional<general_asset_info>> database_api_impl::get_assets_general_info(
const vector<std::string>& asset_symbols_or_ids ) const
{
vector<optional<general_asset_info>> result; result.reserve(asset_symbols_or_ids.size());
std::transform(asset_symbols_or_ids.begin(), asset_symbols_or_ids.end(), std::back_inserter(result),
[this](std::string id_or_name) -> optional<general_asset_info> {

const asset_object* asset_obj = get_asset_from_string( id_or_name, false );
if( asset_obj == nullptr )
return {};
const asset_bitasset_data_object* bitasset = nullptr;
if( asset_obj->is_market_issued() )
bitasset = &asset_obj->bitasset_data(_db);
return general_asset_info( *asset_obj, bitasset );
});
return result;
}

vector<extended_asset_object> database_api::list_assets(const string& lower_bound_symbol, uint32_t limit)const
{
return my->list_assets( lower_bound_symbol, limit );
Expand All @@ -889,6 +913,132 @@ vector<extended_asset_object> database_api_impl::list_assets(const string& lower
return result;
}

vector<general_asset_info> database_api::list_assets_general_info(
optional<string> lower_bound_symbol,
optional<uint32_t> limit,
optional<general_asset_info::asset_type> type )const
{
return my->list_assets_general_info( lower_bound_symbol, limit, type );
}

vector<general_asset_info> database_api_impl::list_assets_general_info(
optional<string> lower_bound_symbol,
optional<uint32_t> olimit,
optional<general_asset_info::asset_type> type )const
{
uint32_t limit = olimit.valid() ? *olimit : 100;
uint64_t api_limit_get_assets = _app_options->api_limit_get_assets;
FC_ASSERT( limit <= api_limit_get_assets );

vector<general_asset_info> result;
if( limit == 0 )
return result;

result.reserve(limit);

if( !type.valid() || *type == general_asset_info::ALL )
{
const auto& assets_by_symbol = _db.get_index_type<asset_index>().indices().get<by_symbol>();
auto itr = lower_bound_symbol.valid() ? assets_by_symbol.lower_bound(*lower_bound_symbol)
: assets_by_symbol.begin();
for( ; limit > 0 && itr != assets_by_symbol.end(); ++itr, --limit )
{
const asset_object& asset_obj = *itr;
const asset_bitasset_data_object* bitasset = nullptr;
if( asset_obj.is_market_issued() )
bitasset = &asset_obj.bitasset_data(_db);
result.emplace_back( asset_obj, bitasset );
}
return result;
}

const asset_object& core_asset = _db.get_core_asset();
if( *type == general_asset_info::CORE )
{
if( !lower_bound_symbol.valid() || *lower_bound_symbol <= core_asset.symbol )
result.emplace_back( core_asset );
return result;
}

switch( *type )
{
case general_asset_info::UIA :
case general_asset_info::CORE_OR_UIA :
case general_asset_info::MPA_OR_PM :
{
const auto& assets_by_type_symbol = _db.get_index_type<asset_index>().indices().get<by_type_symbol>();
auto itr = assets_by_type_symbol.begin();
auto itr_end = assets_by_type_symbol.end();

if( *type == general_asset_info::MPA_OR_PM )
{
if( lower_bound_symbol.valid() )
itr = assets_by_type_symbol.lower_bound( boost::make_tuple( true, *lower_bound_symbol ) );
else
itr = assets_by_type_symbol.lower_bound( true );
}
else
{
itr_end = assets_by_type_symbol.lower_bound( true );
if( lower_bound_symbol.valid() )
itr = assets_by_type_symbol.lower_bound( boost::make_tuple( false, *lower_bound_symbol ) );
// else itr = assets_by_type_symbol.begin()
}

bool include_core = ( *type == general_asset_info::CORE_OR_UIA );
bool mpa_or_pm = ( *type == general_asset_info::MPA_OR_PM );

for( ; limit > 0 && itr != itr_end; ++itr )
{
const asset_object& asset_obj = *itr;
if( !include_core && (&asset_obj) == (&core_asset) )
continue;
const asset_bitasset_data_object* bitasset = nullptr;
if( mpa_or_pm )
bitasset = &asset_obj.bitasset_data(_db);
result.emplace_back( asset_obj, bitasset );
--limit;
}
break;
}
case general_asset_info::MPA :
case general_asset_info::PM :
{
const auto& bitassets_by_type_symbol = _db.get_index_type<asset_bitasset_data_index>().indices()
.get<by_type_symbol>();
auto itr = bitassets_by_type_symbol.begin();
auto itr_end = bitassets_by_type_symbol.end();

if( *type == general_asset_info::PM )
{
if( lower_bound_symbol.valid() )
itr = bitassets_by_type_symbol.lower_bound( boost::make_tuple( true, *lower_bound_symbol ) );
else
itr = bitassets_by_type_symbol.lower_bound( true );
}
else
{
itr_end = bitassets_by_type_symbol.lower_bound( true );
if( lower_bound_symbol.valid() )
itr = bitassets_by_type_symbol.lower_bound( boost::make_tuple( false, *lower_bound_symbol ) );
// else itr = bitassets_by_type_symbol.begin()
}

for( ; limit > 0 && itr != itr_end; ++itr, --limit )
{
const asset_bitasset_data_object& bitasset = *itr;
const asset_object& asset_obj = bitasset.asset_id(_db);
result.emplace_back( asset_obj, &bitasset );
}
break;
}
default: // nothing here
break;
}

return result;
}

uint64_t database_api::get_asset_count()const
{
return my->get_asset_count();
Expand Down
6 changes: 6 additions & 0 deletions libraries/app/database_api_impl.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,13 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
asset_id_type get_asset_id_from_string(const std::string& symbol_or_id)const;
vector<optional<extended_asset_object>> get_assets( const vector<std::string>& asset_symbols_or_ids,
optional<bool> subscribe )const;
vector<optional<general_asset_info>> get_assets_general_info(
const vector<std::string>& asset_symbols_or_ids ) const;
vector<extended_asset_object> list_assets(const string& lower_bound_symbol, uint32_t limit)const;
vector<general_asset_info> list_assets_general_info(
optional<string> lower_bound_symbol,
optional<uint32_t> limit,
optional<general_asset_info::asset_type> type )const;
vector<optional<extended_asset_object>> lookup_asset_symbols(const vector<string>& symbols_or_ids)const;
vector<extended_asset_object> get_assets_by_issuer(const std::string& issuer_name_or_id,
asset_id_type start, uint32_t limit)const;
Expand Down
30 changes: 30 additions & 0 deletions libraries/app/include/graphene/app/api_objects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,32 @@ namespace graphene { namespace app {
optional<share_type> total_backing_collateral;
};

/// General information of an asset
struct general_asset_info
{
/// General asset types
enum asset_type
{
CORE, ///< Core asset
UIA, ///< User-issued asset
MPA, ///< Market-pegged asset
PM, ///< Predition market
CORE_OR_UIA, ///< CORE or UIA, to be used as query parameter
MPA_OR_PM, ///< MPA or PM, to be used as query parameter
ALL ///< ALL, to be used as query parameter
};

explicit general_asset_info( const asset_object& a,
const asset_bitasset_data_object* b = nullptr );

asset_id_type id; ///< ID of this asset, i.e. "1.3.1"
string symbol; ///< Ticker symbol for this asset, i.e. "USD"
uint8_t precision = 0; ///< Maximum number of digits after the decimal point
account_id_type issuer; ///< ID of the account which created this asset
asset_type type; ///< Type of the asset
optional<asset_id_type> backing_asset_id; ///< ID of backing asset if this asset is a MPA or PM
};

} }

FC_REFLECT( graphene::app::more_data,
Expand Down Expand Up @@ -184,3 +210,7 @@ FC_REFLECT( graphene::app::market_trade, (sequence)(date)(price)(amount)(value)(

FC_REFLECT_DERIVED( graphene::app::extended_asset_object, (graphene::chain::asset_object),
(total_in_collateral)(total_backing_collateral) );

FC_REFLECT( graphene::app::general_asset_info, (id)(symbol)(precision)(issuer)(type)(backing_asset_id) )

FC_REFLECT_ENUM( graphene::app::general_asset_info::asset_type, (CORE)(UIA)(MPA)(PM)(CORE_OR_UIA)(MPA_OR_PM)(ALL) )
23 changes: 21 additions & 2 deletions libraries/app/include/graphene/app/database_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,13 +386,32 @@ class database_api
optional<bool> subscribe = optional<bool>() )const;

/**
* @brief Get assets alphabetically by symbol name
* @brief Get general info of a list of assets by symbol names or IDs
* @param asset_symbols_or_ids symbol names or IDs of the assets to retrieve
* @return General info of the assets corresponding to the provided symbol names or IDs
*/
vector<optional<general_asset_info>> get_assets_general_info(
const vector<std::string>& asset_symbols_or_ids ) const;

/**
* @brief Get assets alphabetically ordered by symbol name
* @param lower_bound_symbol Lower bound of symbol names to retrieve
* @param limit Maximum number of assets to fetch (must not exceed 101)
* @param limit Maximum number of assets to fetch
* @return The assets found
*/
vector<extended_asset_object> list_assets(const string& lower_bound_symbol, uint32_t limit)const;

/**
* @brief Get general info of assets alphabetically ordered by symbol name
* @param lower_bound_symbol Lower bound of symbol names to retrieve, optional, empty string if omitted
* @param limit Maximum number of assets to fetch, optional, @a 100 if omitted
* @param type type of assets to fetch, optional, @a ALL if omitted
* @return General info of the assets found
*/
vector<general_asset_info> list_assets_general_info( optional<string> lower_bound_symbol = {},
optional<uint32_t> limit = {},
optional<general_asset_info::asset_type> type = {} )const;

/**
* @brief Get a list of assets by symbol names or IDs
* @param symbols_or_ids symbol names or IDs of the assets to retrieve
Expand Down
1 change: 1 addition & 0 deletions libraries/chain/asset_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ object_id_type asset_create_evaluator::do_apply( const asset_create_operation& o
a.options = *op.bitasset_opts;
a.is_prediction_market = op.is_prediction_market;
a.asset_id = next_asset_id;
a.symbol = op.symbol;
}).id;

const asset_object& new_asset =
Expand Down
1 change: 1 addition & 0 deletions libraries/chain/asset_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::asset_dynamic_data_object, (gra

FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::asset_bitasset_data_object, (graphene::db::object),
(asset_id)
(symbol)
(feeds)
(current_feed)
(current_feed_publication_time)
Expand Down
4 changes: 3 additions & 1 deletion libraries/chain/db_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,10 +531,12 @@ void database::init_genesis(const genesis_state_type& genesis_state)
++collateral_holder_number;
}

bitasset_data_id = create<asset_bitasset_data_object>([&core_asset,new_asset_id](asset_bitasset_data_object& b) {
bitasset_data_id = create<asset_bitasset_data_object>(
[&core_asset,new_asset_id,&asset](asset_bitasset_data_object& b) {
b.options.short_backing_asset = core_asset.id;
b.options.minimum_feeds = GRAPHENE_DEFAULT_MINIMUM_FEEDS;
b.asset_id = new_asset_id;
b.symbol = asset.symbol;
}).id;
}

Expand Down
40 changes: 31 additions & 9 deletions libraries/chain/include/graphene/chain/asset_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ namespace graphene { namespace chain {
/// The asset this object belong to
asset_id_type asset_id;

/// The symbol of this asset
string symbol;

/// The tunable options for BitAssets are stored in this field.
bitasset_options options;

Expand Down Expand Up @@ -271,6 +274,8 @@ namespace graphene { namespace chain {
}
};

struct by_symbol;
struct by_type_symbol;
struct by_short_backing_asset;
struct by_feed_expiration;
struct by_cer_update;
Expand All @@ -279,38 +284,55 @@ namespace graphene { namespace chain {
asset_bitasset_data_object,
indexed_by<
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
ordered_unique< tag<by_symbol>,
member< asset_bitasset_data_object, string, &asset_bitasset_data_object::symbol >
>,
ordered_unique< tag<by_type_symbol>,
composite_key< asset_bitasset_data_object,
member< asset_bitasset_data_object, bool, &asset_bitasset_data_object::is_prediction_market >,
member< asset_bitasset_data_object, string, &asset_bitasset_data_object::symbol >
>
>,
ordered_non_unique< tag<by_short_backing_asset>, bitasset_short_backing_asset_extractor >,
ordered_unique< tag<by_feed_expiration>,
composite_key< asset_bitasset_data_object,
const_mem_fun< asset_bitasset_data_object, time_point_sec, &asset_bitasset_data_object::feed_expiration_time >,
const_mem_fun< asset_bitasset_data_object,
time_point_sec,
&asset_bitasset_data_object::feed_expiration_time >,
member< asset_bitasset_data_object, asset_id_type, &asset_bitasset_data_object::asset_id >
>
>,
ordered_non_unique< tag<by_cer_update>,
const_mem_fun< asset_bitasset_data_object, bool, &asset_bitasset_data_object::need_to_update_cer >
const_mem_fun< asset_bitasset_data_object, bool, &asset_bitasset_data_object::need_to_update_cer >
>
>
> asset_bitasset_data_object_multi_index_type;
typedef generic_index<asset_bitasset_data_object, asset_bitasset_data_object_multi_index_type> asset_bitasset_data_index;
typedef generic_index<asset_bitasset_data_object,
asset_bitasset_data_object_multi_index_type> asset_bitasset_data_index;

struct by_symbol;
struct by_type;
struct by_issuer;
typedef multi_index_container<
asset_object,
indexed_by<
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
ordered_unique< tag<by_symbol>, member<asset_object, string, &asset_object::symbol> >,
ordered_unique< tag<by_symbol>, member<asset_object, string, &asset_object::symbol > >,
ordered_unique< tag<by_type>,
composite_key< asset_object,
const_mem_fun<asset_object, bool, &asset_object::is_market_issued>,
member< object, object_id_type, &object::id >
const_mem_fun< asset_object, bool, &asset_object::is_market_issued >,
member< object, object_id_type, &object::id >
>
>,
ordered_unique< tag<by_type_symbol>,
composite_key< asset_object,
const_mem_fun< asset_object, bool, &asset_object::is_market_issued >,
member< asset_object, string, &asset_object::symbol >
>
>,
ordered_unique< tag<by_issuer>,
composite_key< asset_object,
member< asset_object, account_id_type, &asset_object::issuer >,
member< object, object_id_type, &object::id >
member< asset_object, account_id_type, &asset_object::issuer >,
member< object, object_id_type, &object::id >
>
>
>
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/include/graphene/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

#define GRAPHENE_MAX_NESTED_OBJECTS (200)

#define GRAPHENE_CURRENT_DB_VERSION "20190503"
#define GRAPHENE_CURRENT_DB_VERSION "20190810"

#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3
Expand Down

0 comments on commit 5c4c32a

Please sign in to comment.