Database API
This commit is contained in:
parent
775eac55a9
commit
d0c72f7cf7
6 changed files with 138 additions and 11 deletions
|
|
@ -184,6 +184,12 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
|
||||||
// gpos
|
// gpos
|
||||||
gpos_info get_gpos_info(const account_id_type account) const;
|
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:
|
//private:
|
||||||
const account_object* get_account_from_string( const std::string& name_or_id,
|
const account_object* get_account_from_string( const std::string& name_or_id,
|
||||||
bool throw_if_not_found = true ) const;
|
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);
|
return my->get_gpos_info(account);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
graphene::app::gpos_info database_api_impl::get_gpos_info(const account_id_type account) const
|
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
|
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;
|
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 //
|
// Private methods //
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@
|
||||||
#include <graphene/chain/witness_object.hpp>
|
#include <graphene/chain/witness_object.hpp>
|
||||||
#include <graphene/chain/tournament_object.hpp>
|
#include <graphene/chain/tournament_object.hpp>
|
||||||
|
|
||||||
|
#include <graphene/chain/nft_object.hpp>
|
||||||
|
|
||||||
#include <graphene/market_history/market_history_plugin.hpp>
|
#include <graphene/market_history/market_history_plugin.hpp>
|
||||||
|
|
||||||
#include <fc/api.hpp>
|
#include <fc/api.hpp>
|
||||||
|
|
@ -709,6 +711,37 @@ class database_api
|
||||||
*/
|
*/
|
||||||
gpos_info get_gpos_info(const account_id_type account) const;
|
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:
|
private:
|
||||||
|
|
@ -848,4 +881,11 @@ FC_API(graphene::app::database_api,
|
||||||
|
|
||||||
// gpos
|
// gpos
|
||||||
(get_gpos_info)
|
(get_gpos_info)
|
||||||
|
|
||||||
|
// NFT
|
||||||
|
(nft_get_balance)
|
||||||
|
(nft_owner_of)
|
||||||
|
(nft_get_approved)
|
||||||
|
(nft_is_approved_for_all)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ namespace graphene { namespace chain {
|
||||||
static const uint8_t type_id = nft_object_type;
|
static const uint8_t type_id = nft_object_type;
|
||||||
|
|
||||||
account_id_type owner;
|
account_id_type owner;
|
||||||
|
account_id_type approved;
|
||||||
vector<account_id_type> approved_operators;
|
vector<account_id_type> approved_operators;
|
||||||
std::string metadata;
|
std::string metadata;
|
||||||
};
|
};
|
||||||
|
|
@ -42,6 +43,7 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
FC_REFLECT_DERIVED( graphene::chain::nft_object, (graphene::db::object),
|
FC_REFLECT_DERIVED( graphene::chain::nft_object, (graphene::db::object),
|
||||||
(owner)
|
(owner)
|
||||||
|
(approved)
|
||||||
(approved_operators)
|
(approved_operators)
|
||||||
(metadata) )
|
(metadata) )
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ namespace graphene { namespace chain {
|
||||||
asset fee;
|
asset fee;
|
||||||
|
|
||||||
account_id_type owner;
|
account_id_type owner;
|
||||||
|
account_id_type approved;
|
||||||
vector<account_id_type> approved_operators;
|
vector<account_id_type> approved_operators;
|
||||||
std::string metadata;
|
std::string metadata;
|
||||||
|
|
||||||
|
|
@ -21,12 +22,14 @@ namespace graphene { namespace chain {
|
||||||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||||
asset fee;
|
asset fee;
|
||||||
|
|
||||||
|
account_id_type operator_;
|
||||||
|
|
||||||
account_id_type from;
|
account_id_type from;
|
||||||
account_id_type to;
|
account_id_type to;
|
||||||
nft_id_type token_id;
|
nft_id_type token_id;
|
||||||
string data;
|
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
|
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_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_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_create_operation, (fee) (owner) (approved) (approved_operators) (metadata) )
|
||||||
FC_REFLECT( graphene::chain::nft_safe_transfer_from_operation, (fee) (from) (to) (token_id) (data) )
|
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_approve_operation, (fee) (owner) (approved) (token_id) )
|
||||||
FC_REFLECT( graphene::chain::nft_set_approval_for_all_operation, (fee) (owner) (operator_) (approved) )
|
FC_REFLECT( graphene::chain::nft_set_approval_for_all_operation, (fee) (owner) (operator_) (approved) )
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ object_id_type nft_create_evaluator::do_apply( const nft_create_operation& op )
|
||||||
{ try {
|
{ try {
|
||||||
const auto& new_nft_object = db().create<nft_object>( [&]( nft_object& obj ){
|
const auto& new_nft_object = db().create<nft_object>( [&]( nft_object& obj ){
|
||||||
obj.owner = op.owner;
|
obj.owner = op.owner;
|
||||||
|
obj.approved = op.approved;
|
||||||
obj.approved_operators = op.approved_operators;
|
obj.approved_operators = op.approved_operators;
|
||||||
obj.metadata = op.metadata;
|
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);
|
auto itr_nft = idx_nft.find(op.token_id);
|
||||||
FC_ASSERT( itr_nft != idx_nft.end(), "NFT does not exists" );
|
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);
|
auto itr_owner = idx_acc.find(itr_nft->owner);
|
||||||
FC_ASSERT( itr_owner != idx_acc.end(), "Owner account does not exists" );
|
FC_ASSERT( itr_owner != idx_acc.end(), "Owner account does not exists" );
|
||||||
|
|
||||||
auto itr_from = idx_acc.find(op.from);
|
auto itr_from = idx_acc.find(op.from);
|
||||||
FC_ASSERT( itr_from != idx_acc.end(), "Sender account does not exists" );
|
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);
|
auto itr_to = idx_acc.find(op.to);
|
||||||
FC_ASSERT( itr_to != idx_acc.end(), "Receiver account does not exists" );
|
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);
|
auto itr_approved_op = std::find(itr_nft->approved_operators.begin(), itr_nft->approved_operators.end(), op.operator_);
|
||||||
FC_ASSERT( (itr_nft->owner == itr_from->id) || (itr_approved_op != itr_nft->approved_operators.end()), "Sender is not NFT owner or approved 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();
|
return void_result();
|
||||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
} 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) {
|
db().modify(*itr, [&op](nft_object &obj) {
|
||||||
obj.owner = op.to;
|
obj.owner = op.to;
|
||||||
|
obj.approved = {};
|
||||||
obj.approved_operators.clear();
|
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())
|
if (itr != idx.end())
|
||||||
{
|
{
|
||||||
db().modify(*itr, [&op](nft_object &obj) {
|
db().modify(*itr, [&op](nft_object &obj) {
|
||||||
auto itr = std::find(obj.approved_operators.begin(), obj.approved_operators.end(), op.approved);
|
obj.approved = op.approved;
|
||||||
if (itr == obj.approved_operators.end()) {
|
//auto itr = std::find(obj.approved_operators.begin(), obj.approved_operators.end(), op.approved);
|
||||||
obj.approved_operators.push_back(op.approved);
|
//if (itr == obj.approved_operators.end()) {
|
||||||
}
|
// obj.approved_operators.push_back(op.approved);
|
||||||
|
//}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return op.token_id;
|
return op.token_id;
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ BOOST_AUTO_TEST_CASE( nft_create_test ) {
|
||||||
|
|
||||||
nft_create_operation op;
|
nft_create_operation op;
|
||||||
op.owner = alice_id;
|
op.owner = alice_id;
|
||||||
|
op.approved = alice_id;
|
||||||
op.approved_operators.push_back(operator1_id);
|
op.approved_operators.push_back(operator1_id);
|
||||||
op.approved_operators.push_back(operator2_id);
|
op.approved_operators.push_back(operator2_id);
|
||||||
op.metadata = "metadata";
|
op.metadata = "metadata";
|
||||||
|
|
@ -130,10 +131,10 @@ BOOST_AUTO_TEST_CASE( nft_approve_operation_test ) {
|
||||||
BOOST_REQUIRE( idx.size() == 1 );
|
BOOST_REQUIRE( idx.size() == 1 );
|
||||||
auto obj = idx.begin();
|
auto obj = idx.begin();
|
||||||
BOOST_REQUIRE( obj != idx.end() );
|
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(0) == operator1_id );
|
||||||
BOOST_CHECK( obj->approved_operators.at(1) == operator2_id );
|
BOOST_CHECK( obj->approved_operators.at(1) == operator2_id );
|
||||||
BOOST_CHECK( obj->approved_operators.at(2) == operator3_id );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue