Database API

This commit is contained in:
Srdjan Obucina 2020-06-22 21:36:42 +02:00
parent 775eac55a9
commit d0c72f7cf7
6 changed files with 138 additions and 11 deletions

View file

@ -184,6 +184,12 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
// gpos
gpos_info get_gpos_info(const account_id_type account) const;
// NFT
uint64_t nft_get_balance(const account_id_type owner) const;
optional<account_id_type> nft_owner_of(const nft_id_type token_id) const;
optional<account_id_type> nft_get_approved(const nft_id_type token_id) const;
bool nft_is_approved_for_all(const account_id_type owner, const account_id_type operator_) const;
//private:
const account_object* get_account_from_string( const std::string& name_or_id,
bool throw_if_not_found = true ) const;
@ -2240,6 +2246,7 @@ graphene::app::gpos_info database_api::get_gpos_info(const account_id_type accou
return my->get_gpos_info(account);
}
graphene::app::gpos_info database_api_impl::get_gpos_info(const account_id_type account) const
{
FC_ASSERT( _db.head_block_time() > HARDFORK_GPOS_TIME); //Can be deleted after GPOS hardfork time
@ -2303,6 +2310,73 @@ graphene::app::gpos_info database_api_impl::get_gpos_info(const account_id_type
return result;
}
//////////////////////////////////////////////////////////////////////
// //
// NFT methods //
// //
//////////////////////////////////////////////////////////////////////
uint64_t database_api::nft_get_balance(const account_id_type owner) const
{
return my->nft_get_balance(owner);
}
uint64_t database_api_impl::nft_get_balance(const account_id_type owner) const
{
const auto &idx_nft = _db.get_index_type<nft_index>().indices().get<by_owner>();
const auto &idx_nft_range = idx_nft.equal_range(owner);
return std::distance(idx_nft_range.first, idx_nft_range.second);
}
optional<account_id_type> database_api::nft_owner_of(const nft_id_type token_id) const
{
return my->nft_owner_of(token_id);
}
optional<account_id_type> database_api_impl::nft_owner_of(const nft_id_type token_id) const
{
const auto &idx_nft = _db.get_index_type<nft_index>().indices().get<by_id>();
auto itr_nft = idx_nft.find(token_id);
if (itr_nft != idx_nft.end()) {
return itr_nft->owner;
}
return {};
}
optional<account_id_type> database_api::nft_get_approved(const nft_id_type token_id) const
{
return my->nft_get_approved(token_id);
}
optional<account_id_type> database_api_impl::nft_get_approved(const nft_id_type token_id) const
{
const auto &idx_nft = _db.get_index_type<nft_index>().indices().get<by_id>();
auto itr_nft = idx_nft.find(token_id);
if (itr_nft != idx_nft.end()) {
return itr_nft->approved;
}
return {};
}
bool database_api::nft_is_approved_for_all(const account_id_type owner, const account_id_type operator_) const
{
return my->nft_is_approved_for_all(owner, operator_);
}
bool database_api_impl::nft_is_approved_for_all(const account_id_type owner, const account_id_type operator_) const
{
const auto &idx_nft = _db.get_index_type<nft_index>().indices().get<by_owner>();
const auto &idx_nft_range = idx_nft.equal_range(owner);
if (std::distance(idx_nft_range.first, idx_nft_range.second) == 0) {
return false;
}
bool result = true;
std::for_each(idx_nft_range.first, idx_nft_range.second, [&](const nft_object &obj) {
result = result && (obj.approved == operator_);
});
return result;
}
//////////////////////////////////////////////////////////////////////
// //
// Private methods //

View file

@ -48,6 +48,8 @@
#include <graphene/chain/witness_object.hpp>
#include <graphene/chain/tournament_object.hpp>
#include <graphene/chain/nft_object.hpp>
#include <graphene/market_history/market_history_plugin.hpp>
#include <fc/api.hpp>
@ -709,6 +711,37 @@ class database_api
*/
gpos_info get_gpos_info(const account_id_type account) const;
/////////
// NFT //
/////////
/**
* @brief Returns the number of NFT owned by account
* @param owner Owner account ID
* @return Number of NFTs owned by account
*/
uint64_t nft_get_balance(const account_id_type owner) const;
/**
* @brief Returns the NFT owner
* @param token_id NFT ID
* @return NFT owner account ID
*/
optional<account_id_type> nft_owner_of(const nft_id_type token_id) const;
/**
* @brief Returns the NFT approved account ID
* @param token_id NFT ID
* @return NFT approved account ID
*/
optional<account_id_type> nft_get_approved(const nft_id_type token_id) const;
/**
* @brief Returns operator approved state for all NFT owned by owner
* @param owner NFT owner account ID
* @param token_id NFT ID
* @return True if operator is approved for all NFT owned by owner, else False
*/
bool nft_is_approved_for_all(const account_id_type owner, const account_id_type operator_) const;
private:
@ -848,4 +881,11 @@ FC_API(graphene::app::database_api,
// gpos
(get_gpos_info)
// NFT
(nft_get_balance)
(nft_owner_of)
(nft_get_approved)
(nft_is_approved_for_all)
)

View file

@ -13,6 +13,7 @@ namespace graphene { namespace chain {
static const uint8_t type_id = nft_object_type;
account_id_type owner;
account_id_type approved;
vector<account_id_type> approved_operators;
std::string metadata;
};
@ -42,6 +43,7 @@ namespace graphene { namespace chain {
FC_REFLECT_DERIVED( graphene::chain::nft_object, (graphene::db::object),
(owner)
(approved)
(approved_operators)
(metadata) )

View file

@ -10,6 +10,7 @@ namespace graphene { namespace chain {
asset fee;
account_id_type owner;
account_id_type approved;
vector<account_id_type> approved_operators;
std::string metadata;
@ -21,12 +22,14 @@ namespace graphene { namespace chain {
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
asset fee;
account_id_type operator_;
account_id_type from;
account_id_type to;
nft_id_type token_id;
string data;
account_id_type fee_payer()const { return from; }
account_id_type fee_payer()const { return operator_; }
};
struct nft_approve_operation : public base_operation
@ -62,8 +65,8 @@ FC_REFLECT( graphene::chain::nft_safe_transfer_from_operation::fee_parameters_ty
FC_REFLECT( graphene::chain::nft_approve_operation::fee_parameters_type, (fee) )
FC_REFLECT( graphene::chain::nft_set_approval_for_all_operation::fee_parameters_type, (fee) )
FC_REFLECT( graphene::chain::nft_create_operation, (fee) (owner) (approved_operators) (metadata) )
FC_REFLECT( graphene::chain::nft_safe_transfer_from_operation, (fee) (from) (to) (token_id) (data) )
FC_REFLECT( graphene::chain::nft_create_operation, (fee) (owner) (approved) (approved_operators) (metadata) )
FC_REFLECT( graphene::chain::nft_safe_transfer_from_operation, (fee) (operator_) (from) (to) (token_id) (data) )
FC_REFLECT( graphene::chain::nft_approve_operation, (fee) (owner) (approved) (token_id) )
FC_REFLECT( graphene::chain::nft_set_approval_for_all_operation, (fee) (owner) (operator_) (approved) )

View file

@ -13,6 +13,7 @@ object_id_type nft_create_evaluator::do_apply( const nft_create_operation& op )
{ try {
const auto& new_nft_object = db().create<nft_object>( [&]( nft_object& obj ){
obj.owner = op.owner;
obj.approved = op.approved;
obj.approved_operators = op.approved_operators;
obj.metadata = op.metadata;
});
@ -28,17 +29,21 @@ void_result nft_safe_transfer_from_evaluator::do_evaluate( const nft_safe_transf
auto itr_nft = idx_nft.find(op.token_id);
FC_ASSERT( itr_nft != idx_nft.end(), "NFT does not exists" );
auto itr_operator = idx_acc.find(op.operator_);
FC_ASSERT( itr_operator != idx_acc.end(), "Operator account does not exists" );
auto itr_owner = idx_acc.find(itr_nft->owner);
FC_ASSERT( itr_owner != idx_acc.end(), "Owner account does not exists" );
auto itr_from = idx_acc.find(op.from);
FC_ASSERT( itr_from != idx_acc.end(), "Sender account does not exists" );
FC_ASSERT( itr_from->id == itr_owner->id, "Sender account is not owner of this NFT" );
auto itr_to = idx_acc.find(op.to);
FC_ASSERT( itr_to != idx_acc.end(), "Receiver account does not exists" );
auto itr_approved_op = std::find(itr_nft->approved_operators.begin(), itr_nft->approved_operators.end(), op.from);
FC_ASSERT( (itr_nft->owner == itr_from->id) || (itr_approved_op != itr_nft->approved_operators.end()), "Sender is not NFT owner or approved operator" );
auto itr_approved_op = std::find(itr_nft->approved_operators.begin(), itr_nft->approved_operators.end(), op.operator_);
FC_ASSERT( (itr_nft->owner == itr_owner->id) || (itr_nft->approved == itr_operator->id) || (itr_approved_op != itr_nft->approved_operators.end()), "Operator is not NFT owner or approved operator" );
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
@ -51,6 +56,7 @@ object_id_type nft_safe_transfer_from_evaluator::do_apply( const nft_safe_transf
{
db().modify(*itr, [&op](nft_object &obj) {
obj.owner = op.to;
obj.approved = {};
obj.approved_operators.clear();
});
}
@ -85,10 +91,11 @@ object_id_type nft_approve_evaluator::do_apply( const nft_approve_operation& op
if (itr != idx.end())
{
db().modify(*itr, [&op](nft_object &obj) {
auto itr = std::find(obj.approved_operators.begin(), obj.approved_operators.end(), op.approved);
if (itr == obj.approved_operators.end()) {
obj.approved_operators.push_back(op.approved);
}
obj.approved = op.approved;
//auto itr = std::find(obj.approved_operators.begin(), obj.approved_operators.end(), op.approved);
//if (itr == obj.approved_operators.end()) {
// obj.approved_operators.push_back(op.approved);
//}
});
}
return op.token_id;

View file

@ -30,6 +30,7 @@ BOOST_AUTO_TEST_CASE( nft_create_test ) {
nft_create_operation op;
op.owner = alice_id;
op.approved = alice_id;
op.approved_operators.push_back(operator1_id);
op.approved_operators.push_back(operator2_id);
op.metadata = "metadata";
@ -130,10 +131,10 @@ BOOST_AUTO_TEST_CASE( nft_approve_operation_test ) {
BOOST_REQUIRE( idx.size() == 1 );
auto obj = idx.begin();
BOOST_REQUIRE( obj != idx.end() );
BOOST_CHECK( obj->approved_operators.size() == 3 );
BOOST_CHECK( obj->approved == operator3_id );
BOOST_CHECK( obj->approved_operators.size() == 2 );
BOOST_CHECK( obj->approved_operators.at(0) == operator1_id );
BOOST_CHECK( obj->approved_operators.at(1) == operator2_id );
BOOST_CHECK( obj->approved_operators.at(2) == operator3_id );
}
}