NFT evaluators and basic tests, no evaluator checks
This commit is contained in:
parent
de9ede0d5c
commit
31ed9b4ddb
6 changed files with 346 additions and 35 deletions
|
|
@ -294,16 +294,19 @@ struct get_impacted_account_visitor
|
|||
_impacted.insert( op.account );
|
||||
}
|
||||
void operator()( const nft_create_operation& op ) {
|
||||
_impacted.insert( op.payer );
|
||||
_impacted.insert( op.owner );
|
||||
}
|
||||
void operator()( const nft_safe_transfer_from_operation& op ) {
|
||||
_impacted.insert( op.payer );
|
||||
_impacted.insert( op.from );
|
||||
_impacted.insert( op.to );
|
||||
}
|
||||
void operator()( const nft_approve_operation& op ) {
|
||||
_impacted.insert( op.payer );
|
||||
_impacted.insert( op.owner );
|
||||
_impacted.insert( op.approved );
|
||||
}
|
||||
void operator()( const nft_set_approval_for_all_operation& op ) {
|
||||
_impacted.insert( op.payer );
|
||||
_impacted.insert( op.owner );
|
||||
_impacted.insert( op.operator_ );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace graphene { namespace chain {
|
|||
public:
|
||||
typedef nft_create_operation operation_type;
|
||||
void_result do_evaluate( const nft_create_operation& o );
|
||||
void_result do_apply( const nft_create_operation& o );
|
||||
object_id_type do_apply( const nft_create_operation& o );
|
||||
};
|
||||
|
||||
class nft_safe_transfer_from_evaluator : public evaluator<nft_safe_transfer_from_evaluator>
|
||||
|
|
@ -20,7 +20,7 @@ namespace graphene { namespace chain {
|
|||
public:
|
||||
typedef nft_safe_transfer_from_operation operation_type;
|
||||
void_result do_evaluate( const nft_safe_transfer_from_operation& o );
|
||||
void_result do_apply( const nft_safe_transfer_from_operation& o );
|
||||
object_id_type do_apply( const nft_safe_transfer_from_operation& o );
|
||||
};
|
||||
|
||||
class nft_approve_evaluator : public evaluator<nft_approve_evaluator>
|
||||
|
|
@ -28,7 +28,7 @@ namespace graphene { namespace chain {
|
|||
public:
|
||||
typedef nft_approve_operation operation_type;
|
||||
void_result do_evaluate( const nft_approve_operation& o );
|
||||
void_result do_apply( const nft_approve_operation& o );
|
||||
object_id_type do_apply( const nft_approve_operation& o );
|
||||
};
|
||||
|
||||
class nft_set_approval_for_all_evaluator : public evaluator<nft_set_approval_for_all_evaluator>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace graphene { namespace chain {
|
|||
|
||||
account_id_type owner;
|
||||
vector<account_id_type> approved_operators;
|
||||
std::string metadata;
|
||||
std::string metadata;
|
||||
};
|
||||
|
||||
struct by_owner;
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@ namespace graphene { namespace chain {
|
|||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
asset fee;
|
||||
|
||||
account_id_type payer;
|
||||
nft_id_type nft_id;
|
||||
account_id_type owner;
|
||||
vector<account_id_type> approved_operators;
|
||||
std::string metadata;
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
account_id_type fee_payer()const { return owner; }
|
||||
};
|
||||
|
||||
struct nft_safe_transfer_from_operation : public base_operation
|
||||
|
|
@ -20,10 +21,12 @@ namespace graphene { namespace chain {
|
|||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
asset fee;
|
||||
|
||||
account_id_type payer;
|
||||
nft_id_type nft_id;
|
||||
account_id_type from;
|
||||
account_id_type to;
|
||||
nft_id_type token_id;
|
||||
string data;
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
account_id_type fee_payer()const { return from; }
|
||||
};
|
||||
|
||||
struct nft_approve_operation : public base_operation
|
||||
|
|
@ -31,10 +34,12 @@ namespace graphene { namespace chain {
|
|||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
asset fee;
|
||||
|
||||
account_id_type payer;
|
||||
nft_id_type nft_id;
|
||||
account_id_type owner;
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
account_id_type approved;
|
||||
nft_id_type token_id;
|
||||
|
||||
account_id_type fee_payer()const { return owner; }
|
||||
};
|
||||
|
||||
struct nft_set_approval_for_all_operation : public base_operation
|
||||
|
|
@ -42,10 +47,12 @@ namespace graphene { namespace chain {
|
|||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
asset fee;
|
||||
|
||||
account_id_type payer;
|
||||
nft_id_type nft_id;
|
||||
account_id_type owner;
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
account_id_type operator_;
|
||||
bool approved;
|
||||
|
||||
account_id_type fee_payer()const { return owner; }
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -55,8 +62,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) (payer) (nft_id) )
|
||||
FC_REFLECT( graphene::chain::nft_safe_transfer_from_operation, (fee) (payer) (nft_id) )
|
||||
FC_REFLECT( graphene::chain::nft_approve_operation, (fee) (payer) (nft_id) )
|
||||
FC_REFLECT( graphene::chain::nft_set_approval_for_all_operation, (fee) (payer) (nft_id) )
|
||||
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_approve_operation, (fee) (owner) (approved) (token_id) )
|
||||
FC_REFLECT( graphene::chain::nft_set_approval_for_all_operation, (fee) (owner) (operator_) (approved) )
|
||||
|
||||
|
|
|
|||
|
|
@ -9,23 +9,35 @@ void_result nft_create_evaluator::do_evaluate( const nft_create_operation& op )
|
|||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
void_result nft_create_evaluator::do_apply( const nft_create_operation& op )
|
||||
object_id_type nft_create_evaluator::do_apply( const nft_create_operation& op )
|
||||
{ try {
|
||||
|
||||
return void_result();
|
||||
const auto& new_nft_object = db().create<nft_object>( [&]( nft_object& obj ){
|
||||
obj.owner = op.owner;
|
||||
obj.approved_operators = op.approved_operators;
|
||||
obj.metadata = op.metadata;
|
||||
});
|
||||
return new_nft_object.id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
||||
void_result nft_safe_transfer_from_evaluator::do_evaluate( const nft_safe_transfer_from_operation& op )
|
||||
{ try {
|
||||
|
||||
return void_result();
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
void_result nft_safe_transfer_from_evaluator::do_apply( const nft_safe_transfer_from_operation& op )
|
||||
object_id_type nft_safe_transfer_from_evaluator::do_apply( const nft_safe_transfer_from_operation& op )
|
||||
{ try {
|
||||
|
||||
return void_result();
|
||||
const auto& idx = db().get_index_type<nft_index>().indices().get<by_id>();
|
||||
auto itr = idx.find(op.token_id);
|
||||
if (itr != idx.end())
|
||||
{
|
||||
db().modify(*itr, [&op](nft_object &obj) {
|
||||
obj.owner = op.to;
|
||||
obj.approved_operators.clear();
|
||||
});
|
||||
}
|
||||
return op.token_id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
||||
|
|
@ -35,10 +47,17 @@ void_result nft_approve_evaluator::do_evaluate( const nft_approve_operation& op
|
|||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
void_result nft_approve_evaluator::do_apply( const nft_approve_operation& op )
|
||||
object_id_type nft_approve_evaluator::do_apply( const nft_approve_operation& op )
|
||||
{ try {
|
||||
|
||||
return void_result();
|
||||
const auto& idx = db().get_index_type<nft_index>().indices().get<by_id>();
|
||||
auto itr = idx.find(op.token_id);
|
||||
if (itr != idx.end())
|
||||
{
|
||||
db().modify(*itr, [&op](nft_object &obj) {
|
||||
obj.approved_operators.push_back(op.approved);
|
||||
});
|
||||
}
|
||||
return op.token_id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
||||
|
|
@ -50,7 +69,17 @@ void_result nft_set_approval_for_all_evaluator::do_evaluate( const nft_set_appro
|
|||
|
||||
void_result nft_set_approval_for_all_evaluator::do_apply( const nft_set_approval_for_all_operation& op )
|
||||
{ try {
|
||||
|
||||
const auto &idx = db().get_index_type<nft_index>().indices().get<by_owner>();
|
||||
const auto &idx_range = idx.equal_range(op.owner);
|
||||
std::for_each(idx_range.first, idx_range.second, [&](const nft_object &obj) {
|
||||
db().modify(obj, [&op](nft_object &obj) {
|
||||
if (op.approved) {
|
||||
obj.approved_operators.push_back(op.operator_);
|
||||
} else {
|
||||
//
|
||||
}
|
||||
});
|
||||
});
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
|
|
|||
272
tests/tests/nft_tests.cpp
Normal file
272
tests/tests/nft_tests.cpp
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "../common/database_fixture.hpp"
|
||||
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
#include <graphene/chain/nft_object.hpp>
|
||||
|
||||
using namespace graphene::chain;
|
||||
using namespace graphene::chain::test;
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE( nft_tests, database_fixture )
|
||||
|
||||
BOOST_AUTO_TEST_CASE( nft_create_test ) {
|
||||
|
||||
BOOST_TEST_MESSAGE("nft_create_test");
|
||||
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
ACTORS((alice));
|
||||
ACTORS((bob));
|
||||
ACTORS((operator1));
|
||||
ACTORS((operator2));
|
||||
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send nft_create_operation");
|
||||
|
||||
nft_create_operation op;
|
||||
op.owner = alice_id;
|
||||
op.approved_operators.push_back(operator1_id);
|
||||
op.approved_operators.push_back(operator2_id);
|
||||
op.metadata = "metadata";
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
BOOST_TEST_MESSAGE("Check nft_create_operation results");
|
||||
|
||||
const auto& idx = db.get_index_type<nft_index>().indices().get<by_id>();
|
||||
BOOST_REQUIRE( idx.size() == 1 );
|
||||
auto obj = idx.begin();
|
||||
BOOST_REQUIRE( obj != idx.end() );
|
||||
BOOST_CHECK( obj->owner == alice_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->metadata == "metadata" );
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( nft_safe_transfer_from_test ) {
|
||||
|
||||
BOOST_TEST_MESSAGE("nft_safe_transfer_from_test");
|
||||
|
||||
INVOKE(nft_create_test);
|
||||
|
||||
GET_ACTOR(alice);
|
||||
GET_ACTOR(bob);
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Check nft_safe_transfer_operation preconditions");
|
||||
|
||||
const auto& idx = db.get_index_type<nft_index>().indices().get<by_id>();
|
||||
BOOST_REQUIRE( idx.size() == 1 );
|
||||
auto obj = idx.begin();
|
||||
BOOST_REQUIRE( obj->owner == alice_id );
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send nft_safe_transfer_operation");
|
||||
|
||||
nft_safe_transfer_from_operation op;
|
||||
op.from = alice_id;
|
||||
op.to = bob_id;
|
||||
op.token_id = nft_id_type(0);
|
||||
op.data = "data";
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Check nft_safe_transfer_operation results");
|
||||
|
||||
const auto& idx = db.get_index_type<nft_index>().indices().get<by_id>();
|
||||
BOOST_REQUIRE( idx.size() == 1 );
|
||||
auto obj = idx.begin();
|
||||
BOOST_REQUIRE( obj->owner == bob_id );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( nft_approve_operation_test ) {
|
||||
|
||||
BOOST_TEST_MESSAGE("nft_approve_operation_test");
|
||||
|
||||
INVOKE(nft_create_test);
|
||||
|
||||
GET_ACTOR(alice);
|
||||
GET_ACTOR(operator1);
|
||||
GET_ACTOR(operator2);
|
||||
|
||||
ACTORS((operator3));
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send nft_approve_operation");
|
||||
|
||||
nft_approve_operation op;
|
||||
op.owner = alice_id;
|
||||
op.approved = operator3_id;
|
||||
op.token_id = nft_id_type(0);
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Check nft_approve_operation results");
|
||||
|
||||
const auto& idx = db.get_index_type<nft_index>().indices().get<by_id>();
|
||||
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_operators.at(0) == operator1_id );
|
||||
BOOST_CHECK( obj->approved_operators.at(1) == operator2_id );
|
||||
BOOST_CHECK( obj->approved_operators.at(2) == operator3_id );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( nft_set_approval_for_all_test ) {
|
||||
|
||||
BOOST_TEST_MESSAGE("nft_set_approval_for_all_test");
|
||||
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
ACTORS((alice));
|
||||
ACTORS((bob));
|
||||
|
||||
generate_block();
|
||||
set_expiration(db, trx);
|
||||
|
||||
BOOST_TEST_MESSAGE("Create NFT assets");
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send nft_create_operation 1");
|
||||
|
||||
nft_create_operation op;
|
||||
op.owner = alice_id;
|
||||
op.metadata = "metadata 1";
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send nft_create_operation 2");
|
||||
|
||||
nft_create_operation op;
|
||||
op.owner = bob_id;
|
||||
op.metadata = "metadata 2";
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, bob_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send nft_create_operation 3");
|
||||
|
||||
nft_create_operation op;
|
||||
op.owner = alice_id;
|
||||
op.metadata = "metadata 3";
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send nft_create_operation 4");
|
||||
|
||||
nft_create_operation op;
|
||||
op.owner = bob_id;
|
||||
op.metadata = "metadata 4";
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, bob_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send nft_create_operation 5");
|
||||
|
||||
nft_create_operation op;
|
||||
op.owner = alice_id;
|
||||
op.metadata = "metadata 5";
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Send nft_approve_operation");
|
||||
|
||||
nft_set_approval_for_all_operation op;
|
||||
op.owner = alice_id;
|
||||
op.operator_ = bob_id;
|
||||
op.approved = true;
|
||||
|
||||
trx.operations.push_back(op);
|
||||
sign(trx, alice_private_key);
|
||||
PUSH_TX(db, trx, ~0);
|
||||
}
|
||||
generate_block();
|
||||
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Check nft_approve_operation results");
|
||||
|
||||
const auto& idx = db.get_index_type<nft_index>().indices().get<by_owner>();
|
||||
const auto &idx_range = idx.equal_range(alice_id);
|
||||
std::for_each(idx_range.first, idx_range.second, [&](const nft_object &obj) {
|
||||
BOOST_CHECK( obj.approved_operators.size() == 1 );
|
||||
BOOST_CHECK( obj.approved_operators.at(0) == bob_id );
|
||||
});
|
||||
}
|
||||
|
||||
//{
|
||||
// BOOST_TEST_MESSAGE("Send nft_approve_operation");
|
||||
//
|
||||
// nft_set_approval_for_all_operation op;
|
||||
// op.owner = alice_id;
|
||||
// op.operator_ = bob_id;
|
||||
// op.approved = false;
|
||||
//
|
||||
// trx.operations.push_back(op);
|
||||
// sign(trx, alice_private_key);
|
||||
// PUSH_TX(db, trx, ~0);
|
||||
//}
|
||||
//generate_block();
|
||||
//
|
||||
//{
|
||||
// BOOST_TEST_MESSAGE("Check nft_approve_operation results");
|
||||
//
|
||||
// const auto& idx = db.get_index_type<nft_index>().indices().get<by_owner>();
|
||||
// const auto &idx_range = idx.equal_range(alice_id);
|
||||
// std::for_each(idx_range.first, idx_range.second, [&](const nft_object &obj) {
|
||||
// BOOST_CHECK( obj.approved_operators.size() == 1 );
|
||||
// });
|
||||
//}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
Loading…
Reference in a new issue