Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep track of collateral #1836

Merged
merged 10 commits into from
Jul 29, 2019
5 changes: 4 additions & 1 deletion libraries/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ add_library( graphene_app
)

# need to link graphene_debug_witness because plugins aren't sufficiently isolated #246
target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_grouped_orders graphene_chain fc graphene_db graphene_net graphene_utilities graphene_debug_witness )
target_link_libraries( graphene_app
graphene_market_history graphene_account_history graphene_grouped_orders
graphene_api_helper_indexes
graphene_chain fc graphene_db graphene_net graphene_utilities graphene_debug_witness )
target_include_directories( graphene_app
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../egenesis/include" )
Expand Down
87 changes: 56 additions & 31 deletions libraries/app/database_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
vector<vesting_balance_object> get_vesting_balances( const std::string account_id_or_name )const;

// Assets
uint64_t get_asset_count()const;
asset_id_type get_asset_id_from_string(const std::string& symbol_or_id)const;
vector<optional<asset_object>> get_assets(const vector<std::string>& asset_symbols_or_ids)const;
vector<asset_object> list_assets(const string& lower_bound_symbol, uint32_t limit)const;
vector<optional<asset_object>> lookup_asset_symbols(const vector<string>& symbols_or_ids)const;
uint64_t get_asset_count()const;
vector<asset_object> get_assets_by_issuer(const std::string& issuer_name_or_id,
asset_id_type start, uint32_t limit)const;
vector<optional<extended_asset_object>> get_assets(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<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;

// Markets / feeds
vector<limit_order_object> get_limit_orders(const std::string& a, const std::string& b, uint32_t limit)const;
Expand Down Expand Up @@ -262,6 +262,20 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
return account;
}

template<class ASSET>
extended_asset_object extend_asset( ASSET&& a )const
{
asset_id_type id = a.id;
extended_asset_object result = extended_asset_object( std::forward<ASSET>( a ) );
if( amount_in_collateral_index )
{
result.total_in_collateral = amount_in_collateral_index->get_amount_in_collateral( id );
if( result.bitasset_data_id.valid() )
result.total_backing_collateral = amount_in_collateral_index->get_backing_collateral( id );
}
return result;
}

const asset_object* get_asset_from_string( const std::string& symbol_or_id, bool throw_if_not_found = true ) const
{
// TODO cache the result to avoid repeatly fetching from db
Expand All @@ -280,16 +294,16 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
FC_ASSERT( asset, "no such asset" );
return asset;
}
vector<optional<asset_object>> get_assets(const vector<asset_id_type>& asset_ids)const
vector<optional<extended_asset_object>> get_assets(const vector<asset_id_type>& asset_ids)const
{
vector<optional<asset_object>> result; result.reserve(asset_ids.size());
vector<optional<extended_asset_object>> result; result.reserve(asset_ids.size());
std::transform(asset_ids.begin(), asset_ids.end(), std::back_inserter(result),
[this](asset_id_type id) -> optional<asset_object> {
[this](asset_id_type id) -> optional<extended_asset_object> {
if(auto o = _db.find(id))
{
if( _enabled_auto_subscription )
subscribe_to_item( id );
return *o;
return extend_asset( *o );
}
return {};
});
Expand Down Expand Up @@ -374,6 +388,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
map< pair<asset_id_type,asset_id_type>, std::function<void(const variant&)> > _market_subscriptions;
graphene::chain::database& _db;
const application_options* _app_options = nullptr;
const graphene::api_helper_indexes::amount_in_collateral_index* amount_in_collateral_index;
};

//////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -405,6 +420,16 @@ database_api_impl::database_api_impl( graphene::chain::database& db, const appli
_pending_trx_connection = _db.on_pending_transaction.connect([this](const signed_transaction& trx ){
if( _pending_trx_callback ) _pending_trx_callback( fc::variant(trx, GRAPHENE_MAX_NESTED_OBJECTS) );
});
try
{
amount_in_collateral_index = &_db.get_index_type< primary_index< call_order_index > >()
.get_secondary_index<graphene::api_helper_indexes::amount_in_collateral_index>();
}
catch( fc::assert_exception& e )
{
wlog( "amount_in_collateral_index not found - please enable api_helper_indexes plugin!" );
amount_in_collateral_index = nullptr;
}
}

database_api_impl::~database_api_impl()
Expand Down Expand Up @@ -1291,39 +1316,39 @@ asset_id_type database_api::get_asset_id_from_string(const std::string& symbol_o
return my->get_asset_from_string( symbol_or_id )->id;
}

vector<optional<asset_object>> database_api::get_assets(const vector<std::string>& asset_symbols_or_ids)const
vector<optional<extended_asset_object>> database_api::get_assets(const vector<std::string>& asset_symbols_or_ids)const
{
return my->get_assets( asset_symbols_or_ids );
}

vector<optional<asset_object>> database_api_impl::get_assets(const vector<std::string>& asset_symbols_or_ids)const
vector<optional<extended_asset_object>> database_api_impl::get_assets(const vector<std::string>& asset_symbols_or_ids)const
{
vector<optional<asset_object>> result; result.reserve(asset_symbols_or_ids.size());
vector<optional<extended_asset_object>> 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<asset_object> {
[this](std::string id_or_name) -> optional<extended_asset_object> {

const asset_object* asset_obj = get_asset_from_string( id_or_name, false );
if( asset_obj == nullptr )
return {};
if( _enabled_auto_subscription )
subscribe_to_item( asset_obj->id );
return *asset_obj;
return extend_asset( *asset_obj );
});
return result;
}

vector<asset_object> database_api::list_assets(const string& lower_bound_symbol, uint32_t limit)const
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 );
}

vector<asset_object> database_api_impl::list_assets(const string& lower_bound_symbol, uint32_t limit)const
vector<extended_asset_object> database_api_impl::list_assets(const string& lower_bound_symbol, uint32_t limit)const
{
uint64_t api_limit_get_assets = _app_options->api_limit_get_assets;
FC_ASSERT( limit <= api_limit_get_assets );

const auto& assets_by_symbol = _db.get_index_type<asset_index>().indices().get<by_symbol>();
vector<asset_object> result;
vector<extended_asset_object> result;
result.reserve(limit);

auto itr = assets_by_symbol.lower_bound(lower_bound_symbol);
Expand All @@ -1332,7 +1357,7 @@ vector<asset_object> database_api_impl::list_assets(const string& lower_bound_sy
itr = assets_by_symbol.begin();

while(limit-- && itr != assets_by_symbol.end())
result.emplace_back(*itr++);
result.emplace_back( extend_asset( *itr++ ) );

return result;
}
Expand All @@ -1347,50 +1372,50 @@ uint64_t database_api_impl::get_asset_count()const
return _db.get_index_type<asset_index>().indices().size();
}

vector<asset_object> database_api::get_assets_by_issuer(const std::string& issuer_name_or_id,
asset_id_type start, uint32_t limit)const
vector<extended_asset_object> database_api::get_assets_by_issuer(const std::string& issuer_name_or_id,
asset_id_type start, uint32_t limit)const
{
return my->get_assets_by_issuer(issuer_name_or_id, start, limit);
}

vector<asset_object> database_api_impl::get_assets_by_issuer(const std::string& issuer_name_or_id,
asset_id_type start, uint32_t limit)const
vector<extended_asset_object> database_api_impl::get_assets_by_issuer(const std::string& issuer_name_or_id,
asset_id_type start, uint32_t limit)const
{
uint64_t api_limit_get_assets = _app_options->api_limit_get_assets;
FC_ASSERT( limit <= api_limit_get_assets );

vector<asset_object> result;
vector<extended_asset_object> result;
const account_id_type account = get_account_from_string(issuer_name_or_id)->id;
const auto& asset_idx = _db.get_index_type<asset_index>().indices().get<by_issuer>();
auto asset_index_end = asset_idx.end();
auto asset_itr = asset_idx.lower_bound(boost::make_tuple(account, start));
while(asset_itr != asset_index_end && asset_itr->issuer == account && result.size() < limit)
{
result.push_back(*asset_itr);
result.emplace_back( extend_asset( *asset_itr ) );
++asset_itr;
}
return result;
}

vector<optional<asset_object>> database_api::lookup_asset_symbols(const vector<string>& symbols_or_ids)const
vector<optional<extended_asset_object>> database_api::lookup_asset_symbols(const vector<string>& symbols_or_ids)const
{
return my->lookup_asset_symbols( symbols_or_ids );
}

vector<optional<asset_object>> database_api_impl::lookup_asset_symbols(const vector<string>& symbols_or_ids)const
vector<optional<extended_asset_object>> database_api_impl::lookup_asset_symbols(const vector<string>& symbols_or_ids)const
{
const auto& assets_by_symbol = _db.get_index_type<asset_index>().indices().get<by_symbol>();
vector<optional<asset_object> > result;
vector<optional<extended_asset_object> > result;
result.reserve(symbols_or_ids.size());
std::transform(symbols_or_ids.begin(), symbols_or_ids.end(), std::back_inserter(result),
[this, &assets_by_symbol](const string& symbol_or_id) -> optional<asset_object> {
[this, &assets_by_symbol](const string& symbol_or_id) -> optional<extended_asset_object> {
if( !symbol_or_id.empty() && std::isdigit(symbol_or_id[0]) )
{
auto ptr = _db.find(variant(symbol_or_id, 1).as<asset_id_type>(1));
return ptr == nullptr? optional<asset_object>() : *ptr;
return ptr == nullptr? optional<extended_asset_object>() : extend_asset( *ptr );
}
auto itr = assets_by_symbol.find(symbol_or_id);
return itr == assets_by_symbol.end()? optional<asset_object>() : *itr;
return itr == assets_by_symbol.end()? optional<extended_asset_object>() : extend_asset( *itr );
});
return result;
}
Expand Down
24 changes: 19 additions & 5 deletions libraries/app/include/graphene/app/database_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <graphene/chain/witness_object.hpp>
#include <graphene/chain/htlc_object.hpp>

#include <graphene/api_helper_indexes/api_helper_indexes.hpp>
#include <graphene/market_history/market_history_plugin.hpp>

#include <fc/api.hpp>
Expand Down Expand Up @@ -125,6 +126,16 @@ struct market_trade
account_id_type side2_account_id = GRAPHENE_NULL_ACCOUNT;
};

struct extended_asset_object : asset_object
{
extended_asset_object() {}
explicit extended_asset_object( const asset_object& a ) : asset_object( a ) {}
explicit extended_asset_object( asset_object&& a ) : asset_object( std::move(a) ) {}

optional<share_type> total_in_collateral;
optional<share_type> total_backing_collateral;
};

/**
* @brief The database_api class implements the RPC API for the chain database.
*
Expand Down Expand Up @@ -416,15 +427,15 @@ class database_api
*
* This function has semantics identical to @ref get_objects
*/
vector<optional<asset_object>> get_assets(const vector<std::string>& asset_symbols_or_ids)const;
vector<optional<extended_asset_object>> get_assets(const vector<std::string>& asset_symbols_or_ids)const;

/**
* @brief Get assets alphabetically 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)
* @return The assets found
*/
vector<asset_object> list_assets(const string& lower_bound_symbol, uint32_t limit)const;
vector<extended_asset_object> list_assets(const string& lower_bound_symbol, uint32_t limit)const;

/**
* @brief Get a list of assets by symbol
Expand All @@ -433,7 +444,7 @@ class database_api
*
* This function has semantics identical to @ref get_objects
*/
vector<optional<asset_object>> lookup_asset_symbols(const vector<string>& symbols_or_ids)const;
vector<optional<extended_asset_object>> lookup_asset_symbols(const vector<string>& symbols_or_ids)const;

/**
* @brief Get assets count
Expand All @@ -448,8 +459,8 @@ class database_api
* @param limit Maximum number of orders to retrieve
* @return The assets issued by the account
*/
vector<asset_object> get_assets_by_issuer(const std::string& issuer_name_or_id,
asset_id_type start, uint32_t limit)const;
vector<extended_asset_object> get_assets_by_issuer(const std::string& issuer_name_or_id,
asset_id_type start, uint32_t limit)const;

/////////////////////
// Markets / feeds //
Expand Down Expand Up @@ -836,6 +847,9 @@ FC_REFLECT( graphene::app::market_ticker,
FC_REFLECT( graphene::app::market_volume, (time)(base)(quote)(base_volume)(quote_volume) );
FC_REFLECT( graphene::app::market_trade, (sequence)(date)(price)(amount)(value)(side1_account_id)(side2_account_id) );

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

FC_API(graphene::app::database_api,
// Objects
(get_objects)
Expand Down
10 changes: 0 additions & 10 deletions libraries/chain/asset_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,6 @@ FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::asset_bitasset_data_object, (gr
(feed_cer_updated)
)

FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::asset_object, (graphene::db::object),
(symbol)
(precision)
(issuer)
(options)
(dynamic_asset_data_id)
(bitasset_data_id)
(buyback_account)
)

GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::chain::asset_object )
GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::chain::asset_bitasset_data_object )
GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::chain::asset_dynamic_data_object )
11 changes: 10 additions & 1 deletion libraries/chain/include/graphene/chain/asset_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,16 @@ MAP_OBJECT_ID_TO_TYPE(graphene::chain::asset_object)
MAP_OBJECT_ID_TO_TYPE(graphene::chain::asset_dynamic_data_object)
MAP_OBJECT_ID_TO_TYPE(graphene::chain::asset_bitasset_data_object)

FC_REFLECT_TYPENAME( graphene::chain::asset_object )
FC_REFLECT_DERIVED( graphene::chain::asset_object, (graphene::db::object),
(symbol)
(precision)
(issuer)
(options)
(dynamic_asset_data_id)
(bitasset_data_id)
(buyback_account)
)

FC_REFLECT_TYPENAME( graphene::chain::asset_bitasset_data_object )
FC_REFLECT_TYPENAME( graphene::chain::asset_dynamic_data_object )

Expand Down
1 change: 1 addition & 0 deletions libraries/plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ add_subdirectory( delayed_node )
add_subdirectory( debug_witness )
add_subdirectory( snapshot )
add_subdirectory( es_objects )
add_subdirectory( api_helper_indexes )
22 changes: 22 additions & 0 deletions libraries/plugins/api_helper_indexes/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
file(GLOB HEADERS "include/graphene/api_helper_indexes/*.hpp")

add_library( graphene_api_helper_indexes
api_helper_indexes.cpp
)

target_link_libraries( graphene_api_helper_indexes graphene_chain graphene_app )
target_include_directories( graphene_api_helper_indexes
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )

if(MSVC)
set_source_files_properties(api_helper_indexes.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
endif(MSVC)

install( TARGETS
graphene_api_helper_indexes

RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
INSTALL( FILES ${HEADERS} DESTINATION "include/graphene/api_helper_indexes" )
Loading