* private-key option update * ppy marketplace 1 - add evaluators and objects * NFT object and basic operations * ci: update .gitlab-ci.yml * ci: update .gitlab-ci.yml * NFT evaluators and basic tests, no evaluator checks * Evaluator checks in place * ppy marketplace 2 - batch sale, offer_object escrow * Database API * Wallet API * NFT metadata implemented * Fix NFT tests * Database API for NFT metadata and enumerables * ppy marketplace 4 - Add tests NFT+Marketplace * ppy marketplace 5 - Add revenue split * ppy marketplace 6 - Remove unnecessary files * ppy marketplace 7 - Add db, wallet changes and some NFT fixes * ppy marketplace 8 - Add pagination for list APIs * ci: update .gitlab-ci.yml * New DB API, list all NFTs, list NFTs by owner * Marketplace + NFT + RBAC (#368) * rbac1 - evaluators and op validators added * rbac2 - op_type hf checks * rbac3 - tx auth verify changes * Update .gitlab-ci.yml * rbac4 - basic op tests * rbac5 - clear expired and deleted permission linked auths * rbac6 - more tests * rbac7 - more tests * rbac8 - more tests * rbac9 - wallet and db api changes * rbac10 - db api changes for required signature fetch * rbac11 - add db_api tests * rbac12 - add missing code for key auths Co-authored-by: Roshan Syed <roshan.syed.rs@gmail.com> Co-authored-by: sierra19XX <15652887+sierra19XX@users.noreply.github.com> * Fix nft_get_token_uri returning empty string * Fix nft_mint_evaluator to save token_uri * Fix cli_wallet to properly pass metadata id for nft_create * ppy marketplace 9 - FC_REFLECT offer create op * Add stricter checks to NFTs * GPOS2 HF - Handle rolling period on missing blocks (#369) * Mainnet chain halt 5050 Issue (#370) * Unlisting offers, add result in offer history object * Reverting genesis.json wrong commit * Add non-transferable non-sellable properties to NFTs * Review comments - change variable names, use scoped enums * nft_metadata_update changes * NFT HF checks and op fee addition changes * NFT make revenue_split integer from double * revenue_split condition check allow zero or above * Peerplays Marketplace + NFT (#367) * ppy marketplace 1 - add evaluators and objects * NFT object and basic operations * ci: update .gitlab-ci.yml * ci: update .gitlab-ci.yml * NFT evaluators and basic tests, no evaluator checks * Evaluator checks in place * ppy marketplace 2 - batch sale, offer_object escrow * Database API * Wallet API * NFT metadata implemented * Fix NFT tests * Database API for NFT metadata and enumerables * ppy marketplace 4 - Add tests NFT+Marketplace * ppy marketplace 5 - Add revenue split * ppy marketplace 6 - Remove unnecessary files * ppy marketplace 7 - Add db, wallet changes and some NFT fixes * ppy marketplace 8 - Add pagination for list APIs * New DB API, list all NFTs, list NFTs by owner * Marketplace + NFT + RBAC (#368) * rbac1 - evaluators and op validators added * rbac2 - op_type hf checks * rbac3 - tx auth verify changes * Update .gitlab-ci.yml * rbac4 - basic op tests * rbac5 - clear expired and deleted permission linked auths * rbac6 - more tests * rbac7 - more tests * rbac8 - more tests * rbac9 - wallet and db api changes * rbac10 - db api changes for required signature fetch * rbac11 - add db_api tests * rbac12 - add missing code for key auths Co-authored-by: Roshan Syed <roshan.syed.rs@gmail.com> Co-authored-by: sierra19XX <15652887+sierra19XX@users.noreply.github.com> * Fix nft_get_token_uri returning empty string * Fix nft_mint_evaluator to save token_uri * Fix cli_wallet to properly pass metadata id for nft_create * ppy marketplace 9 - FC_REFLECT offer create op * Add stricter checks to NFTs * Unlisting offers, add result in offer history object * Reverting genesis.json wrong commit * Add non-transferable non-sellable properties to NFTs * Review comments - change variable names, use scoped enums * nft_metadata_update changes * NFT HF checks and op fee addition changes * NFT make revenue_split integer from double * revenue_split condition check allow zero or above Co-authored-by: Srdjan Obucina <obucinac@gmail.com> Co-authored-by: Roshan Syed <roshan.syed.rs@gmail.com> Co-authored-by: obucina <11353193+obucina@users.noreply.github.com> * Beatrice NFT HF Co-authored-by: pbattu123 <43043205+pbattu123@users.noreply.github.com> Co-authored-by: pbattu123 <p.battu@pbsa.info> Co-authored-by: Srdjan Obucina <obucinac@gmail.com> Co-authored-by: Roshan Syed <roshan.syed.rs@gmail.com> Co-authored-by: obucina <11353193+obucina@users.noreply.github.com>
941 lines
38 KiB
C++
941 lines
38 KiB
C++
#include <boost/test/unit_test.hpp>
|
|
|
|
#include "../common/database_fixture.hpp"
|
|
|
|
#include <graphene/chain/hardfork.hpp>
|
|
#include <graphene/chain/nft_object.hpp>
|
|
#include <graphene/chain/offer_object.hpp>
|
|
|
|
using namespace graphene::chain;
|
|
using namespace graphene::chain::test;
|
|
|
|
BOOST_FIXTURE_TEST_SUITE(marketplace_tests, database_fixture)
|
|
offer_id_type buy_offer;
|
|
offer_id_type sell_offer;
|
|
BOOST_AUTO_TEST_CASE(nft_metadata_create_test)
|
|
{
|
|
|
|
BOOST_TEST_MESSAGE("nft_metadata_create_test");
|
|
generate_blocks(HARDFORK_NFT_TIME);
|
|
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";
|
|
op.revenue_partner = mdowner_id;
|
|
op.revenue_split = 1000;
|
|
|
|
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_mint_test)
|
|
{
|
|
|
|
BOOST_TEST_MESSAGE("nft_mint_test");
|
|
|
|
INVOKE(nft_metadata_create_test);
|
|
set_expiration(db, trx);
|
|
|
|
ACTORS((alice)(bob)(charlie)(operator1)(operator2));
|
|
upgrade_to_lifetime_member(alice);
|
|
upgrade_to_lifetime_member(bob);
|
|
upgrade_to_lifetime_member(charlie);
|
|
transfer(committee_account, alice_id, asset(1000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
|
transfer(committee_account, bob_id, asset(1000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
|
transfer(committee_account, charlie_id, asset(1000 * GRAPHENE_BLOCKCHAIN_PRECISION));
|
|
|
|
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);
|
|
trx.clear();
|
|
}
|
|
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);
|
|
|
|
{
|
|
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);
|
|
trx.clear();
|
|
}
|
|
generate_block();
|
|
BOOST_REQUIRE(idx.size() == 2);
|
|
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);
|
|
const auto &nft2 = nft_id_type(1)(db);
|
|
BOOST_CHECK(nft2.owner == alice_id);
|
|
BOOST_CHECK(nft2.approved_operators.size() == 2);
|
|
BOOST_CHECK(nft2.approved_operators.at(0) == operator1_id);
|
|
BOOST_CHECK(nft2.approved_operators.at(1) == operator2_id);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(create_sell_offer_test)
|
|
{
|
|
try
|
|
{
|
|
INVOKE(nft_mint_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(operator1);
|
|
GET_ACTOR(operator2);
|
|
const asset_object &bitusd = create_bitasset("STUB");
|
|
{
|
|
offer_operation offer_op;
|
|
offer_op.item_ids.emplace(nft_id_type(0));
|
|
offer_op.item_ids.emplace(nft_id_type(1));
|
|
offer_op.issuer = alice_id;
|
|
offer_op.buying_item = false;
|
|
offer_op.maximum_price = asset(10000);
|
|
offer_op.minimum_price = asset(10);
|
|
offer_op.offer_expiration_date = db.head_block_time() + fc::seconds(15);
|
|
trx.operations.push_back(offer_op);
|
|
auto op = trx.operations.back().get<offer_operation>();
|
|
REQUIRE_THROW_WITH_VALUE(op, offer_expiration_date, db.head_block_time());
|
|
REQUIRE_THROW_WITH_VALUE(op, issuer, bob_id);
|
|
// positive prices
|
|
REQUIRE_OP_VALIDATION_FAILURE(op, minimum_price, asset(-1));
|
|
REQUIRE_OP_VALIDATION_FAILURE(op, maximum_price, asset(-1));
|
|
REQUIRE_OP_VALIDATION_FAILURE(op, fee, asset(-1));
|
|
// min price > max price check
|
|
REQUIRE_OP_VALIDATION_FAILURE(op, maximum_price, asset(1));
|
|
// different asset for min/max
|
|
REQUIRE_OP_VALIDATION_FAILURE(op, minimum_price, asset(1, bitusd.id));
|
|
|
|
trx.clear();
|
|
trx.operations.push_back(offer_op);
|
|
sign(trx, alice_private_key);
|
|
PUSH_TX(db, trx);
|
|
trx.clear();
|
|
//generate_block();
|
|
|
|
const auto &idx = db.get_index_type<offer_index>().indices().get<by_id>();
|
|
BOOST_REQUIRE(idx.size() == 1);
|
|
const offer_object &d = offer_id_type(0)(db);
|
|
|
|
BOOST_CHECK(d.space_id == protocol_ids);
|
|
BOOST_CHECK(d.type_id == offer_object_type);
|
|
//empty bid
|
|
BOOST_CHECK(!d.bid_price);
|
|
BOOST_CHECK(!d.bidder);
|
|
// data integrity
|
|
BOOST_CHECK(d.issuer == alice_id);
|
|
BOOST_CHECK(d.maximum_price == asset(10000));
|
|
BOOST_CHECK(d.minimum_price == asset(10));
|
|
BOOST_CHECK(d.buying_item == false);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)) == true);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)) == true);
|
|
sell_offer = d.id;
|
|
}
|
|
}
|
|
catch (fc::exception &e)
|
|
{
|
|
edump((e.to_detail_string()));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(buy_bid_for_sell_offer_test)
|
|
{
|
|
try
|
|
{
|
|
INVOKE(create_sell_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(operator1);
|
|
|
|
const auto &offer_obj = sell_offer(db);
|
|
|
|
bid_operation bid_op;
|
|
bid_op.offer_id = offer_obj.id;
|
|
bid_op.bid_price = asset(offer_obj.minimum_price.amount + 1, offer_obj.minimum_price.asset_id);
|
|
bid_op.bidder = bob_id;
|
|
trx.operations.push_back(bid_op);
|
|
|
|
asset exp_delta_bidder = -bid_op.bid_price;
|
|
int64_t bidder_balance = get_balance(bob_id(db), asset_id_type()(db));
|
|
|
|
auto op = trx.operations.back().get<bid_operation>();
|
|
// Positive asset values
|
|
REQUIRE_THROW_WITH_VALUE(op, bid_price, asset(-1, asset_id_type()));
|
|
// Max price limit
|
|
REQUIRE_THROW_WITH_VALUE(op, bid_price, asset(offer_obj.maximum_price.amount + 1, offer_obj.minimum_price.asset_id));
|
|
// Min Price Limit
|
|
REQUIRE_THROW_WITH_VALUE(op, bid_price, asset(offer_obj.minimum_price.amount - 1, offer_obj.minimum_price.asset_id));
|
|
// Invalid offer
|
|
REQUIRE_THROW_WITH_VALUE(op, offer_id, offer_id_type(6));
|
|
// Owner bidder
|
|
REQUIRE_THROW_WITH_VALUE(op, bidder, alice_id);
|
|
// Operator bidder
|
|
REQUIRE_THROW_WITH_VALUE(op, bidder, operator1_id);
|
|
// Different asset
|
|
REQUIRE_THROW_WITH_VALUE(op, bid_price, asset(50, asset_id_type(1)));
|
|
|
|
trx.clear();
|
|
trx.operations.push_back(bid_op);
|
|
sign(trx, bob_private_key);
|
|
PUSH_TX(db, trx);
|
|
trx.clear();
|
|
|
|
BOOST_CHECK_EQUAL(get_balance(bob_id(db), asset_id_type()(db)),
|
|
(bidder_balance + exp_delta_bidder.amount).value);
|
|
//not empty bid
|
|
BOOST_CHECK(offer_obj.bid_price);
|
|
BOOST_CHECK(offer_obj.bidder);
|
|
// data integrity
|
|
BOOST_CHECK(offer_obj.bidder == bob_id);
|
|
BOOST_CHECK(offer_obj.issuer == alice_id);
|
|
BOOST_CHECK(offer_obj.maximum_price == asset(10000));
|
|
BOOST_CHECK(offer_obj.minimum_price == asset(10));
|
|
BOOST_CHECK(offer_obj.bid_price == bid_op.bid_price);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)));
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)));
|
|
}
|
|
catch (fc::exception &e)
|
|
{
|
|
edump((e.to_detail_string()));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(second_buy_bid_for_sell_offer_test)
|
|
{
|
|
try
|
|
{
|
|
INVOKE(buy_bid_for_sell_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(charlie);
|
|
GET_ACTOR(operator1);
|
|
|
|
int64_t bob_balance = get_balance(bob_id(db), asset_id_type()(db));
|
|
int64_t charlie_balance = get_balance(charlie_id(db), asset_id_type()(db));
|
|
const auto &offer_obj = sell_offer(db);
|
|
|
|
bid_operation bid_op;
|
|
bid_op.offer_id = offer_obj.id;
|
|
bid_op.bid_price = asset((*offer_obj.bid_price).amount + 1, offer_obj.minimum_price.asset_id);
|
|
bid_op.bidder = charlie_id;
|
|
trx.operations.push_back(bid_op);
|
|
|
|
asset bid = bid_op.bid_price;
|
|
asset exp_delta_bidder1 = *offer_obj.bid_price;
|
|
asset exp_delta_bidder2 = -bid;
|
|
|
|
auto op = trx.operations.back().get<bid_operation>();
|
|
// Not a better bid than previous
|
|
REQUIRE_THROW_WITH_VALUE(op, bid_price, asset((*offer_obj.bid_price).amount, offer_obj.minimum_price.asset_id));
|
|
|
|
trx.clear();
|
|
trx.operations.push_back(bid_op);
|
|
sign(trx, charlie_private_key);
|
|
PUSH_TX(db, trx);
|
|
trx.clear();
|
|
|
|
BOOST_CHECK_EQUAL(get_balance(bob_id(db), asset_id_type()(db)),
|
|
(bob_balance + exp_delta_bidder1.amount).value);
|
|
BOOST_CHECK_EQUAL(get_balance(charlie_id(db), asset_id_type()(db)),
|
|
(charlie_balance + exp_delta_bidder2.amount).value);
|
|
|
|
//not empty bid
|
|
BOOST_CHECK(offer_obj.bid_price);
|
|
BOOST_CHECK(offer_obj.bidder);
|
|
|
|
// data integrity
|
|
BOOST_CHECK(offer_obj.bidder == charlie_id);
|
|
BOOST_CHECK(offer_obj.issuer == alice_id);
|
|
BOOST_CHECK(offer_obj.maximum_price == asset(10000));
|
|
BOOST_CHECK(offer_obj.minimum_price == asset(10));
|
|
BOOST_CHECK(offer_obj.bid_price == bid);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)));
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)));
|
|
}
|
|
catch (fc::exception &e)
|
|
{
|
|
edump((e.to_detail_string()));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(best_buy_bid_for_sell_offer)
|
|
{
|
|
try
|
|
{
|
|
INVOKE(second_buy_bid_for_sell_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(charlie);
|
|
GET_ACTOR(operator1);
|
|
GET_ACTOR(mdowner);
|
|
|
|
int64_t bob_balance = get_balance(bob_id(db), asset_id_type()(db));
|
|
int64_t alice_balance = get_balance(alice_id(db), asset_id_type()(db));
|
|
int64_t charlie_balance = get_balance(charlie_id(db), asset_id_type()(db));
|
|
int64_t mdowner_balance = get_balance(mdowner_id(db), asset_id_type()(db));
|
|
const auto &offer_obj = sell_offer(db);
|
|
|
|
bid_operation bid_op;
|
|
bid_op.offer_id = offer_obj.id;
|
|
bid_op.bid_price = asset(offer_obj.maximum_price.amount, offer_obj.minimum_price.asset_id);
|
|
bid_op.bidder = bob_id;
|
|
|
|
asset bid = bid_op.bid_price;
|
|
asset exp_delta_bidder1 = *offer_obj.bid_price;
|
|
asset exp_delta_bidder2 = -bid;
|
|
|
|
trx.operations.push_back(bid_op);
|
|
sign(trx, bob_private_key);
|
|
PUSH_TX(db, trx);
|
|
trx.clear();
|
|
// Check balances
|
|
BOOST_CHECK_EQUAL(get_balance(bob_id(db), asset_id_type()(db)),
|
|
(bob_balance + exp_delta_bidder2.amount).value);
|
|
BOOST_CHECK_EQUAL(get_balance(charlie_id(db), asset_id_type()(db)),
|
|
(charlie_balance + exp_delta_bidder1.amount).value);
|
|
//not empty bid
|
|
BOOST_CHECK(offer_obj.bid_price);
|
|
BOOST_CHECK(offer_obj.bidder);
|
|
// data integrity
|
|
BOOST_CHECK(offer_obj.bidder == bob_id);
|
|
BOOST_CHECK(offer_obj.issuer == alice_id);
|
|
BOOST_CHECK(offer_obj.maximum_price == asset(10000));
|
|
BOOST_CHECK(offer_obj.minimum_price == asset(10));
|
|
BOOST_CHECK(offer_obj.bid_price == bid);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)));
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)));
|
|
auto cached_offer_obj = offer_obj;
|
|
// Generate a block and offer should be finalized with bid
|
|
generate_block();
|
|
int64_t partner_fee = 2 * static_cast<int64_t>((0.1 * (*cached_offer_obj.bid_price).amount.value)/2);
|
|
BOOST_CHECK_EQUAL(get_balance(alice_id(db), asset_id_type()(db)),
|
|
(alice_balance + cached_offer_obj.maximum_price.amount).value - partner_fee);
|
|
BOOST_CHECK_EQUAL(get_balance(mdowner_id(db), asset_id_type()(db)),
|
|
mdowner_balance + partner_fee);
|
|
const auto &oidx = db.get_index_type<offer_index>().indices().get<by_id>();
|
|
const auto &ohidx = db.get_index_type<offer_history_index>().indices().get<by_id>();
|
|
BOOST_REQUIRE(oidx.size() == 0);
|
|
BOOST_REQUIRE(ohidx.size() == 1);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)) == false);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)) == false);
|
|
BOOST_CHECK((nft_id_type(0)(db).owner == bob_id) && (nft_id_type(1)(db).owner == bob_id));
|
|
// Get offer history object
|
|
const auto &history_obj = offer_history_id_type(0)(db);
|
|
// History object data check
|
|
BOOST_CHECK(cached_offer_obj.bid_price == history_obj.bid_price);
|
|
BOOST_CHECK(cached_offer_obj.bidder == history_obj.bidder);
|
|
BOOST_CHECK(cached_offer_obj.buying_item == history_obj.buying_item);
|
|
BOOST_CHECK(cached_offer_obj.issuer == history_obj.issuer);
|
|
BOOST_CHECK(cached_offer_obj.maximum_price == history_obj.maximum_price);
|
|
BOOST_CHECK(cached_offer_obj.minimum_price == history_obj.minimum_price);
|
|
BOOST_CHECK(cached_offer_obj.offer_expiration_date == history_obj.offer_expiration_date);
|
|
BOOST_CHECK(cached_offer_obj.item_ids == history_obj.item_ids);
|
|
BOOST_CHECK(result_type::Expired == history_obj.result);
|
|
}
|
|
catch (fc::exception &e)
|
|
{
|
|
edump((e.to_detail_string()));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(expire_with_bid_for_sell_offer_test)
|
|
{
|
|
INVOKE(second_buy_bid_for_sell_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(charlie);
|
|
GET_ACTOR(mdowner);
|
|
int64_t alice_balance = get_balance(alice_id(db), asset_id_type()(db));
|
|
int64_t mdowner_balance = get_balance(mdowner_id(db), asset_id_type()(db));
|
|
const auto &offer_obj = sell_offer(db);
|
|
auto cached_offer_obj = offer_obj;
|
|
generate_blocks(5);
|
|
int64_t partner_fee = 2 * static_cast<int64_t>((0.1 * (*cached_offer_obj.bid_price).amount.value)/2);
|
|
BOOST_CHECK_EQUAL(get_balance(mdowner_id(db), asset_id_type()(db)),
|
|
mdowner_balance + partner_fee);
|
|
BOOST_CHECK_EQUAL(get_balance(alice_id(db), asset_id_type()(db)),
|
|
(alice_balance + (*cached_offer_obj.bid_price).amount).value - partner_fee);
|
|
const auto &oidx = db.get_index_type<offer_index>().indices().get<by_id>();
|
|
const auto &ohidx = db.get_index_type<offer_history_index>().indices().get<by_id>();
|
|
BOOST_REQUIRE(oidx.size() == 0);
|
|
BOOST_REQUIRE(ohidx.size() == 1);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)) == false);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)) == false);
|
|
BOOST_CHECK((nft_id_type(0)(db).owner == charlie_id) && (nft_id_type(1)(db).owner == charlie_id));
|
|
// Get offer history object
|
|
const auto &history_obj = offer_history_id_type(0)(db);
|
|
// History object data check
|
|
BOOST_CHECK(cached_offer_obj.bid_price == history_obj.bid_price);
|
|
BOOST_CHECK(cached_offer_obj.bidder == history_obj.bidder);
|
|
BOOST_CHECK(cached_offer_obj.buying_item == history_obj.buying_item);
|
|
BOOST_CHECK(cached_offer_obj.issuer == history_obj.issuer);
|
|
BOOST_CHECK(cached_offer_obj.maximum_price == history_obj.maximum_price);
|
|
BOOST_CHECK(cached_offer_obj.minimum_price == history_obj.minimum_price);
|
|
BOOST_CHECK(cached_offer_obj.offer_expiration_date == history_obj.offer_expiration_date);
|
|
BOOST_CHECK(cached_offer_obj.item_ids == history_obj.item_ids);
|
|
BOOST_CHECK(result_type::Expired == history_obj.result);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(expire_no_bid_for_sell_offer_test)
|
|
{
|
|
INVOKE(create_sell_offer_test);
|
|
GET_ACTOR(alice);
|
|
int64_t alice_balance = get_balance(alice_id(db), asset_id_type()(db));
|
|
const auto &offer_obj = sell_offer(db);
|
|
auto cached_offer_obj = offer_obj;
|
|
generate_blocks(5);
|
|
BOOST_CHECK_EQUAL(get_balance(alice_id(db), asset_id_type()(db)),
|
|
alice_balance);
|
|
const auto &oidx = db.get_index_type<offer_index>().indices().get<by_id>();
|
|
const auto &ohidx = db.get_index_type<offer_history_index>().indices().get<by_id>();
|
|
BOOST_REQUIRE(oidx.size() == 0);
|
|
BOOST_REQUIRE(ohidx.size() == 1);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)) == false);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)) == false);
|
|
BOOST_CHECK((nft_id_type(0)(db).owner == alice_id) && (nft_id_type(1)(db).owner == alice_id));
|
|
// Get offer history object
|
|
const auto &history_obj = offer_history_id_type(0)(db);
|
|
// History object data check
|
|
BOOST_CHECK(cached_offer_obj.bid_price == history_obj.bid_price);
|
|
BOOST_CHECK(cached_offer_obj.bidder == history_obj.bidder);
|
|
BOOST_CHECK(cached_offer_obj.buying_item == history_obj.buying_item);
|
|
BOOST_CHECK(cached_offer_obj.issuer == history_obj.issuer);
|
|
BOOST_CHECK(cached_offer_obj.maximum_price == history_obj.maximum_price);
|
|
BOOST_CHECK(cached_offer_obj.minimum_price == history_obj.minimum_price);
|
|
BOOST_CHECK(cached_offer_obj.offer_expiration_date == history_obj.offer_expiration_date);
|
|
BOOST_CHECK(cached_offer_obj.item_ids == history_obj.item_ids);
|
|
BOOST_CHECK(result_type::ExpiredNoBid == history_obj.result);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(create_buy_offer_test)
|
|
{
|
|
try
|
|
{
|
|
INVOKE(best_buy_bid_for_sell_offer);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(operator1);
|
|
GET_ACTOR(operator2);
|
|
{
|
|
int64_t alice_balance = get_balance(alice_id(db), asset_id_type()(db));
|
|
offer_operation offer_op;
|
|
offer_op.item_ids.emplace(nft_id_type(0));
|
|
offer_op.item_ids.emplace(nft_id_type(1));
|
|
offer_op.issuer = alice_id;
|
|
offer_op.buying_item = true;
|
|
offer_op.maximum_price = asset(11000);
|
|
offer_op.minimum_price = asset(10);
|
|
offer_op.offer_expiration_date = db.head_block_time() + fc::seconds(15);
|
|
trx.operations.push_back(offer_op);
|
|
auto op = trx.operations.back().get<offer_operation>();
|
|
REQUIRE_THROW_WITH_VALUE(op, issuer, bob_id);
|
|
|
|
trx.clear();
|
|
trx.operations.push_back(offer_op);
|
|
sign(trx, alice_private_key);
|
|
PUSH_TX(db, trx);
|
|
trx.clear();
|
|
|
|
asset exp_delta_bidder2 = -offer_op.maximum_price;
|
|
BOOST_CHECK_EQUAL(get_balance(alice_id(db), asset_id_type()(db)),
|
|
(alice_balance + exp_delta_bidder2.amount).value);
|
|
|
|
const auto &idx = db.get_index_type<offer_index>().indices().get<by_id>();
|
|
BOOST_REQUIRE(idx.size() == 1);
|
|
const offer_object &d = offer_id_type(1)(db);
|
|
|
|
BOOST_CHECK(d.space_id == protocol_ids);
|
|
BOOST_CHECK(d.type_id == offer_object_type);
|
|
// empty bid
|
|
BOOST_CHECK(!d.bid_price);
|
|
BOOST_CHECK(!d.bidder);
|
|
// data integrity
|
|
BOOST_CHECK(d.issuer == alice_id);
|
|
BOOST_CHECK(d.maximum_price == asset(11000));
|
|
BOOST_CHECK(d.minimum_price == asset(10));
|
|
BOOST_CHECK(d.buying_item == true);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)) == false);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)) == false);
|
|
buy_offer = d.id;
|
|
}
|
|
}
|
|
catch (fc::exception &e)
|
|
{
|
|
edump((e.to_detail_string()));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(sell_bid_for_buy_offer_test)
|
|
{
|
|
try
|
|
{
|
|
INVOKE(create_buy_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(operator1);
|
|
|
|
const auto &offer_obj = buy_offer(db);
|
|
|
|
bid_operation bid_op;
|
|
bid_op.offer_id = offer_obj.id;
|
|
bid_op.bid_price = asset(offer_obj.minimum_price.amount + 2, offer_obj.minimum_price.asset_id);
|
|
bid_op.bidder = bob_id;
|
|
trx.operations.push_back(bid_op);
|
|
|
|
auto op = trx.operations.back().get<bid_operation>();
|
|
// Non Owner bidder
|
|
REQUIRE_THROW_WITH_VALUE(op, bidder, alice_id);
|
|
|
|
trx.clear();
|
|
trx.operations.push_back(bid_op);
|
|
sign(trx, bob_private_key);
|
|
PUSH_TX(db, trx);
|
|
trx.clear();
|
|
|
|
//not empty bid
|
|
BOOST_CHECK(offer_obj.bid_price);
|
|
BOOST_CHECK(offer_obj.bidder);
|
|
// data integrity
|
|
BOOST_CHECK(offer_obj.bidder == bob_id);
|
|
BOOST_CHECK(offer_obj.issuer == alice_id);
|
|
BOOST_CHECK(offer_obj.maximum_price == asset(11000));
|
|
BOOST_CHECK(offer_obj.minimum_price == asset(10));
|
|
BOOST_CHECK(offer_obj.bid_price == bid_op.bid_price);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)));
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)));
|
|
}
|
|
catch (fc::exception &e)
|
|
{
|
|
edump((e.to_detail_string()));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(second_sell_bid_for_buy_offer_test)
|
|
{
|
|
try
|
|
{
|
|
INVOKE(sell_bid_for_buy_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(charlie);
|
|
GET_ACTOR(operator1);
|
|
|
|
const auto &offer_obj = buy_offer(db);
|
|
|
|
bid_operation bid_op;
|
|
bid_op.offer_id = offer_obj.id;
|
|
bid_op.bid_price = asset((*offer_obj.bid_price).amount - 1, offer_obj.minimum_price.asset_id);
|
|
bid_op.bidder = bob_id;
|
|
trx.operations.push_back(bid_op);
|
|
|
|
auto op = trx.operations.back().get<bid_operation>();
|
|
// Not a better bid than previous
|
|
REQUIRE_THROW_WITH_VALUE(op, bid_price, asset((*offer_obj.bid_price).amount, offer_obj.minimum_price.asset_id));
|
|
|
|
trx.clear();
|
|
trx.operations.push_back(bid_op);
|
|
sign(trx, bob_private_key);
|
|
PUSH_TX(db, trx);
|
|
trx.clear();
|
|
|
|
//not empty bid
|
|
BOOST_CHECK(offer_obj.bid_price);
|
|
BOOST_CHECK(offer_obj.bidder);
|
|
|
|
// data integrity
|
|
BOOST_CHECK(offer_obj.bidder == bob_id);
|
|
BOOST_CHECK(offer_obj.issuer == alice_id);
|
|
BOOST_CHECK(offer_obj.maximum_price == asset(11000));
|
|
BOOST_CHECK(offer_obj.minimum_price == asset(10));
|
|
BOOST_CHECK(offer_obj.bid_price == bid_op.bid_price);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)));
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)));
|
|
}
|
|
catch (fc::exception &e)
|
|
{
|
|
edump((e.to_detail_string()));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(best_sell_bid_for_buy_offer)
|
|
{
|
|
try
|
|
{
|
|
INVOKE(second_sell_bid_for_buy_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(mdowner);
|
|
|
|
int64_t bob_balance = get_balance(bob_id(db), asset_id_type()(db));
|
|
int64_t alice_balance = get_balance(alice_id(db), asset_id_type()(db));
|
|
int64_t mdowner_balance = get_balance(mdowner_id(db), asset_id_type()(db));
|
|
const auto &offer_obj = buy_offer(db);
|
|
|
|
bid_operation bid_op;
|
|
bid_op.offer_id = offer_obj.id;
|
|
bid_op.bid_price = asset(offer_obj.minimum_price.amount, offer_obj.minimum_price.asset_id);
|
|
bid_op.bidder = bob_id;
|
|
|
|
asset bid = bid_op.bid_price;
|
|
asset exp_delta_bidder1 = offer_obj.minimum_price;
|
|
asset exp_delta_bidder2 = offer_obj.maximum_price - offer_obj.minimum_price;
|
|
|
|
trx.operations.push_back(bid_op);
|
|
sign(trx, bob_private_key);
|
|
PUSH_TX(db, trx);
|
|
trx.clear();
|
|
|
|
//not empty bid
|
|
BOOST_CHECK(offer_obj.bid_price);
|
|
BOOST_CHECK(offer_obj.bidder);
|
|
// data integrity
|
|
BOOST_CHECK(offer_obj.bidder == bob_id);
|
|
BOOST_CHECK(offer_obj.issuer == alice_id);
|
|
BOOST_CHECK(offer_obj.maximum_price == asset(11000));
|
|
BOOST_CHECK(offer_obj.minimum_price == asset(10));
|
|
BOOST_CHECK(offer_obj.bid_price == bid);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)));
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)));
|
|
auto cached_offer_obj = offer_obj;
|
|
// Generate a block and offer should be finalized with bid
|
|
generate_block();
|
|
// Check balances
|
|
int64_t partner_fee = 2 * static_cast<int64_t>((0.1 * (*cached_offer_obj.bid_price).amount.value)/2);
|
|
BOOST_CHECK_EQUAL(get_balance(mdowner_id(db), asset_id_type()(db)),
|
|
mdowner_balance + partner_fee);
|
|
BOOST_CHECK_EQUAL(get_balance(bob_id(db), asset_id_type()(db)),
|
|
(bob_balance + exp_delta_bidder1.amount).value - partner_fee);
|
|
BOOST_CHECK_EQUAL(get_balance(alice_id(db), asset_id_type()(db)),
|
|
(alice_balance + exp_delta_bidder2.amount).value);
|
|
const auto &oidx = db.get_index_type<offer_index>().indices().get<by_id>();
|
|
const auto &ohidx = db.get_index_type<offer_history_index>().indices().get<by_id>();
|
|
BOOST_REQUIRE(oidx.size() == 0);
|
|
BOOST_REQUIRE(ohidx.size() == 2);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)) == false);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)) == false);
|
|
BOOST_CHECK((nft_id_type(0)(db).owner == alice_id) && (nft_id_type(1)(db).owner == alice_id));
|
|
// Get offer history object
|
|
const auto &history_obj = offer_history_id_type(1)(db);
|
|
// History object data check
|
|
BOOST_CHECK(cached_offer_obj.bid_price == history_obj.bid_price);
|
|
BOOST_CHECK(cached_offer_obj.bidder == history_obj.bidder);
|
|
BOOST_CHECK(cached_offer_obj.buying_item == history_obj.buying_item);
|
|
BOOST_CHECK(cached_offer_obj.issuer == history_obj.issuer);
|
|
BOOST_CHECK(cached_offer_obj.maximum_price == history_obj.maximum_price);
|
|
BOOST_CHECK(cached_offer_obj.minimum_price == history_obj.minimum_price);
|
|
BOOST_CHECK(cached_offer_obj.offer_expiration_date == history_obj.offer_expiration_date);
|
|
BOOST_CHECK(cached_offer_obj.item_ids == history_obj.item_ids);
|
|
BOOST_CHECK(result_type::Expired == history_obj.result);
|
|
}
|
|
catch (fc::exception &e)
|
|
{
|
|
edump((e.to_detail_string()));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(expire_with_bid_for_buy_offer_test)
|
|
{
|
|
INVOKE(second_sell_bid_for_buy_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(mdowner);
|
|
int64_t alice_balance = get_balance(alice_id(db), asset_id_type()(db));
|
|
int64_t bob_balance = get_balance(bob_id(db), asset_id_type()(db));
|
|
int64_t mdowner_balance = get_balance(mdowner_id(db), asset_id_type()(db));
|
|
const auto &offer_obj = buy_offer(db);
|
|
auto cached_offer_obj = offer_obj;
|
|
generate_blocks(5);
|
|
int64_t partner_fee = 2 * static_cast<int64_t>((0.1 * (*cached_offer_obj.bid_price).amount.value)/2);
|
|
BOOST_CHECK_EQUAL(get_balance(mdowner_id(db), asset_id_type()(db)),
|
|
mdowner_balance + partner_fee);
|
|
BOOST_CHECK_EQUAL(get_balance(alice_id(db), asset_id_type()(db)),
|
|
(alice_balance + cached_offer_obj.maximum_price.amount - (*cached_offer_obj.bid_price).amount).value);
|
|
BOOST_CHECK_EQUAL(get_balance(bob_id(db), asset_id_type()(db)),
|
|
(bob_balance + (*cached_offer_obj.bid_price).amount).value - partner_fee);
|
|
const auto &oidx = db.get_index_type<offer_index>().indices().get<by_id>();
|
|
const auto &ohidx = db.get_index_type<offer_history_index>().indices().get<by_id>();
|
|
BOOST_REQUIRE(oidx.size() == 0);
|
|
BOOST_REQUIRE(ohidx.size() == 2);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)) == false);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)) == false);
|
|
BOOST_CHECK((nft_id_type(0)(db).owner == alice_id) && (nft_id_type(1)(db).owner == alice_id));
|
|
// Get offer history object
|
|
const auto &history_obj = offer_history_id_type(1)(db);
|
|
// History object data check
|
|
BOOST_CHECK(cached_offer_obj.bid_price == history_obj.bid_price);
|
|
BOOST_CHECK(cached_offer_obj.bidder == history_obj.bidder);
|
|
BOOST_CHECK(cached_offer_obj.buying_item == history_obj.buying_item);
|
|
BOOST_CHECK(cached_offer_obj.issuer == history_obj.issuer);
|
|
BOOST_CHECK(cached_offer_obj.maximum_price == history_obj.maximum_price);
|
|
BOOST_CHECK(cached_offer_obj.minimum_price == history_obj.minimum_price);
|
|
BOOST_CHECK(cached_offer_obj.offer_expiration_date == history_obj.offer_expiration_date);
|
|
BOOST_CHECK(cached_offer_obj.item_ids == history_obj.item_ids);
|
|
BOOST_CHECK(result_type::Expired == history_obj.result);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(expire_no_bid_for_buy_offer_test)
|
|
{
|
|
INVOKE(create_buy_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
int64_t alice_balance = get_balance(alice_id(db), asset_id_type()(db));
|
|
const auto &offer_obj = buy_offer(db);
|
|
auto cached_offer_obj = offer_obj;
|
|
generate_blocks(5);
|
|
BOOST_CHECK_EQUAL(get_balance(alice_id(db), asset_id_type()(db)),
|
|
(alice_balance + cached_offer_obj.maximum_price.amount).value);
|
|
const auto &oidx = db.get_index_type<offer_index>().indices().get<by_id>();
|
|
const auto &ohidx = db.get_index_type<offer_history_index>().indices().get<by_id>();
|
|
BOOST_REQUIRE(oidx.size() == 0);
|
|
BOOST_REQUIRE(ohidx.size() == 2);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)) == false);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)) == false);
|
|
BOOST_CHECK((nft_id_type(0)(db).owner == bob_id) && (nft_id_type(1)(db).owner == bob_id));
|
|
// Get offer history object
|
|
const auto &history_obj = offer_history_id_type(1)(db);
|
|
// History object data check
|
|
BOOST_CHECK(cached_offer_obj.bid_price == history_obj.bid_price);
|
|
BOOST_CHECK(cached_offer_obj.bidder == history_obj.bidder);
|
|
BOOST_CHECK(cached_offer_obj.buying_item == history_obj.buying_item);
|
|
BOOST_CHECK(cached_offer_obj.issuer == history_obj.issuer);
|
|
BOOST_CHECK(cached_offer_obj.maximum_price == history_obj.maximum_price);
|
|
BOOST_CHECK(cached_offer_obj.minimum_price == history_obj.minimum_price);
|
|
BOOST_CHECK(cached_offer_obj.offer_expiration_date == history_obj.offer_expiration_date);
|
|
BOOST_CHECK(cached_offer_obj.item_ids == history_obj.item_ids);
|
|
BOOST_CHECK(result_type::ExpiredNoBid == history_obj.result);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(cancel_sell_offer_no_bid_test)
|
|
{
|
|
try
|
|
{
|
|
INVOKE(create_sell_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(operator1);
|
|
|
|
const auto &offer_obj = sell_offer(db);
|
|
auto cached_offer_obj = offer_obj;
|
|
|
|
cancel_offer_operation cancel_op;
|
|
cancel_op.offer_id = offer_obj.id;
|
|
// Add non-issuer
|
|
cancel_op.issuer = bob_id;
|
|
trx.clear();
|
|
trx.operations.push_back(cancel_op);
|
|
sign(trx, bob_private_key);
|
|
BOOST_CHECK_THROW(PUSH_TX(db, trx), fc::exception);
|
|
trx.clear();
|
|
// Add issuer
|
|
cancel_op.issuer = alice_id;
|
|
trx.operations.push_back(cancel_op);
|
|
sign(trx, alice_private_key);
|
|
PUSH_TX(db, trx);
|
|
|
|
const auto &oidx = db.get_index_type<offer_index>().indices().get<by_id>();
|
|
const auto &ohidx = db.get_index_type<offer_history_index>().indices().get<by_id>();
|
|
BOOST_REQUIRE(oidx.size() == 0);
|
|
BOOST_REQUIRE(ohidx.size() == 1);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)) == false);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)) == false);
|
|
// Get offer history object
|
|
const auto &history_obj = offer_history_id_type(0)(db);
|
|
// History object data check
|
|
BOOST_CHECK(cached_offer_obj.bid_price == history_obj.bid_price);
|
|
BOOST_CHECK(cached_offer_obj.bidder == history_obj.bidder);
|
|
BOOST_CHECK(cached_offer_obj.buying_item == history_obj.buying_item);
|
|
BOOST_CHECK(cached_offer_obj.issuer == history_obj.issuer);
|
|
BOOST_CHECK(cached_offer_obj.maximum_price == history_obj.maximum_price);
|
|
BOOST_CHECK(cached_offer_obj.minimum_price == history_obj.minimum_price);
|
|
BOOST_CHECK(cached_offer_obj.offer_expiration_date == history_obj.offer_expiration_date);
|
|
BOOST_CHECK(cached_offer_obj.item_ids == history_obj.item_ids);
|
|
BOOST_CHECK(result_type::Cancelled == history_obj.result);
|
|
|
|
}
|
|
catch (fc::exception &e)
|
|
{
|
|
edump((e.to_detail_string()));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(cancel_sell_offer_with_bid_test)
|
|
{
|
|
try
|
|
{
|
|
INVOKE(buy_bid_for_sell_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(operator1);
|
|
|
|
const auto &offer_obj = sell_offer(db);
|
|
auto cached_offer_obj = offer_obj;
|
|
int64_t bob_balance = get_balance(bob_id(db), asset_id_type()(db));
|
|
|
|
cancel_offer_operation cancel_op;
|
|
cancel_op.offer_id = offer_obj.id;
|
|
// Add issuer
|
|
cancel_op.issuer = alice_id;
|
|
trx.clear();
|
|
trx.operations.push_back(cancel_op);
|
|
sign(trx, alice_private_key);
|
|
PUSH_TX(db, trx);
|
|
|
|
const auto &oidx = db.get_index_type<offer_index>().indices().get<by_id>();
|
|
const auto &ohidx = db.get_index_type<offer_history_index>().indices().get<by_id>();
|
|
BOOST_REQUIRE(oidx.size() == 0);
|
|
BOOST_REQUIRE(ohidx.size() == 1);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)) == false);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)) == false);
|
|
BOOST_CHECK_EQUAL(get_balance(bob_id(db), asset_id_type()(db)),
|
|
(bob_balance + (*cached_offer_obj.bid_price).amount).value);
|
|
// Get offer history object
|
|
const auto &history_obj = offer_history_id_type(0)(db);
|
|
// History object data check
|
|
BOOST_CHECK(cached_offer_obj.bid_price == history_obj.bid_price);
|
|
BOOST_CHECK(cached_offer_obj.bidder == history_obj.bidder);
|
|
BOOST_CHECK(cached_offer_obj.buying_item == history_obj.buying_item);
|
|
BOOST_CHECK(cached_offer_obj.issuer == history_obj.issuer);
|
|
BOOST_CHECK(cached_offer_obj.maximum_price == history_obj.maximum_price);
|
|
BOOST_CHECK(cached_offer_obj.minimum_price == history_obj.minimum_price);
|
|
BOOST_CHECK(cached_offer_obj.offer_expiration_date == history_obj.offer_expiration_date);
|
|
BOOST_CHECK(cached_offer_obj.item_ids == history_obj.item_ids);
|
|
BOOST_CHECK(result_type::Cancelled == history_obj.result);
|
|
|
|
}
|
|
catch (fc::exception &e)
|
|
{
|
|
edump((e.to_detail_string()));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(cancel_buy_offer_with_bid_test)
|
|
{
|
|
try
|
|
{
|
|
INVOKE(sell_bid_for_buy_offer_test);
|
|
GET_ACTOR(alice);
|
|
GET_ACTOR(bob);
|
|
GET_ACTOR(operator1);
|
|
|
|
const auto &offer_obj = buy_offer(db);
|
|
auto cached_offer_obj = offer_obj;
|
|
int64_t alice_balance = get_balance(alice_id(db), asset_id_type()(db));
|
|
|
|
cancel_offer_operation cancel_op;
|
|
cancel_op.offer_id = offer_obj.id;
|
|
cancel_op.issuer = alice_id;
|
|
|
|
trx.clear();
|
|
trx.operations.push_back(cancel_op);
|
|
sign(trx, alice_private_key);
|
|
PUSH_TX(db, trx);
|
|
trx.clear();
|
|
|
|
generate_block();
|
|
|
|
const auto &oidx = db.get_index_type<offer_index>().indices().get<by_id>();
|
|
const auto &ohidx = db.get_index_type<offer_history_index>().indices().get<by_id>();
|
|
BOOST_REQUIRE(oidx.size() == 0);
|
|
BOOST_REQUIRE(ohidx.size() == 2);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(0)) == false);
|
|
BOOST_CHECK(db.item_locked(nft_id_type(1)) == false);
|
|
BOOST_CHECK_EQUAL(get_balance(alice_id(db), asset_id_type()(db)),
|
|
(alice_balance + cached_offer_obj.maximum_price.amount).value);
|
|
// Get offer history object
|
|
const auto &history_obj = offer_history_id_type(1)(db);
|
|
// History object data check
|
|
BOOST_CHECK(cached_offer_obj.bid_price == history_obj.bid_price);
|
|
BOOST_CHECK(cached_offer_obj.bidder == history_obj.bidder);
|
|
BOOST_CHECK(cached_offer_obj.buying_item == history_obj.buying_item);
|
|
BOOST_CHECK(cached_offer_obj.issuer == history_obj.issuer);
|
|
BOOST_CHECK(cached_offer_obj.maximum_price == history_obj.maximum_price);
|
|
BOOST_CHECK(cached_offer_obj.minimum_price == history_obj.minimum_price);
|
|
BOOST_CHECK(cached_offer_obj.offer_expiration_date == history_obj.offer_expiration_date);
|
|
BOOST_CHECK(cached_offer_obj.item_ids == history_obj.item_ids);
|
|
BOOST_CHECK(result_type::Cancelled == history_obj.result);
|
|
|
|
}
|
|
catch (fc::exception &e)
|
|
{
|
|
edump((e.to_detail_string()));
|
|
throw;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|