Compare commits
11 commits
master
...
feature/nf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76ed35af2e | ||
|
|
3a8d8b9e98 | ||
|
|
e2c375e2a2 | ||
|
|
51cb17e2d8 | ||
|
|
0d79d5d0ee | ||
|
|
d0c72f7cf7 | ||
|
|
775eac55a9 | ||
|
|
21606396ee | ||
|
|
31ed9b4ddb | ||
|
|
9f03e9a6ff | ||
|
|
de9ede0d5c |
17 changed files with 1519 additions and 26 deletions
|
|
@ -31,25 +31,3 @@ test:
|
||||||
- ./tests/cli_test
|
- ./tests/cli_test
|
||||||
tags:
|
tags:
|
||||||
- builder
|
- builder
|
||||||
|
|
||||||
code_quality:
|
|
||||||
stage: test
|
|
||||||
image: docker:stable
|
|
||||||
variables:
|
|
||||||
DOCKER_DRIVER: overlay2
|
|
||||||
allow_failure: true
|
|
||||||
services:
|
|
||||||
- docker:stable-dind
|
|
||||||
script:
|
|
||||||
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
|
|
||||||
- docker run
|
|
||||||
--env SOURCE_CODE="$PWD"
|
|
||||||
--volume "$PWD":/code
|
|
||||||
--volume /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
|
|
||||||
artifacts:
|
|
||||||
paths: [gl-code-quality-report.json]
|
|
||||||
expire_in: 1 week
|
|
||||||
except:
|
|
||||||
variables:
|
|
||||||
- $CODE_QUALITY_DISABLED
|
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ else( WIN32 ) # Apple AND Linux
|
||||||
endif( APPLE )
|
endif( APPLE )
|
||||||
|
|
||||||
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" )
|
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" )
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-builtin-memcmp -Wno-class-memaccess -Wno-parentheses -Wno-terminate -Wno-invalid-offsetof" )
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-builtin-memcmp -Wno-parentheses -Wno-terminate -Wno-invalid-offsetof" )
|
||||||
elseif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
elseif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
if( CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.0.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0.0 )
|
if( CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.0.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0.0 )
|
||||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-partial-specialization" )
|
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-partial-specialization" )
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,20 @@ 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;
|
||||||
|
string nft_get_name(const nft_metadata_id_type nft_metadata_id) const;
|
||||||
|
string nft_get_symbol(const nft_metadata_id_type nft_metadata_id) const;
|
||||||
|
string nft_get_token_uri(const nft_id_type token_id) const;
|
||||||
|
uint64_t nft_get_total_supply(const nft_metadata_id_type nft_metadata_id) const;
|
||||||
|
nft_object nft_token_by_index(const nft_metadata_id_type nft_metadata_id, const uint64_t token_idx) const;
|
||||||
|
nft_object nft_token_of_owner_by_index(const nft_metadata_id_type nft_metadata_id, const account_id_type owner, const uint64_t token_idx) const;
|
||||||
|
vector<nft_object> nft_get_all_tokens() const;
|
||||||
|
vector<nft_object> nft_get_tokens_by_owner(const account_id_type owner) 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 +2254,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 +2318,202 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
string database_api::nft_get_name(const nft_metadata_id_type nft_metadata_id) const
|
||||||
|
{
|
||||||
|
return my->nft_get_name(nft_metadata_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
string database_api_impl::nft_get_name(const nft_metadata_id_type nft_metadata_id) const
|
||||||
|
{
|
||||||
|
const auto &idx_nft_md = _db.get_index_type<nft_metadata_index>().indices().get<by_id>();
|
||||||
|
auto itr_nft_md = idx_nft_md.find(nft_metadata_id);
|
||||||
|
if (itr_nft_md != idx_nft_md.end()) {
|
||||||
|
return itr_nft_md->name;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string database_api::nft_get_symbol(const nft_metadata_id_type nft_metadata_id) const
|
||||||
|
{
|
||||||
|
return my->nft_get_symbol(nft_metadata_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
string database_api_impl::nft_get_symbol(const nft_metadata_id_type nft_metadata_id) const
|
||||||
|
{
|
||||||
|
const auto &idx_nft_md = _db.get_index_type<nft_metadata_index>().indices().get<by_id>();
|
||||||
|
auto itr_nft_md = idx_nft_md.find(nft_metadata_id);
|
||||||
|
if (itr_nft_md != idx_nft_md.end()) {
|
||||||
|
return itr_nft_md->symbol;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string database_api::nft_get_token_uri(const nft_id_type token_id) const
|
||||||
|
{
|
||||||
|
return my->nft_get_token_uri(token_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
string database_api_impl::nft_get_token_uri(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()) {
|
||||||
|
const auto &idx_nft_md = _db.get_index_type<nft_metadata_index>().indices().get<by_id>();
|
||||||
|
auto itr_nft_md = idx_nft_md.find(itr_nft->nft_metadata_id);
|
||||||
|
if (itr_nft_md != idx_nft_md.end()) {
|
||||||
|
return itr_nft_md->base_uri + itr_nft->token_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t database_api::nft_get_total_supply(const nft_metadata_id_type nft_metadata_id) const
|
||||||
|
{
|
||||||
|
return my->nft_get_total_supply(nft_metadata_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t database_api_impl::nft_get_total_supply(const nft_metadata_id_type nft_metadata_id) const
|
||||||
|
{
|
||||||
|
const auto &idx_nft_md = _db.get_index_type<nft_metadata_index>().indices().get<by_id>();
|
||||||
|
return idx_nft_md.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
nft_object database_api::nft_token_by_index(const nft_metadata_id_type nft_metadata_id, const uint64_t token_idx) const
|
||||||
|
{
|
||||||
|
return my->nft_token_by_index(nft_metadata_id, token_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
nft_object database_api_impl::nft_token_by_index(const nft_metadata_id_type nft_metadata_id, const uint64_t token_idx) const
|
||||||
|
{
|
||||||
|
const auto &idx_nft = _db.get_index_type<nft_index>().indices().get<by_metadata>();
|
||||||
|
auto idx_nft_range = idx_nft.equal_range(nft_metadata_id);
|
||||||
|
uint64_t tmp_idx = token_idx;
|
||||||
|
for (auto itr = idx_nft_range.first; itr != idx_nft_range.second; ++itr) {
|
||||||
|
if (tmp_idx == 0) {
|
||||||
|
return *itr;
|
||||||
|
}
|
||||||
|
tmp_idx = tmp_idx - 1;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
nft_object database_api::nft_token_of_owner_by_index(const nft_metadata_id_type nft_metadata_id, const account_id_type owner, const uint64_t token_idx) const
|
||||||
|
{
|
||||||
|
return my->nft_token_of_owner_by_index(nft_metadata_id, owner, token_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
nft_object database_api_impl::nft_token_of_owner_by_index(const nft_metadata_id_type nft_metadata_id, const account_id_type owner, const uint64_t token_idx) const
|
||||||
|
{
|
||||||
|
const auto &idx_nft = _db.get_index_type<nft_index>().indices().get<by_metadata_and_owner>();
|
||||||
|
auto idx_nft_range = idx_nft.equal_range(std::make_tuple(nft_metadata_id, owner));
|
||||||
|
uint64_t tmp_idx = token_idx;
|
||||||
|
for (auto itr = idx_nft_range.first; itr != idx_nft_range.second; ++itr) {
|
||||||
|
if (tmp_idx == 0) {
|
||||||
|
return *itr;
|
||||||
|
}
|
||||||
|
tmp_idx = tmp_idx - 1;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<nft_object> database_api::nft_get_all_tokens() const
|
||||||
|
{
|
||||||
|
return my->nft_get_all_tokens();
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<nft_object> database_api_impl::nft_get_all_tokens() const
|
||||||
|
{
|
||||||
|
const auto &idx_nft = _db.get_index_type<nft_index>().indices().get<by_id>();
|
||||||
|
vector<nft_object> result;
|
||||||
|
for (auto itr = idx_nft.begin(); itr != idx_nft.end(); ++itr) {
|
||||||
|
result.push_back(*itr);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<nft_object> database_api::nft_get_tokens_by_owner(const account_id_type owner) const
|
||||||
|
{
|
||||||
|
return my->nft_get_tokens_by_owner(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<nft_object> database_api_impl::nft_get_tokens_by_owner(const account_id_type owner) const
|
||||||
|
{
|
||||||
|
const auto &idx_nft = _db.get_index_type<nft_index>().indices().get<by_owner>();
|
||||||
|
auto idx_nft_range = idx_nft.equal_range(owner);
|
||||||
|
vector<nft_object> result;
|
||||||
|
for (auto itr = idx_nft_range.first; itr != idx_nft_range.second; ++itr) {
|
||||||
|
result.push_back(*itr);
|
||||||
|
}
|
||||||
|
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,7 +711,95 @@ 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns NFT name from NFT metadata
|
||||||
|
* @param nft_metadata_id NFT metadata ID
|
||||||
|
* @return NFT name
|
||||||
|
*/
|
||||||
|
string nft_get_name(const nft_metadata_id_type nft_metadata_id) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns NFT symbol from NFT metadata
|
||||||
|
* @param nft_metadata_id NFT metadata ID
|
||||||
|
* @return NFT symbol
|
||||||
|
*/
|
||||||
|
string nft_get_symbol(const nft_metadata_id_type nft_metadata_id) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns NFT URI
|
||||||
|
* @param token_id NFT ID
|
||||||
|
* @return NFT URI
|
||||||
|
*/
|
||||||
|
string nft_get_token_uri(const nft_id_type token_id) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns total number of NFTs assigned to NFT metadata
|
||||||
|
* @param nft_metadata_id NFT metadata ID
|
||||||
|
* @return Total number of NFTs assigned to NFT metadata
|
||||||
|
*/
|
||||||
|
uint64_t nft_get_total_supply(const nft_metadata_id_type nft_metadata_id) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns NFT by index from NFT metadata
|
||||||
|
* @param nft_metadata_id NFT metadata ID
|
||||||
|
* @param token_idx NFT index in the list of tokens
|
||||||
|
* @return NFT symbol
|
||||||
|
*/
|
||||||
|
nft_object nft_token_by_index(const nft_metadata_id_type nft_metadata_id, const uint64_t token_idx) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns NFT by owner and index
|
||||||
|
* @param nft_metadata_id NFT metadata ID
|
||||||
|
* @param owner NFT owner
|
||||||
|
* @param token_idx NFT index in the list of tokens
|
||||||
|
* @return NFT object
|
||||||
|
*/
|
||||||
|
nft_object nft_token_of_owner_by_index(const nft_metadata_id_type nft_metadata_id, const account_id_type owner, const uint64_t token_idx) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns list of all available NTF's
|
||||||
|
* @return List of all available NFT's
|
||||||
|
*/
|
||||||
|
vector<nft_object> nft_get_all_tokens() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns NFT's owned by owner
|
||||||
|
* @param owner NFT owner
|
||||||
|
* @return List of NFT owned by owner
|
||||||
|
*/
|
||||||
|
vector<nft_object> nft_get_tokens_by_owner(const account_id_type owner) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr< database_api_impl > my;
|
std::shared_ptr< database_api_impl > my;
|
||||||
|
|
@ -848,4 +938,19 @@ 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)
|
||||||
|
(nft_get_name)
|
||||||
|
(nft_get_symbol)
|
||||||
|
(nft_get_token_uri)
|
||||||
|
(nft_get_total_supply)
|
||||||
|
(nft_token_by_index)
|
||||||
|
(nft_token_of_owner_by_index)
|
||||||
|
(nft_get_all_tokens)
|
||||||
|
(nft_get_tokens_by_owner)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,8 @@ add_library( graphene_chain
|
||||||
|
|
||||||
affiliate_payout.cpp
|
affiliate_payout.cpp
|
||||||
|
|
||||||
|
nft_evaluator.cpp
|
||||||
|
|
||||||
${HEADERS}
|
${HEADERS}
|
||||||
${PROTOCOL_HEADERS}
|
${PROTOCOL_HEADERS}
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/include/graphene/chain/hardfork.hpp"
|
"${CMAKE_CURRENT_BINARY_DIR}/include/graphene/chain/hardfork.hpp"
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
#include <graphene/chain/tournament_object.hpp>
|
#include <graphene/chain/tournament_object.hpp>
|
||||||
#include <graphene/chain/match_object.hpp>
|
#include <graphene/chain/match_object.hpp>
|
||||||
#include <graphene/chain/game_object.hpp>
|
#include <graphene/chain/game_object.hpp>
|
||||||
|
#include <graphene/chain/nft_object.hpp>
|
||||||
|
|
||||||
#include <graphene/chain/sport_object.hpp>
|
#include <graphene/chain/sport_object.hpp>
|
||||||
#include <graphene/chain/event_group_object.hpp>
|
#include <graphene/chain/event_group_object.hpp>
|
||||||
|
|
@ -77,6 +77,7 @@
|
||||||
#include <graphene/chain/event_evaluator.hpp>
|
#include <graphene/chain/event_evaluator.hpp>
|
||||||
#include <graphene/chain/betting_market_evaluator.hpp>
|
#include <graphene/chain/betting_market_evaluator.hpp>
|
||||||
#include <graphene/chain/tournament_evaluator.hpp>
|
#include <graphene/chain/tournament_evaluator.hpp>
|
||||||
|
#include <graphene/chain/nft_evaluator.hpp>
|
||||||
|
|
||||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||||
|
|
||||||
|
|
@ -163,6 +164,9 @@ const uint8_t betting_market_object::type_id;
|
||||||
const uint8_t bet_object::space_id;
|
const uint8_t bet_object::space_id;
|
||||||
const uint8_t bet_object::type_id;
|
const uint8_t bet_object::type_id;
|
||||||
|
|
||||||
|
const uint8_t nft_object::space_id;
|
||||||
|
const uint8_t nft_object::type_id;
|
||||||
|
|
||||||
const uint8_t betting_market_position_object::space_id;
|
const uint8_t betting_market_position_object::space_id;
|
||||||
const uint8_t betting_market_position_object::type_id;
|
const uint8_t betting_market_position_object::type_id;
|
||||||
|
|
||||||
|
|
@ -243,6 +247,12 @@ void database::initialize_evaluators()
|
||||||
register_evaluator<lottery_reward_evaluator>();
|
register_evaluator<lottery_reward_evaluator>();
|
||||||
register_evaluator<lottery_end_evaluator>();
|
register_evaluator<lottery_end_evaluator>();
|
||||||
register_evaluator<sweeps_vesting_claim_evaluator>();
|
register_evaluator<sweeps_vesting_claim_evaluator>();
|
||||||
|
register_evaluator<nft_metadata_create_evaluator>();
|
||||||
|
register_evaluator<nft_metadata_update_evaluator>();
|
||||||
|
register_evaluator<nft_mint_evaluator>();
|
||||||
|
register_evaluator<nft_safe_transfer_from_evaluator>();
|
||||||
|
register_evaluator<nft_approve_evaluator>();
|
||||||
|
register_evaluator<nft_set_approval_for_all_evaluator>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void database::initialize_indexes()
|
void database::initialize_indexes()
|
||||||
|
|
@ -285,6 +295,9 @@ void database::initialize_indexes()
|
||||||
add_index< primary_index<match_index> >();
|
add_index< primary_index<match_index> >();
|
||||||
add_index< primary_index<game_index> >();
|
add_index< primary_index<game_index> >();
|
||||||
|
|
||||||
|
add_index< primary_index<nft_metadata_index > >();
|
||||||
|
add_index< primary_index<nft_index > >();
|
||||||
|
|
||||||
//Implementation object indexes
|
//Implementation object indexes
|
||||||
add_index< primary_index<transaction_index > >();
|
add_index< primary_index<transaction_index > >();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -293,6 +293,27 @@ struct get_impacted_account_visitor
|
||||||
void operator()( const sweeps_vesting_claim_operation& op ) {
|
void operator()( const sweeps_vesting_claim_operation& op ) {
|
||||||
_impacted.insert( op.account );
|
_impacted.insert( op.account );
|
||||||
}
|
}
|
||||||
|
void operator()( const nft_metadata_create_operation& op ) {
|
||||||
|
_impacted.insert( op.owner );
|
||||||
|
}
|
||||||
|
void operator()( const nft_metadata_update_operation& op ) {
|
||||||
|
_impacted.insert( op.owner );
|
||||||
|
}
|
||||||
|
void operator()( const nft_mint_operation& op ) {
|
||||||
|
_impacted.insert( op.owner );
|
||||||
|
}
|
||||||
|
void operator()( const nft_safe_transfer_from_operation& op ) {
|
||||||
|
_impacted.insert( op.from );
|
||||||
|
_impacted.insert( op.to );
|
||||||
|
}
|
||||||
|
void operator()( const nft_approve_operation& op ) {
|
||||||
|
_impacted.insert( op.operator_ );
|
||||||
|
_impacted.insert( op.approved );
|
||||||
|
}
|
||||||
|
void operator()( const nft_set_approval_for_all_operation& op ) {
|
||||||
|
_impacted.insert( op.owner );
|
||||||
|
_impacted.insert( op.operator_ );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void graphene::chain::operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
|
void graphene::chain::operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
|
||||||
|
|
|
||||||
59
libraries/chain/include/graphene/chain/nft_evaluator.hpp
Normal file
59
libraries/chain/include/graphene/chain/nft_evaluator.hpp
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <graphene/chain/database.hpp>
|
||||||
|
#include <graphene/chain/evaluator.hpp>
|
||||||
|
#include <graphene/chain/protocol/operations.hpp>
|
||||||
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
class nft_metadata_create_evaluator : public evaluator<nft_metadata_create_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef nft_metadata_create_operation operation_type;
|
||||||
|
void_result do_evaluate( const nft_metadata_create_operation& o );
|
||||||
|
object_id_type do_apply( const nft_metadata_create_operation& o );
|
||||||
|
};
|
||||||
|
|
||||||
|
class nft_metadata_update_evaluator : public evaluator<nft_metadata_update_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef nft_metadata_update_operation operation_type;
|
||||||
|
void_result do_evaluate( const nft_metadata_update_operation& o );
|
||||||
|
void_result do_apply( const nft_metadata_update_operation& o );
|
||||||
|
};
|
||||||
|
|
||||||
|
class nft_mint_evaluator : public evaluator<nft_mint_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef nft_mint_operation operation_type;
|
||||||
|
void_result do_evaluate( const nft_mint_operation& o );
|
||||||
|
object_id_type do_apply( const nft_mint_operation& o );
|
||||||
|
};
|
||||||
|
|
||||||
|
class nft_safe_transfer_from_evaluator : public evaluator<nft_safe_transfer_from_evaluator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef nft_safe_transfer_from_operation operation_type;
|
||||||
|
void_result do_evaluate( 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>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef nft_approve_operation operation_type;
|
||||||
|
void_result do_evaluate( 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>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef nft_set_approval_for_all_operation operation_type;
|
||||||
|
void_result do_evaluate( const nft_set_approval_for_all_operation& o );
|
||||||
|
void_result do_apply( const nft_set_approval_for_all_operation& o );
|
||||||
|
};
|
||||||
|
|
||||||
|
} } // graphene::chain
|
||||||
|
|
||||||
98
libraries/chain/include/graphene/chain/nft_object.hpp
Normal file
98
libraries/chain/include/graphene/chain/nft_object.hpp
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
|
#include <graphene/db/object.hpp>
|
||||||
|
#include <graphene/db/generic_index.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
using namespace graphene::db;
|
||||||
|
|
||||||
|
class nft_metadata_object : public abstract_object<nft_metadata_object>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = protocol_ids;
|
||||||
|
static const uint8_t type_id = nft_metadata_type;
|
||||||
|
|
||||||
|
account_id_type owner;
|
||||||
|
std::string name;
|
||||||
|
std::string symbol;
|
||||||
|
std::string base_uri;
|
||||||
|
};
|
||||||
|
|
||||||
|
class nft_object : public abstract_object<nft_object>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = protocol_ids;
|
||||||
|
static const uint8_t type_id = nft_object_type;
|
||||||
|
|
||||||
|
nft_metadata_id_type nft_metadata_id;
|
||||||
|
account_id_type owner;
|
||||||
|
account_id_type approved;
|
||||||
|
vector<account_id_type> approved_operators;
|
||||||
|
std::string token_uri;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct by_name;
|
||||||
|
struct by_symbol;
|
||||||
|
using nft_metadata_multi_index_type = multi_index_container<
|
||||||
|
nft_metadata_object,
|
||||||
|
indexed_by<
|
||||||
|
ordered_unique< tag<by_id>,
|
||||||
|
member<object, object_id_type, &object::id>
|
||||||
|
>,
|
||||||
|
ordered_unique< tag<by_name>,
|
||||||
|
member<nft_metadata_object, std::string, &nft_metadata_object::name>
|
||||||
|
>,
|
||||||
|
ordered_unique< tag<by_symbol>,
|
||||||
|
member<nft_metadata_object, std::string, &nft_metadata_object::symbol>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
using nft_metadata_index = generic_index<nft_metadata_object, nft_metadata_multi_index_type>;
|
||||||
|
|
||||||
|
struct by_metadata;
|
||||||
|
struct by_metadata_and_owner;
|
||||||
|
struct by_owner;
|
||||||
|
struct by_owner_and_id;
|
||||||
|
using nft_multi_index_type = multi_index_container<
|
||||||
|
nft_object,
|
||||||
|
indexed_by<
|
||||||
|
ordered_unique< tag<by_id>,
|
||||||
|
member<object, object_id_type, &object::id>
|
||||||
|
>,
|
||||||
|
ordered_non_unique< tag<by_metadata>,
|
||||||
|
member<nft_object, nft_metadata_id_type, &nft_object::nft_metadata_id>
|
||||||
|
>,
|
||||||
|
ordered_non_unique< tag<by_metadata_and_owner>,
|
||||||
|
composite_key<nft_object,
|
||||||
|
member<nft_object, nft_metadata_id_type, &nft_object::nft_metadata_id>,
|
||||||
|
member<nft_object, account_id_type, &nft_object::owner>
|
||||||
|
>
|
||||||
|
>,
|
||||||
|
ordered_non_unique< tag<by_owner>,
|
||||||
|
member<nft_object, account_id_type, &nft_object::owner>
|
||||||
|
>,
|
||||||
|
ordered_unique< tag<by_owner_and_id>,
|
||||||
|
composite_key<nft_object,
|
||||||
|
member<nft_object, account_id_type, &nft_object::owner>,
|
||||||
|
member<object, object_id_type, &object::id>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
using nft_index = generic_index<nft_object, nft_multi_index_type>;
|
||||||
|
|
||||||
|
} } // graphene::chain
|
||||||
|
|
||||||
|
FC_REFLECT_DERIVED( graphene::chain::nft_metadata_object, (graphene::db::object),
|
||||||
|
(owner)
|
||||||
|
(name)
|
||||||
|
(symbol)
|
||||||
|
(base_uri) )
|
||||||
|
|
||||||
|
FC_REFLECT_DERIVED( graphene::chain::nft_object, (graphene::db::object),
|
||||||
|
(nft_metadata_id)
|
||||||
|
(owner)
|
||||||
|
(approved)
|
||||||
|
(approved_operators)
|
||||||
|
(token_uri) )
|
||||||
|
|
||||||
106
libraries/chain/include/graphene/chain/protocol/nft_ops.hpp
Normal file
106
libraries/chain/include/graphene/chain/protocol/nft_ops.hpp
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/protocol/base.hpp>
|
||||||
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
struct nft_metadata_create_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||||
|
asset fee;
|
||||||
|
|
||||||
|
account_id_type owner;
|
||||||
|
std::string name;
|
||||||
|
std::string symbol;
|
||||||
|
std::string base_uri;
|
||||||
|
|
||||||
|
account_id_type fee_payer()const { return owner; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nft_metadata_update_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||||
|
asset fee;
|
||||||
|
|
||||||
|
account_id_type owner;
|
||||||
|
nft_metadata_id_type nft_metadata_id;
|
||||||
|
optional<std::string> name;
|
||||||
|
optional<std::string> symbol;
|
||||||
|
optional<std::string> base_uri;
|
||||||
|
|
||||||
|
account_id_type fee_payer()const { return owner; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nft_mint_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||||
|
asset fee;
|
||||||
|
|
||||||
|
account_id_type payer;
|
||||||
|
|
||||||
|
optional<nft_metadata_id_type> nft_metadata_id;
|
||||||
|
account_id_type owner;
|
||||||
|
account_id_type approved;
|
||||||
|
vector<account_id_type> approved_operators;
|
||||||
|
std::string token_uri;
|
||||||
|
|
||||||
|
account_id_type fee_payer()const { return payer; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nft_safe_transfer_from_operation : public base_operation
|
||||||
|
{
|
||||||
|
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 operator_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nft_approve_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||||
|
asset fee;
|
||||||
|
|
||||||
|
account_id_type operator_;
|
||||||
|
|
||||||
|
account_id_type approved;
|
||||||
|
nft_id_type token_id;
|
||||||
|
|
||||||
|
account_id_type fee_payer()const { return operator_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nft_set_approval_for_all_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||||
|
asset fee;
|
||||||
|
|
||||||
|
account_id_type owner;
|
||||||
|
|
||||||
|
account_id_type operator_;
|
||||||
|
bool approved;
|
||||||
|
|
||||||
|
account_id_type fee_payer()const { return owner; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} } // graphene::chain
|
||||||
|
|
||||||
|
FC_REFLECT( graphene::chain::nft_metadata_create_operation::fee_parameters_type, (fee) )
|
||||||
|
FC_REFLECT( graphene::chain::nft_metadata_update_operation::fee_parameters_type, (fee) )
|
||||||
|
FC_REFLECT( graphene::chain::nft_mint_operation::fee_parameters_type, (fee) )
|
||||||
|
FC_REFLECT( graphene::chain::nft_safe_transfer_from_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_metadata_create_operation, (fee) (owner) (name) (symbol) (base_uri) )
|
||||||
|
FC_REFLECT( graphene::chain::nft_metadata_update_operation, (fee) (owner) (nft_metadata_id) (name) (symbol) (base_uri) )
|
||||||
|
FC_REFLECT( graphene::chain::nft_mint_operation, (fee) (nft_metadata_id) (owner) (approved) (approved_operators) (token_uri) )
|
||||||
|
FC_REFLECT( graphene::chain::nft_safe_transfer_from_operation, (fee) (operator_) (from) (to) (token_id) (data) )
|
||||||
|
FC_REFLECT( graphene::chain::nft_approve_operation, (fee) (operator_) (approved) (token_id) )
|
||||||
|
FC_REFLECT( graphene::chain::nft_set_approval_for_all_operation, (fee) (owner) (operator_) (approved) )
|
||||||
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
#include <graphene/chain/protocol/event.hpp>
|
#include <graphene/chain/protocol/event.hpp>
|
||||||
#include <graphene/chain/protocol/betting_market.hpp>
|
#include <graphene/chain/protocol/betting_market.hpp>
|
||||||
#include <graphene/chain/protocol/tournament.hpp>
|
#include <graphene/chain/protocol/tournament.hpp>
|
||||||
|
#include <graphene/chain/protocol/nft_ops.hpp>
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
|
@ -135,7 +136,13 @@ namespace graphene { namespace chain {
|
||||||
ticket_purchase_operation,
|
ticket_purchase_operation,
|
||||||
lottery_reward_operation,
|
lottery_reward_operation,
|
||||||
lottery_end_operation,
|
lottery_end_operation,
|
||||||
sweeps_vesting_claim_operation
|
sweeps_vesting_claim_operation,
|
||||||
|
nft_metadata_create_operation,
|
||||||
|
nft_metadata_update_operation,
|
||||||
|
nft_mint_operation,
|
||||||
|
nft_safe_transfer_from_operation,
|
||||||
|
nft_approve_operation,
|
||||||
|
nft_set_approval_for_all_operation
|
||||||
> operation;
|
> operation;
|
||||||
|
|
||||||
/// @} // operations group
|
/// @} // operations group
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,8 @@ namespace graphene { namespace chain {
|
||||||
betting_market_group_object_type,
|
betting_market_group_object_type,
|
||||||
betting_market_object_type,
|
betting_market_object_type,
|
||||||
bet_object_type,
|
bet_object_type,
|
||||||
|
nft_metadata_type,
|
||||||
|
nft_object_type,
|
||||||
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -230,6 +232,8 @@ namespace graphene { namespace chain {
|
||||||
class betting_market_group_object;
|
class betting_market_group_object;
|
||||||
class betting_market_object;
|
class betting_market_object;
|
||||||
class bet_object;
|
class bet_object;
|
||||||
|
class nft_metadata_object;
|
||||||
|
class nft_object;
|
||||||
|
|
||||||
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
|
||||||
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
|
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
|
||||||
|
|
@ -256,6 +260,8 @@ namespace graphene { namespace chain {
|
||||||
typedef object_id< protocol_ids, betting_market_group_object_type, betting_market_group_object> betting_market_group_id_type;
|
typedef object_id< protocol_ids, betting_market_group_object_type, betting_market_group_object> betting_market_group_id_type;
|
||||||
typedef object_id< protocol_ids, betting_market_object_type, betting_market_object> betting_market_id_type;
|
typedef object_id< protocol_ids, betting_market_object_type, betting_market_object> betting_market_id_type;
|
||||||
typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type;
|
typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type;
|
||||||
|
typedef object_id< protocol_ids, nft_metadata_type, nft_metadata_object> nft_metadata_id_type;
|
||||||
|
typedef object_id< protocol_ids, nft_object_type, nft_object> nft_id_type;
|
||||||
|
|
||||||
// implementation types
|
// implementation types
|
||||||
class global_property_object;
|
class global_property_object;
|
||||||
|
|
@ -436,6 +442,8 @@ FC_REFLECT_ENUM( graphene::chain::object_type,
|
||||||
(betting_market_group_object_type)
|
(betting_market_group_object_type)
|
||||||
(betting_market_object_type)
|
(betting_market_object_type)
|
||||||
(bet_object_type)
|
(bet_object_type)
|
||||||
|
(nft_metadata_type)
|
||||||
|
(nft_object_type)
|
||||||
(OBJECT_TYPE_COUNT)
|
(OBJECT_TYPE_COUNT)
|
||||||
)
|
)
|
||||||
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
||||||
|
|
@ -505,6 +513,8 @@ FC_REFLECT_TYPENAME( graphene::chain::fba_accumulator_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::betting_market_position_id_type )
|
FC_REFLECT_TYPENAME( graphene::chain::betting_market_position_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::global_betting_statistics_id_type )
|
FC_REFLECT_TYPENAME( graphene::chain::global_betting_statistics_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::tournament_details_id_type )
|
FC_REFLECT_TYPENAME( graphene::chain::tournament_details_id_type )
|
||||||
|
FC_REFLECT_TYPENAME( graphene::chain::nft_metadata_id_type )
|
||||||
|
FC_REFLECT_TYPENAME( graphene::chain::nft_id_type )
|
||||||
|
|
||||||
FC_REFLECT( graphene::chain::void_t, )
|
FC_REFLECT( graphene::chain::void_t, )
|
||||||
|
|
||||||
|
|
|
||||||
183
libraries/chain/nft_evaluator.cpp
Normal file
183
libraries/chain/nft_evaluator.cpp
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
#include <graphene/chain/nft_evaluator.hpp>
|
||||||
|
#include <graphene/chain/nft_object.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
void_result nft_metadata_create_evaluator::do_evaluate( const nft_metadata_create_operation& op )
|
||||||
|
{ try {
|
||||||
|
const auto& idx_nft_md_by_name = db().get_index_type<nft_metadata_index>().indices().get<by_name>();
|
||||||
|
FC_ASSERT( idx_nft_md_by_name.find(op.name) == idx_nft_md_by_name.end(), "NFT name already in use" );
|
||||||
|
const auto& idx_nft_md_by_symbol = db().get_index_type<nft_metadata_index>().indices().get<by_symbol>();
|
||||||
|
FC_ASSERT( idx_nft_md_by_symbol.find(op.symbol) == idx_nft_md_by_symbol.end(), "NFT symbol already in use" );
|
||||||
|
return void_result();
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
object_id_type nft_metadata_create_evaluator::do_apply( const nft_metadata_create_operation& op )
|
||||||
|
{ try {
|
||||||
|
const auto& new_nft_metadata_object = db().create<nft_metadata_object>( [&]( nft_metadata_object& obj ){
|
||||||
|
obj.owner = op.owner;
|
||||||
|
obj.name = op.name;
|
||||||
|
obj.symbol = op.symbol;
|
||||||
|
obj.base_uri = op.base_uri;
|
||||||
|
});
|
||||||
|
return new_nft_metadata_object.id;
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
|
||||||
|
void_result nft_metadata_update_evaluator::do_evaluate( const nft_metadata_update_operation& op )
|
||||||
|
{ try {
|
||||||
|
const auto& idx_nft_md = db().get_index_type<nft_metadata_index>().indices().get<by_id>();
|
||||||
|
auto itr_nft_md = idx_nft_md.find(op.nft_metadata_id);
|
||||||
|
FC_ASSERT( itr_nft_md != idx_nft_md.end(), "NFT metadata not found" );
|
||||||
|
FC_ASSERT( itr_nft_md->owner == op.owner, "Only owner can modify NFT metadata" );
|
||||||
|
|
||||||
|
return void_result();
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
void_result nft_metadata_update_evaluator::do_apply( const nft_metadata_update_operation& op )
|
||||||
|
{ try {
|
||||||
|
db().modify(db().get(op.nft_metadata_id), [&] ( nft_metadata_object& obj ) {
|
||||||
|
if( op.name.valid() )
|
||||||
|
obj.name = *op.name;
|
||||||
|
if( op.symbol.valid() )
|
||||||
|
obj.symbol = *op.symbol;
|
||||||
|
if( op.base_uri.valid() )
|
||||||
|
obj.base_uri = *op.base_uri;
|
||||||
|
});
|
||||||
|
return void_result();
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
|
||||||
|
void_result nft_mint_evaluator::do_evaluate( const nft_mint_operation& op )
|
||||||
|
{ try {
|
||||||
|
const auto& idx_nft_md = db().get_index_type<nft_metadata_index>().indices().get<by_id>();
|
||||||
|
auto itr_nft_md = idx_nft_md.find(*op.nft_metadata_id);
|
||||||
|
FC_ASSERT( itr_nft_md != idx_nft_md.end(), "NFT metadata not found" );
|
||||||
|
FC_ASSERT( itr_nft_md->owner == op.payer, "Only metadata owner can mint NFT" );
|
||||||
|
|
||||||
|
return void_result();
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
object_id_type nft_mint_evaluator::do_apply( const nft_mint_operation& op )
|
||||||
|
{ try {
|
||||||
|
const auto& new_nft_object = db().create<nft_object>( [&]( nft_object& obj ){
|
||||||
|
obj.nft_metadata_id = *op.nft_metadata_id;
|
||||||
|
obj.owner = op.owner;
|
||||||
|
obj.approved = op.approved;
|
||||||
|
obj.approved_operators = op.approved_operators;
|
||||||
|
});
|
||||||
|
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 {
|
||||||
|
const auto& idx_nft = db().get_index_type<nft_index>().indices().get<by_id>();
|
||||||
|
const auto& idx_acc = db().get_index_type<account_index>().indices().get<by_id>();
|
||||||
|
|
||||||
|
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.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) ) }
|
||||||
|
|
||||||
|
object_id_type nft_safe_transfer_from_evaluator::do_apply( const nft_safe_transfer_from_operation& op )
|
||||||
|
{ try {
|
||||||
|
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 = {};
|
||||||
|
obj.approved_operators.clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return op.token_id;
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
|
||||||
|
void_result nft_approve_evaluator::do_evaluate( const nft_approve_operation& op )
|
||||||
|
{ try {
|
||||||
|
const auto& idx_nft = db().get_index_type<nft_index>().indices().get<by_id>();
|
||||||
|
const auto& idx_acc = db().get_index_type<account_index>().indices().get<by_id>();
|
||||||
|
|
||||||
|
auto itr_nft = idx_nft.find(op.token_id);
|
||||||
|
FC_ASSERT( itr_nft != idx_nft.end(), "NFT does not exists" );
|
||||||
|
|
||||||
|
auto itr_owner = idx_acc.find(op.operator_);
|
||||||
|
FC_ASSERT( itr_owner != idx_acc.end(), "Owner account does not exists" );
|
||||||
|
|
||||||
|
auto itr_approved = idx_acc.find(op.approved);
|
||||||
|
FC_ASSERT( itr_approved != idx_acc.end(), "Approved account does not exists" );
|
||||||
|
|
||||||
|
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_approved_op != itr_nft->approved_operators.end()), "Sender is not NFT owner or approved operator" );
|
||||||
|
|
||||||
|
return void_result();
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
object_id_type nft_approve_evaluator::do_apply( const nft_approve_operation& op )
|
||||||
|
{ try {
|
||||||
|
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 = 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;
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
|
||||||
|
void_result nft_set_approval_for_all_evaluator::do_evaluate( const nft_set_approval_for_all_operation& op )
|
||||||
|
{ try {
|
||||||
|
const auto& idx_acc = db().get_index_type<account_index>().indices().get<by_id>();
|
||||||
|
|
||||||
|
auto itr_operator = idx_acc.find(op.operator_);
|
||||||
|
FC_ASSERT( itr_operator != idx_acc.end(), "Operator account does not exists" );
|
||||||
|
|
||||||
|
return void_result();
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
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) {
|
||||||
|
auto itr = std::find(obj.approved_operators.begin(), obj.approved_operators.end(), op.operator_);
|
||||||
|
if ((op.approved) && (itr == obj.approved_operators.end())) {
|
||||||
|
obj.approved_operators.push_back(op.operator_);
|
||||||
|
}
|
||||||
|
if ((!op.approved) && (itr != obj.approved_operators.end())) {
|
||||||
|
obj.approved_operators.erase(itr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return void_result();
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||||
|
|
||||||
|
} } // graphene::chain
|
||||||
|
|
||||||
|
|
@ -1895,6 +1895,143 @@ class wallet_api
|
||||||
bool is_gpos,
|
bool is_gpos,
|
||||||
bool broadcast);
|
bool broadcast);
|
||||||
|
|
||||||
|
/////////
|
||||||
|
// NFT //
|
||||||
|
/////////
|
||||||
|
/**
|
||||||
|
* @brief Creates NFT metadata
|
||||||
|
* @param owner_account_id_or_name Owner account ID or name
|
||||||
|
* @param name Name of the token group
|
||||||
|
* @param symbol Symbol of the token group
|
||||||
|
* @param base_uri Base URI for token URI
|
||||||
|
* @param broadcast true to broadcast transaction to the network
|
||||||
|
* @return Signed transaction transfering the funds
|
||||||
|
*/
|
||||||
|
signed_transaction nft_metadata_create(string owner_account_id_or_name,
|
||||||
|
string name,
|
||||||
|
string symbol,
|
||||||
|
string base_uri,
|
||||||
|
bool broadcast);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Updates NFT metadata
|
||||||
|
* @param owner_account_id_or_name Owner account ID or name
|
||||||
|
* @param name Name of the token group
|
||||||
|
* @param symbol Symbol of the token group
|
||||||
|
* @param base_uri Base URI for token URI
|
||||||
|
* @param broadcast true to broadcast transaction to the network
|
||||||
|
* @return Signed transaction transfering the funds
|
||||||
|
*/
|
||||||
|
signed_transaction nft_metadata_update(string owner_account_id_or_name,
|
||||||
|
string name,
|
||||||
|
string symbol,
|
||||||
|
string base_uri,
|
||||||
|
bool broadcast);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates NFT
|
||||||
|
* @param metadata_owner_account_id_or_name NFT metadata owner account ID or name
|
||||||
|
* @param metadata_id NFT metadata ID to which token will belong
|
||||||
|
* @param owner_account_id_or_name Owner account ID or name
|
||||||
|
* @param approved_account_id_or_name Approved account ID or name
|
||||||
|
* @param token_uri Token URI (Will be combined with metadata base_uri if its not empty)
|
||||||
|
* @param broadcast true to broadcast transaction to the network
|
||||||
|
* @return Signed transaction transfering the funds
|
||||||
|
*/
|
||||||
|
signed_transaction nft_create(string metadata_owner_account_id_or_name,
|
||||||
|
nft_metadata_id_type metadata_id,
|
||||||
|
string owner_account_id_or_name,
|
||||||
|
string approved_account_id_or_name,
|
||||||
|
string token_uri,
|
||||||
|
bool broadcast);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the number of NFT owned by account
|
||||||
|
* @param owner_account_id_or_name Owner account ID or name
|
||||||
|
* @return Number of NFTs owned by account
|
||||||
|
*/
|
||||||
|
uint64_t nft_get_balance(string owner_account_id_or_name) 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 Transfers NFT safely
|
||||||
|
* @param operator_account_id_or_name Operators account ID or name
|
||||||
|
* @param from_account_id_or_name Senders account ID or name
|
||||||
|
* @param to_account_id_or_name Receivers account ID or name
|
||||||
|
* @param token_id NFT ID
|
||||||
|
* @param data Non mandatory data
|
||||||
|
* @param broadcast true to broadcast transaction to the network
|
||||||
|
* @return Signed transaction transfering NFT
|
||||||
|
*/
|
||||||
|
signed_transaction nft_safe_transfer_from(string operator_account_id_or_name,
|
||||||
|
string from_account_id_or_name,
|
||||||
|
string to_account_id_or_name,
|
||||||
|
nft_id_type token_id,
|
||||||
|
string data,
|
||||||
|
bool broadcast);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transfers NFT
|
||||||
|
* @param operator_account_id_or_name Operators account ID or name
|
||||||
|
* @param from_account_id_or_name Senders account ID or name
|
||||||
|
* @param to_account_id_or_name Receivers account ID or name
|
||||||
|
* @param token_id NFT ID
|
||||||
|
* @param broadcast true to broadcast transaction to the network
|
||||||
|
* @return Signed transaction transfering NFT
|
||||||
|
*/
|
||||||
|
signed_transaction nft_transfer_from(string operator_account_id_or_name,
|
||||||
|
string from_account_id_or_name,
|
||||||
|
string to_account_id_or_name,
|
||||||
|
nft_id_type token_id,
|
||||||
|
bool broadcast);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets approved account for NFT
|
||||||
|
* @param operator_account_id_or_name Operators account ID or name
|
||||||
|
* @param approved_account_id_or_name Senders account ID or name
|
||||||
|
* @param token_id NFT ID
|
||||||
|
* @param broadcast true to broadcast transaction to the network
|
||||||
|
* @return Signed transaction setting approving account for NFT
|
||||||
|
*/
|
||||||
|
signed_transaction nft_approve(string operator_account_id_or_name,
|
||||||
|
string approved_account_id_or_name,
|
||||||
|
nft_id_type token_id,
|
||||||
|
bool broadcast);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets approval for all NFT owned by owner
|
||||||
|
* @param owner_account_id_or_name Owner account ID or name
|
||||||
|
* @param operator_account_id_or_name Operator account ID or name
|
||||||
|
* @param approved true if approved
|
||||||
|
* @param broadcast true to broadcast transaction to the network
|
||||||
|
* @return Signed transaction setting approvals for all NFT owned by owner
|
||||||
|
*/
|
||||||
|
signed_transaction nft_set_approval_for_all(string owner_account_id_or_name,
|
||||||
|
string operator_account_id_or_name,
|
||||||
|
bool approved,
|
||||||
|
bool broadcast);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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(string owner_account_id_or_name, string operator_account_id_or_name) const;
|
||||||
|
|
||||||
void dbg_make_uia(string creator, string symbol);
|
void dbg_make_uia(string creator, string symbol);
|
||||||
void dbg_make_mia(string creator, string symbol);
|
void dbg_make_mia(string creator, string symbol);
|
||||||
void dbg_push_blocks( std::string src_filename, uint32_t count );
|
void dbg_push_blocks( std::string src_filename, uint32_t count );
|
||||||
|
|
@ -2145,6 +2282,14 @@ FC_API( graphene::wallet::wallet_api,
|
||||||
(tournament_leave)
|
(tournament_leave)
|
||||||
(rps_throw)
|
(rps_throw)
|
||||||
(create_vesting_balance)
|
(create_vesting_balance)
|
||||||
|
(nft_get_balance)
|
||||||
|
(nft_owner_of)
|
||||||
|
(nft_safe_transfer_from)
|
||||||
|
(nft_transfer_from)
|
||||||
|
(nft_approve)
|
||||||
|
(nft_set_approval_for_all)
|
||||||
|
(nft_get_approved)
|
||||||
|
(nft_is_approved_for_all)
|
||||||
(get_upcoming_tournaments)
|
(get_upcoming_tournaments)
|
||||||
(get_tournaments)
|
(get_tournaments)
|
||||||
(get_tournaments_by_state)
|
(get_tournaments_by_state)
|
||||||
|
|
|
||||||
|
|
@ -6157,6 +6157,176 @@ signed_transaction wallet_api::create_vesting_balance(string owner,
|
||||||
return my->sign_transaction( trx, broadcast );
|
return my->sign_transaction( trx, broadcast );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::nft_metadata_create(string owner_account_id_or_name,
|
||||||
|
string name,
|
||||||
|
string symbol,
|
||||||
|
string base_uri,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
account_object owner_account = my->get_account(owner_account_id_or_name);
|
||||||
|
|
||||||
|
nft_metadata_create_operation op;
|
||||||
|
op.owner = owner_account.id;
|
||||||
|
op.name = name;
|
||||||
|
op.symbol = symbol;
|
||||||
|
op.base_uri = base_uri;
|
||||||
|
|
||||||
|
signed_transaction trx;
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
my->set_operation_fees( trx, my->_remote_db->get_global_properties().parameters.current_fees );
|
||||||
|
trx.validate();
|
||||||
|
|
||||||
|
return my->sign_transaction( trx, broadcast );
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::nft_metadata_update(string owner_account_id_or_name,
|
||||||
|
string name,
|
||||||
|
string symbol,
|
||||||
|
string base_uri,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
account_object owner_account = my->get_account(owner_account_id_or_name);
|
||||||
|
|
||||||
|
nft_metadata_update_operation op;
|
||||||
|
op.owner = owner_account.id;
|
||||||
|
op.name = name;
|
||||||
|
op.symbol = symbol;
|
||||||
|
op.base_uri = base_uri;
|
||||||
|
|
||||||
|
signed_transaction trx;
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
my->set_operation_fees( trx, my->_remote_db->get_global_properties().parameters.current_fees );
|
||||||
|
trx.validate();
|
||||||
|
|
||||||
|
return my->sign_transaction( trx, broadcast );
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::nft_create(string metadata_owner_account_id_or_name,
|
||||||
|
nft_metadata_id_type metadata_id,
|
||||||
|
string owner_account_id_or_name,
|
||||||
|
string approved_account_id_or_name,
|
||||||
|
string token_uri,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
account_object metadata_owner_account = my->get_account(metadata_owner_account_id_or_name);
|
||||||
|
account_object owner_account = my->get_account(owner_account_id_or_name);
|
||||||
|
account_object approved_account = my->get_account(approved_account_id_or_name);
|
||||||
|
|
||||||
|
nft_mint_operation op;
|
||||||
|
op.payer = metadata_owner_account.id;
|
||||||
|
op.nft_metadata_id = op.nft_metadata_id;
|
||||||
|
op.owner = owner_account.id;
|
||||||
|
op.approved = approved_account.id;
|
||||||
|
op.token_uri = token_uri;
|
||||||
|
|
||||||
|
signed_transaction trx;
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
my->set_operation_fees( trx, my->_remote_db->get_global_properties().parameters.current_fees );
|
||||||
|
trx.validate();
|
||||||
|
|
||||||
|
return my->sign_transaction( trx, broadcast );
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t wallet_api::nft_get_balance(string owner_account_id_or_name) const
|
||||||
|
{
|
||||||
|
account_object owner_account = my->get_account(owner_account_id_or_name);
|
||||||
|
return my->_remote_db->nft_get_balance(owner_account.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<account_id_type> wallet_api::nft_owner_of(const nft_id_type token_id) const
|
||||||
|
{
|
||||||
|
return my->_remote_db->nft_owner_of(token_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::nft_safe_transfer_from(string operator_account_id_or_name,
|
||||||
|
string from_account_id_or_name,
|
||||||
|
string to_account_id_or_name,
|
||||||
|
nft_id_type token_id,
|
||||||
|
string data,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
account_object operator_account = my->get_account(operator_account_id_or_name);
|
||||||
|
account_object from_account = my->get_account(from_account_id_or_name);
|
||||||
|
account_object to_account = my->get_account(to_account_id_or_name);
|
||||||
|
|
||||||
|
nft_safe_transfer_from_operation op;
|
||||||
|
op.operator_ = operator_account.id;
|
||||||
|
op.from = from_account.id;
|
||||||
|
op.to = to_account.id;
|
||||||
|
op.token_id = token_id;
|
||||||
|
op.data = data;
|
||||||
|
|
||||||
|
signed_transaction trx;
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
my->set_operation_fees( trx, my->_remote_db->get_global_properties().parameters.current_fees );
|
||||||
|
trx.validate();
|
||||||
|
|
||||||
|
return my->sign_transaction( trx, broadcast );
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::nft_transfer_from(string operator_account_id_or_name,
|
||||||
|
string from_account_id_or_name,
|
||||||
|
string to_account_id_or_name,
|
||||||
|
nft_id_type token_id,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
return nft_safe_transfer_from(operator_account_id_or_name, from_account_id_or_name, to_account_id_or_name, token_id, "", broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::nft_approve(string operator_account_id_or_name,
|
||||||
|
string approved_account_id_or_name,
|
||||||
|
nft_id_type token_id,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
account_object operator_account = my->get_account(operator_account_id_or_name);
|
||||||
|
account_object approved_account = my->get_account(approved_account_id_or_name);
|
||||||
|
|
||||||
|
nft_approve_operation op;
|
||||||
|
op.operator_ = operator_account.id;
|
||||||
|
op.approved = approved_account.id;
|
||||||
|
op.token_id = token_id;
|
||||||
|
|
||||||
|
signed_transaction trx;
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
my->set_operation_fees( trx, my->_remote_db->get_global_properties().parameters.current_fees );
|
||||||
|
trx.validate();
|
||||||
|
|
||||||
|
return my->sign_transaction( trx, broadcast );
|
||||||
|
}
|
||||||
|
|
||||||
|
signed_transaction wallet_api::nft_set_approval_for_all(string owner_account_id_or_name,
|
||||||
|
string operator_account_id_or_name,
|
||||||
|
bool approved,
|
||||||
|
bool broadcast)
|
||||||
|
{
|
||||||
|
account_object owner_account = my->get_account(owner_account_id_or_name);
|
||||||
|
account_object operator_account = my->get_account(operator_account_id_or_name);
|
||||||
|
|
||||||
|
nft_set_approval_for_all_operation op;
|
||||||
|
op.owner = owner_account.id;
|
||||||
|
op.operator_ = operator_account.id;
|
||||||
|
op.approved = approved;
|
||||||
|
|
||||||
|
signed_transaction trx;
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
my->set_operation_fees( trx, my->_remote_db->get_global_properties().parameters.current_fees );
|
||||||
|
trx.validate();
|
||||||
|
|
||||||
|
return my->sign_transaction( trx, broadcast );
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<account_id_type> wallet_api::nft_get_approved(const nft_id_type token_id) const
|
||||||
|
{
|
||||||
|
return my->_remote_db->nft_get_approved(token_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wallet_api::nft_is_approved_for_all(string owner_account_id_or_name, string operator_account_id_or_name) const
|
||||||
|
{
|
||||||
|
account_object owner_account = my->get_account(owner_account_id_or_name);
|
||||||
|
account_object operator_account = my->get_account(operator_account_id_or_name);
|
||||||
|
return my->_remote_db->nft_is_approved_for_all(owner_account.id, operator_account.id);
|
||||||
|
}
|
||||||
|
|
||||||
// default ctor necessary for FC_REFLECT
|
// default ctor necessary for FC_REFLECT
|
||||||
signed_block_with_info::signed_block_with_info()
|
signed_block_with_info::signed_block_with_info()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
#include <graphene/chain/tournament_object.hpp>
|
#include <graphene/chain/tournament_object.hpp>
|
||||||
#include <graphene/chain/match_object.hpp>
|
#include <graphene/chain/match_object.hpp>
|
||||||
#include <graphene/chain/game_object.hpp>
|
#include <graphene/chain/game_object.hpp>
|
||||||
|
#include <graphene/chain/nft_object.hpp>
|
||||||
|
|
||||||
#include <fc/smart_ref_impl.hpp>
|
#include <fc/smart_ref_impl.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
||||||
384
tests/tests/nft_tests.cpp
Normal file
384
tests/tests/nft_tests.cpp
Normal file
|
|
@ -0,0 +1,384 @@
|
||||||
|
#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_metadata_create_test ) {
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("nft_metadata_create_test");
|
||||||
|
|
||||||
|
generate_block();
|
||||||
|
set_expiration(db, trx);
|
||||||
|
|
||||||
|
ACTORS((mdowner));
|
||||||
|
|
||||||
|
generate_block();
|
||||||
|
set_expiration(db, trx);
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Send nft_metadata_create_operation");
|
||||||
|
|
||||||
|
nft_metadata_create_operation op;
|
||||||
|
op.owner = mdowner_id;
|
||||||
|
op.name = "NFT Test";
|
||||||
|
op.symbol = "NFT";
|
||||||
|
op.base_uri = "http://nft.example.com";
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, mdowner_private_key);
|
||||||
|
PUSH_TX(db, trx, ~0);
|
||||||
|
}
|
||||||
|
generate_block();
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("Check nft_metadata_create_operation results");
|
||||||
|
|
||||||
|
const auto& idx = db.get_index_type<nft_metadata_index>().indices().get<by_id>();
|
||||||
|
BOOST_REQUIRE( idx.size() == 1 );
|
||||||
|
auto obj = idx.begin();
|
||||||
|
BOOST_REQUIRE( obj != idx.end() );
|
||||||
|
BOOST_CHECK( obj->owner == mdowner_id );
|
||||||
|
BOOST_CHECK( obj->name == "NFT Test" );
|
||||||
|
BOOST_CHECK( obj->symbol == "NFT" );
|
||||||
|
BOOST_CHECK( obj->base_uri == "http://nft.example.com" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( nft_metadata_update_test ) {
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("nft_metadata_update_test");
|
||||||
|
|
||||||
|
INVOKE(nft_metadata_create_test);
|
||||||
|
|
||||||
|
GET_ACTOR(mdowner);
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Send nft_metadata_update_operation");
|
||||||
|
|
||||||
|
nft_metadata_update_operation op;
|
||||||
|
op.owner = mdowner_id;
|
||||||
|
op.name = "New NFT Test";
|
||||||
|
op.symbol = "New NFT";
|
||||||
|
op.base_uri = "new http://nft.example.com";
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, mdowner_private_key);
|
||||||
|
PUSH_TX(db, trx, ~0);
|
||||||
|
}
|
||||||
|
generate_block();
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("Check nft_metadata_update_operation results");
|
||||||
|
|
||||||
|
const auto& idx = db.get_index_type<nft_metadata_index>().indices().get<by_id>();
|
||||||
|
BOOST_REQUIRE( idx.size() == 1 );
|
||||||
|
auto obj = idx.begin();
|
||||||
|
BOOST_REQUIRE( obj != idx.end() );
|
||||||
|
BOOST_CHECK( obj->owner == mdowner_id );
|
||||||
|
BOOST_CHECK( obj->name == "New NFT Test" );
|
||||||
|
BOOST_CHECK( obj->symbol == "New NFT" );
|
||||||
|
BOOST_CHECK( obj->base_uri == "new http://nft.example.com" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( nft_mint_test ) {
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("nft_mint_test");
|
||||||
|
|
||||||
|
generate_block();
|
||||||
|
set_expiration(db, trx);
|
||||||
|
|
||||||
|
INVOKE(nft_metadata_create_test);
|
||||||
|
|
||||||
|
ACTORS((alice));
|
||||||
|
ACTORS((bob));
|
||||||
|
ACTORS((operator1));
|
||||||
|
ACTORS((operator2));
|
||||||
|
|
||||||
|
GET_ACTOR(mdowner);
|
||||||
|
|
||||||
|
generate_block();
|
||||||
|
set_expiration(db, trx);
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Send nft_mint_operation");
|
||||||
|
|
||||||
|
const auto& idx = db.get_index_type<nft_metadata_index>().indices().get<by_id>();
|
||||||
|
BOOST_REQUIRE( idx.size() == 1 );
|
||||||
|
auto nft_md_obj = idx.begin();
|
||||||
|
|
||||||
|
nft_mint_operation op;
|
||||||
|
op.payer = mdowner_id;
|
||||||
|
op.nft_metadata_id = nft_md_obj->id;
|
||||||
|
op.owner = alice_id;
|
||||||
|
op.approved = alice_id;
|
||||||
|
op.approved_operators.push_back(operator1_id);
|
||||||
|
op.approved_operators.push_back(operator2_id);
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, alice_private_key);
|
||||||
|
PUSH_TX(db, trx, ~0);
|
||||||
|
}
|
||||||
|
generate_block();
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("Check nft_mint_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_AUTO_TEST_CASE( nft_safe_transfer_from_test ) {
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("nft_safe_transfer_from_test");
|
||||||
|
|
||||||
|
INVOKE(nft_mint_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_mint_test);
|
||||||
|
|
||||||
|
GET_ACTOR(alice);
|
||||||
|
GET_ACTOR(operator1);
|
||||||
|
GET_ACTOR(operator2);
|
||||||
|
|
||||||
|
ACTORS((operator3));
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Send nft_approve_operation");
|
||||||
|
|
||||||
|
nft_approve_operation op;
|
||||||
|
op.operator_ = 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 == 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_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));
|
||||||
|
|
||||||
|
INVOKE(nft_metadata_create_test);
|
||||||
|
|
||||||
|
GET_ACTOR(mdowner);
|
||||||
|
|
||||||
|
generate_block();
|
||||||
|
set_expiration(db, trx);
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE("Create NFT assets");
|
||||||
|
|
||||||
|
const auto& idx = db.get_index_type<nft_metadata_index>().indices().get<by_id>();
|
||||||
|
BOOST_REQUIRE( idx.size() == 1 );
|
||||||
|
auto nft_md_obj = idx.begin();
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Send nft_mint_operation 1");
|
||||||
|
|
||||||
|
nft_mint_operation op;
|
||||||
|
op.payer = mdowner_id;
|
||||||
|
op.nft_metadata_id = nft_md_obj->id;
|
||||||
|
op.owner = alice_id;
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, mdowner_private_key);
|
||||||
|
PUSH_TX(db, trx, ~0);
|
||||||
|
}
|
||||||
|
generate_block();
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Send nft_mint_operation 2");
|
||||||
|
|
||||||
|
nft_mint_operation op;
|
||||||
|
op.payer = mdowner_id;
|
||||||
|
op.nft_metadata_id = nft_md_obj->id;
|
||||||
|
op.owner = bob_id;
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, mdowner_private_key);
|
||||||
|
PUSH_TX(db, trx, ~0);
|
||||||
|
}
|
||||||
|
generate_block();
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Send nft_mint_operation 3");
|
||||||
|
|
||||||
|
nft_mint_operation op;
|
||||||
|
op.payer = mdowner_id;
|
||||||
|
op.nft_metadata_id = nft_md_obj->id;
|
||||||
|
op.owner = alice_id;
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, mdowner_private_key);
|
||||||
|
PUSH_TX(db, trx, ~0);
|
||||||
|
}
|
||||||
|
generate_block();
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Send nft_mint_operation 4");
|
||||||
|
|
||||||
|
nft_mint_operation op;
|
||||||
|
op.payer = mdowner_id;
|
||||||
|
op.nft_metadata_id = nft_md_obj->id;
|
||||||
|
op.owner = bob_id;
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, mdowner_private_key);
|
||||||
|
PUSH_TX(db, trx, ~0);
|
||||||
|
}
|
||||||
|
generate_block();
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOST_TEST_MESSAGE("Send nft_mint_operation 5");
|
||||||
|
|
||||||
|
nft_mint_operation op;
|
||||||
|
op.payer = mdowner_id;
|
||||||
|
op.nft_metadata_id = nft_md_obj->id;
|
||||||
|
op.owner = alice_id;
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
sign(trx, mdowner_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("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() == 0 );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
Loading…
Reference in a new issue