This commit is contained in:
Denis Angell
2023-02-03 04:11:09 -05:00
committed by Richard Holland
parent 56d062f907
commit c848fe91d6

View File

@@ -66,12 +66,81 @@ struct URIToken_test : public beast::unit_test::suite
}
static bool
uritExists(ReadView const& view, uint256 const& id)
uritokenExists(ReadView const& view, uint256 const& id)
{
auto const slep = view.read({ltURI_TOKEN, id});
return bool(slep);
}
void
debugBalance(
jtx::Env const& env,
std::string const& name,
jtx::Account const& account,
jtx::IOU const& iou)
{
// debugBalance(env, "alice", alice, USD);
std::cout << name << " BALANCE XRP: " << env.balance(account) << "\n";
std::cout << name << " BALANCE USD: " << env.balance(account, iou.issue()) << "\n";
}
void
debugToken(
ReadView const& view,
std::string const& name,
jtx::Account const& account,
uint256 const& id)
{
// debugToken(*env.current(), "token", alice, tid);
auto const slep = view.read({ltURI_TOKEN, id});
if (!slep)
return;
std::cout << name << " sfOwner: " << slep->getAccountID(sfOwner) << "\n";
std::cout << name << " sfIssuer: " << slep->getAccountID(sfIssuer) << "\n";
// std::cout << name << " sfURI: " << slep->getFieldVL(sfURI) << "\n";
// std::cout << name << " sfDigest: " << (*slep)[sfDigest] << "\n";
if (slep->getFieldAmount(sfAmount))
std::cout << name << " sfAmount: " << slep->getFieldAmount(sfAmount) << "\n";
if (slep->getFieldAmount(sfAmount))
std::cout << name << " sfDestination: " << slep->getAccountID(sfDestination) << "\n";
}
static AccountID
tokenOwner(ReadView const& view, uint256 const& id)
{
auto const slep = view.read({ltURI_TOKEN, id});
if (!slep)
return AccountID();
return slep->getAccountID(sfOwner);
}
static STAmount
tokenAmount(ReadView const& view, uint256 const& id)
{
auto const slep = view.read({ltURI_TOKEN, id});
if (!slep)
return XRPAmount{-1};
if (slep->getFieldAmount(sfAmount))
return (*slep)[sfAmount];
return XRPAmount{-1};
}
// void
// debugOwnerDir(
// jtx::Env const& env,
// std::string const& name,
// jtx::Account const& account,
// std::string const& uri)
// {
// auto const [urit, uritSle] = uriTokenKeyAndSle(env.current(), account, uri);
// std::cout << "URIT: " << urit << "\n";
// std::cout << name << "IN OWNER DIR: " << inOwnerDir(env.current(), account, uritSle) << "\n";
// std::cout << name << "DIR: " << ownerDirCount(env.current(), account) << "\n";
// }
static Json::Value
mint(
jtx::Account const& account,
@@ -141,30 +210,6 @@ struct URIToken_test : public beast::unit_test::suite
return jv;
}
void
debugBalance(
jtx::Env const& env,
std::string const& name,
jtx::Account const& account,
jtx::IOU const& iou)
{
std::cout << name << " BALANCE XRP: " << env.balance(account) << "\n";
std::cout << name << " BALANCE USD: " << env.balance(account, iou.issue()) << "\n";
}
// void
// debugOwnerDir(
// jtx::Env const& env,
// std::string const& name,
// jtx::Account const& account,
// std::string const& uri)
// {
// auto const [urit, uritSle] = uriTokenKeyAndSle(env.current(), account, uri);
// std::cout << "URIT: " << urit << "\n";
// std::cout << name << "IN OWNER DIR: " << inOwnerDir(env.current(), account, uritSle) << "\n";
// std::cout << name << "DIR: " << ownerDirCount(env.current(), account) << "\n";
// }
void
testEnabled(FeatureBitset features)
{
@@ -637,6 +682,508 @@ struct URIToken_test : public beast::unit_test::suite
env.close();
}
void
testMintValid(FeatureBitset features)
{
testcase("mint");
using namespace jtx;
using namespace std::literals::chrono_literals;
auto const alice = Account("alice");
auto const bob = Account("bob");
// setup env
Env env{*this, features};
env.fund(XRP(1000), alice, bob);
std::string const uri(maxTokenURILength, '?');
std::string const id{strHex(tokenid(alice, uri))};
auto const digestval = "C16E7263F07AA41261DCC955660AF4646ADBA414E37B6F5A5BA50F75153F5CCC";
// 0b110000001U: has digest - has uri - no flags
{
// mint
env(mint(alice, uri), json(sfDigest.fieldName, digestval));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(alice, uri)));
// cleanup
env(burn(alice, id), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tokenid(alice, uri)));
}
// 0b110000010U: has digest - has uri - burnable flag
{
// mint
env(mint(alice, uri), txflags(tfBurnable), json(sfDigest.fieldName, digestval));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(alice, uri)));
// cleanup
env(burn(alice, id), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tokenid(alice, uri)));
}
// 0b010000001U: has uri - no flags
{
// mint
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(alice, uri)));
// cleanup
env(burn(alice, id), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tokenid(alice, uri)));
}
// 0b010000010U: has uri - burnable flag
{
// mint
env(mint(alice, uri), txflags(tfBurnable));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(alice, uri)));
// cleanup
env(burn(alice, id), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tokenid(alice, uri)));
}
}
void
testBurnValid(FeatureBitset features)
{
testcase("burn");
using namespace jtx;
using namespace std::literals::chrono_literals;
auto const alice = Account("alice");
auto const bob = Account("bob");
// setup env
Env env{*this, features};
env.fund(XRP(1000), alice, bob);
std::string const uri(maxTokenURILength, '?');
std::string const id{strHex(tokenid(alice, uri))};
// issuer can burn
{
// alice mints
env(mint(alice, uri), txflags(tfBurnable));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(alice, uri)));
// alice sells
env(sell(alice, id, XRP(1)), txflags(tfSell));
env.close();
// bob buys
env(buy(bob, id, XRP(1)));
env.close();
// alice burns
env(burn(alice, id), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tokenid(alice, uri)));
BEAST_EXPECT(!uritokenExists(*env.current(), tokenid(bob, uri)));
}
// issuer cannot burn
{
// alice mints
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(alice, uri)));
// alice sells
env(sell(alice, id, XRP(1)), txflags(tfSell));
env.close();
// bob buys
env(buy(bob, id, XRP(1)));
env.close();
// alice tries to burn
env(burn(alice, id), txflags(tfBurn), ter(tecNO_PERMISSION));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tokenid(alice, uri)));
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(bob, uri)));
// burn for test reset
env(burn(bob, id), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tokenid(bob, uri)));
}
// owner can burn
{
// alice mints
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(alice, uri)));
// alice sells
env(sell(alice, id, XRP(1)), txflags(tfSell));
env.close();
// bob buys
env(buy(bob, id, XRP(1)));
env.close();
// bob burns
env(burn(bob, id), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tokenid(alice, uri)));
BEAST_EXPECT(!uritokenExists(*env.current(), tokenid(bob, uri)));
}
}
void
testBuyValid(FeatureBitset features)
{
testcase("buy");
using namespace jtx;
using namespace std::literals::chrono_literals;
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const gw = Account("gw");
auto const USD = gw["USD"];
// setup env
Env env{*this, features};
env.fund(XRP(1000), alice, bob, gw);
env.trust(USD(10000), alice);
env.trust(USD(10000), bob);
env.close();
env(pay(gw, alice, USD(1000)));
env(pay(gw, bob, USD(1000)));
env.close();
auto const feeDrops = env.current()->fees().base;
std::string const uri(maxTokenURILength, '?');
auto const tid = tokenid(alice, uri);
std::string const hexid{strHex(tid)};
// bob can buy with XRP
{
// alice mints
const auto delta = XRP(10);
auto preAlice = env.balance(alice);
auto preBob = env.balance(bob);
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tid));
BEAST_EXPECT(env.balance(alice) == preAlice - (1 * feeDrops));
// alice sells
env(sell(alice, hexid, delta), txflags(tfSell));
BEAST_EXPECT(env.balance(alice) == preAlice - (2 * feeDrops));
env.close();
// bob buys
env(buy(bob, hexid, delta));
env.close();
auto const [urit, uritSle] = uriTokenKeyAndSle(*env.current(), alice, uri);
BEAST_EXPECT(uritokenExists(*env.current(), urit));
BEAST_EXPECT(env.balance(alice) == preAlice + delta - (2 * feeDrops));
BEAST_EXPECT(env.balance(bob) == preBob - delta - feeDrops);
BEAST_EXPECT(bob.id() == tokenOwner(*env.current(), tid));
// bob burns to reset tests
env(burn(bob, hexid), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), urit));
}
// bob can buy with USD
{
// alice mints
const auto delta = USD(10);
auto preAlice = env.balance(alice, USD.issue());
auto preAliceXrp = env.balance(alice);
auto preBob = env.balance(bob, USD.issue());
auto preBobXrp = env.balance(bob);
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tid));
BEAST_EXPECT(env.balance(alice) == preAliceXrp - (1 * feeDrops));
// alice sells
env(sell(alice, hexid, delta), txflags(tfSell));
BEAST_EXPECT(env.balance(alice) == preAliceXrp - (2 * feeDrops));
BEAST_EXPECT(env.balance(alice, USD.issue()) == preAlice);
env.close();
// bob buys
env(buy(bob, hexid, delta));
env.close();
auto const [urit, uritSle] = uriTokenKeyAndSle(*env.current(), alice, uri);
BEAST_EXPECT(uritokenExists(*env.current(), urit));
BEAST_EXPECT(env.balance(alice, USD.issue()) == preAlice + delta);
BEAST_EXPECT(env.balance(alice) == preAliceXrp - (2 * feeDrops));
BEAST_EXPECT(env.balance(bob, USD.issue()) == preBob - delta);
BEAST_EXPECT(env.balance(bob) == preBobXrp - (1 * feeDrops));
BEAST_EXPECT(bob.id() == tokenOwner(*env.current(), tid));
// bob burns to reset tests
env(burn(bob, hexid), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), urit));
}
}
void
testSellValid(FeatureBitset features)
{
testcase("sell");
using namespace jtx;
using namespace std::literals::chrono_literals;
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const carol = Account("carol");
auto const gw = Account("gw");
auto const USD = gw["USD"];
// setup env
Env env{*this, features};
env.fund(XRP(1000), alice, bob, carol, gw);
env.trust(USD(10000), alice);
env.trust(USD(10000), bob);
env.trust(USD(10000), carol);
env.close();
env(pay(gw, alice, USD(1000)));
env(pay(gw, bob, USD(1000)));
env(pay(gw, carol, USD(1000)));
env.close();
auto const feeDrops = env.current()->fees().base;
std::string const uri(maxTokenURILength, '?');
auto const tid = tokenid(alice, uri);
std::string const hexid{strHex(tid)};
// alice can sell with XRP
{
// alice mints
const auto delta = XRP(10);
auto preAlice = env.balance(alice);
auto preBob = env.balance(bob);
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tid));
// alice sells
env(sell(alice, hexid, delta), txflags(tfSell));
env.close();
BEAST_EXPECT(delta == tokenAmount(*env.current(), tid));
// alice clears and sells again at a higher price
env(clear(alice, hexid));
BEAST_EXPECT(XRPAmount{-1} == tokenAmount(*env.current(), tid));
env(sell(alice, hexid, XRP(11)), txflags(tfSell));
env.close();
BEAST_EXPECT(XRP(11) == tokenAmount(*env.current(), tid));
// bob tries to buy at original price and fails
env(buy(bob, hexid, delta), ter(tecINSUFFICIENT_PAYMENT));
// bob buys at higher price
env(buy(bob, hexid, XRP(11)));
env.close();
auto const [urit, uritSle] = uriTokenKeyAndSle(*env.current(), alice, uri);
BEAST_EXPECT(uritokenExists(*env.current(), urit));
BEAST_EXPECT(env.balance(alice) == preAlice + XRP(11) - (4 * feeDrops));
BEAST_EXPECT(env.balance(bob) == preBob - XRP(11) - (2 * feeDrops));
BEAST_EXPECT(bob.id() == tokenOwner(*env.current(), tid));
debugToken(*env.current(), "token", alice, tid);
debugBalance(env, "alice", alice, USD);
debugBalance(env, "bob", bob, USD);
// bob burns to reset tests
env(burn(bob, hexid), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tid));
}
// alice can sell with XRP and dest
{
// alice mints
const auto delta = XRP(10);
auto preAlice = env.balance(alice);
auto preBob = env.balance(bob);
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tid));
// alice sells
env(sell(alice, hexid, delta), txflags(tfSell), jtx::token::destination(bob));
env.close();
BEAST_EXPECT(delta == tokenAmount(*env.current(), tid));
// carol tries to buy but cannot
env(buy(carol, hexid, delta), ter(tecNO_PERMISSION));
env.close();
// bob buys
env(buy(bob, hexid, delta));
env.close();
auto const [urit, uritSle] = uriTokenKeyAndSle(*env.current(), alice, uri);
BEAST_EXPECT(uritokenExists(*env.current(), urit));
BEAST_EXPECT(env.balance(alice) == preAlice + delta- (2 * feeDrops));
BEAST_EXPECT(env.balance(bob) == preBob - delta - (1 * feeDrops));
BEAST_EXPECT(bob.id() == tokenOwner(*env.current(), tid));
// bob burns to reset tests
env(burn(bob, hexid), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tid));
}
// alice can sell with USD
{
// alice mints
const auto delta = USD(10);
auto preAlice = env.balance(alice, USD.issue());
auto preAliceXrp = env.balance(alice);
auto preBob = env.balance(bob, USD.issue());
auto preBobXrp = env.balance(bob);
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tid));
// alice sells
env(sell(alice, hexid, delta), txflags(tfSell));
env.close();
BEAST_EXPECT(delta == tokenAmount(*env.current(), tid));
// alice clears and sells again at a higher price
env(clear(alice, hexid));
BEAST_EXPECT(XRPAmount{-1} == tokenAmount(*env.current(), tid));
env(sell(alice, hexid, USD(11)), txflags(tfSell));
env.close();
BEAST_EXPECT(USD(11) == tokenAmount(*env.current(), tid));
// bob tries to buy at original price and fails
env(buy(bob, hexid, delta), ter(tecINSUFFICIENT_PAYMENT));
// bob buys at higher price
env(buy(bob, hexid, USD(11)));
env.close();
auto const [urit, uritSle] = uriTokenKeyAndSle(*env.current(), alice, uri);
BEAST_EXPECT(uritokenExists(*env.current(), urit));
BEAST_EXPECT(env.balance(alice, USD.issue()) == preAlice + USD(11) );
BEAST_EXPECT(env.balance(alice) == preAliceXrp - (4 * feeDrops));
BEAST_EXPECT(env.balance(bob, USD.issue()) == preBob - USD(11) );
BEAST_EXPECT(env.balance(bob) == preBobXrp - (2 * feeDrops));
BEAST_EXPECT(bob.id() == tokenOwner(*env.current(), tid));
// bob burns to reset tests
env(burn(bob, hexid), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tid));
}
// alice can sell with USD and dest
{
// alice mints
const auto delta = USD(10);
auto preAlice = env.balance(alice, USD.issue());
auto preAliceXrp = env.balance(alice);
auto preBob = env.balance(bob, USD.issue());
auto preBobXrp = env.balance(bob);
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tid));
// alice sells
env(sell(alice, hexid, delta), txflags(tfSell), jtx::token::destination(bob));
env.close();
BEAST_EXPECT(delta == tokenAmount(*env.current(), tid));
// carol tries to buy but cannot
env(buy(carol, hexid, delta), ter(tecNO_PERMISSION));
env.close();
// bob buys
env(buy(bob, hexid, delta));
env.close();
auto const [urit, uritSle] = uriTokenKeyAndSle(*env.current(), alice, uri);
BEAST_EXPECT(uritokenExists(*env.current(), urit));
BEAST_EXPECT(env.balance(alice, USD.issue()) == preAlice + delta);
BEAST_EXPECT(env.balance(alice) == preAliceXrp - (2 * feeDrops));
BEAST_EXPECT(env.balance(bob, USD.issue()) == preBob - delta);
BEAST_EXPECT(env.balance(bob) == preBobXrp - (1 * feeDrops));
BEAST_EXPECT(bob.id() == tokenOwner(*env.current(), tid));
// bob burns to reset tests
env(burn(bob, hexid), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tid));
}
}
void
testClearValid(FeatureBitset features)
{
testcase("clear");
using namespace jtx;
using namespace std::literals::chrono_literals;
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const carol = Account("carol");
auto const gw = Account("gw");
auto const USD = gw["USD"];
// setup env
Env env{*this, features};
env.fund(XRP(1000), alice, bob, carol, gw);
env.trust(USD(10000), alice);
env.trust(USD(10000), bob);
env.trust(USD(10000), carol);
env.close();
env(pay(gw, alice, USD(1000)));
env(pay(gw, bob, USD(1000)));
env(pay(gw, carol, USD(1000)));
env.close();
auto const feeDrops = env.current()->fees().base;
std::string const uri(maxTokenURILength, '?');
auto const tid = tokenid(alice, uri);
std::string const hexid{strHex(tid)};
// alice can clear / reset XRP amount
{
// alice mints
const auto delta = XRP(10);
auto preAlice = env.balance(alice);
auto preBob = env.balance(bob);
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tid));
// alice sells
env(sell(alice, hexid, delta), txflags(tfSell));
env.close();
BEAST_EXPECT(delta == tokenAmount(*env.current(), tid));
// alice clears the sell amount
env(clear(alice, hexid));
BEAST_EXPECT(XRPAmount{-1} == tokenAmount(*env.current(), tid));
// alice sets sell for higher amount
env(sell(alice, hexid, XRP(11)), txflags(tfSell));
env.close();
BEAST_EXPECT(XRP(11) == tokenAmount(*env.current(), tid));
// alice clears the sell amount
env(clear(alice, hexid));
BEAST_EXPECT(XRPAmount{-1} == tokenAmount(*env.current(), tid));
// alice burns to reset tests
env(burn(bob, hexid), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tid));
}
// alice can clear / reset USD amount
{
// alice mints
const auto delta = USD(10);
auto preAlice = env.balance(alice, USD.issue());
auto preAliceXrp = env.balance(alice);
auto preBob = env.balance(bob, USD.issue());
auto preBobXrp = env.balance(bob);
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritokenExists(*env.current(), tid));
// alice sells
env(sell(alice, hexid, delta), txflags(tfSell));
env.close();
BEAST_EXPECT(delta == tokenAmount(*env.current(), tid));
// alice clears the sell amount
env(clear(alice, hexid));
BEAST_EXPECT(XRPAmount{-1} == tokenAmount(*env.current(), tid));
// alice sets sell for higher amount
env(sell(alice, hexid, USD(11)), txflags(tfSell));
env.close();
BEAST_EXPECT(USD(11) == tokenAmount(*env.current(), tid));
// alice clears the sell amount
env(clear(alice, hexid));
BEAST_EXPECT(XRPAmount{-1} == tokenAmount(*env.current(), tid));
// alice burns to reset tests
env(burn(alice, hexid), txflags(tfBurn));
env.close();
BEAST_EXPECT(!uritokenExists(*env.current(), tid));
}
}
void
testMetaAndOwnership(FeatureBitset features)
{
@@ -676,7 +1223,7 @@ struct URIToken_test : public beast::unit_test::suite
// // alice sets the sell offer
// // bob sets the buy offer
env(buy(bob, id, USD(10)));
BEAST_EXPECT(uritExists(*env.current(), urit));
BEAST_EXPECT(uritokenExists(*env.current(), urit));
BEAST_EXPECT(!inOwnerDir(*env.current(), alice, uritSle));
BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
BEAST_EXPECT(!inOwnerDir(*env.current(), bob, uritSle));
@@ -706,7 +1253,7 @@ struct URIToken_test : public beast::unit_test::suite
// // bob sets the buy offer
env(buy(bob, id, USD(10)));
env.close();
BEAST_EXPECT(uritExists(*env.current(), urit));
BEAST_EXPECT(uritokenExists(*env.current(), urit));
BEAST_EXPECT(!inOwnerDir(*env.current(), alice, uritSle));
BEAST_EXPECT(ownerDirCount(*env.current(), alice) == 1);
BEAST_EXPECT(!inOwnerDir(*env.current(), bob, uritSle));
@@ -714,6 +1261,7 @@ struct URIToken_test : public beast::unit_test::suite
}
}
// TODO: THIS TEST IS NOT COMPLETE
void
testAccountDelete(FeatureBitset features)
{
@@ -763,15 +1311,10 @@ struct URIToken_test : public beast::unit_test::suite
env(pay(gw, carol, USD(1000)));
env.close();
auto const feeDrops = env.current()->fees().base;
// debugBalance(env, "alice", alice, USD);
// debugBalance(env, "bob", bob, USD);
// mint a uritoken from alice
env(mint(alice, uri));
env.close();
BEAST_EXPECT(uritExists(*env.current(), tokenid(alice, uri)));
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(alice, uri)));
env(sell(alice, id, USD(10)), txflags(tfSell));
env.close();
@@ -785,7 +1328,7 @@ struct URIToken_test : public beast::unit_test::suite
// alice still has a trustline
rmAccount(env, alice, bob, tecHAS_OBLIGATIONS);
BEAST_EXPECT(uritExists(*env.current(), tokenid(alice, uri)));
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(alice, uri)));
// buy should fail if the uri token was removed
auto preBob = env.balance(bob, USD.issue());
@@ -794,10 +1337,11 @@ struct URIToken_test : public beast::unit_test::suite
BEAST_EXPECT(env.balance(bob, USD.issue()) == preBob);
env(mint(bob, uri));
BEAST_EXPECT(uritExists(*env.current(), tokenid(bob, uri)));
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(bob, uri)));
}
}
// TODO: THIS TEST IS NOT COMPLETE
void
testUsingTickets(FeatureBitset features)
{
@@ -836,123 +1380,7 @@ struct URIToken_test : public beast::unit_test::suite
env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
BEAST_EXPECT(env.seq(alice) == aliceSeq);
BEAST_EXPECT(uritExists(*env.current(), tokenid(alice, uri)));
// {
// auto const preAlice = env.balance(alice);
// env(sell(alice, id, XRP(1000)), ticket::use(aliceTicketSeq++));
// env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
// BEAST_EXPECT(env.seq(alice) == aliceSeq);
// auto const feeDrops = env.current()->fees().base;
// BEAST_EXPECT(env.balance(alice) == preAlice - XRP(1000) - feeDrops);
// }
// BEAST_EXPECT(uritExists(*env.current(), tokenid(alice, uri)));
// {
// // No signature needed since the bob is buying
// auto const preBob = env.balance(bob);
// env(buy(bob, id, USD(10)), ticket::use(bobTicketSeq++));
// env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
// BEAST_EXPECT(env.seq(bob) == bobSeq);
// BEAST_EXPECT(uritExists(*env.current(), tokenid(alice, uri)));
// BEAST_EXPECT(env.balance(bob) == preBob + USD(10));
// }
// {
// // Claim with signature
// auto preBob = env.balance(bob);
// auto const delta = XRP(500);
// auto const reqBal = chanBal + delta;
// auto const authAmt = reqBal + XRP(100);
// assert(reqBal <= chanAmt);
// auto const sig =
// signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
// env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk()),
// ticket::use(bobTicketSeq++));
// env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
// BEAST_EXPECT(env.seq(bob) == bobSeq);
// BEAST_EXPECT(channelBalance(*env.current(), chan) == reqBal);
// BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt);
// auto const feeDrops = env.current()->fees().base;
// BEAST_EXPECT(env.balance(bob) == preBob + delta - feeDrops);
// chanBal = reqBal;
// // claim again
// preBob = env.balance(bob);
// // A transaction that generates a tec still consumes its ticket.
// env(claim(bob, chan, reqBal, authAmt, Slice(sig), alice.pk()),
// ticket::use(bobTicketSeq++),
// ter(tecUNFUNDED_PAYMENT));
// env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
// BEAST_EXPECT(env.seq(bob) == bobSeq);
// BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal);
// BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt);
// BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
// }
// {
// // Try to claim more than authorized
// auto const preBob = env.balance(bob);
// STAmount const authAmt = chanBal + XRP(500);
// STAmount const reqAmt = authAmt + drops(1);
// assert(reqAmt <= chanAmt);
// // Note that since claim() returns a tem (neither tec nor tes),
// // the ticket is not consumed. So we don't increment bobTicket.
// auto const sig =
// signClaimAuth(alice.pk(), alice.sk(), chan, authAmt);
// env(claim(bob, chan, reqAmt, authAmt, Slice(sig), alice.pk()),
// ticket::use(bobTicketSeq),
// ter(temBAD_AMOUNT));
// env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
// BEAST_EXPECT(env.seq(bob) == bobSeq);
// BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal);
// BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt);
// BEAST_EXPECT(env.balance(bob) == preBob);
// }
// // Dst tries to fund the channel
// env(fund(bob, chan, XRP(1000)),
// ticket::use(bobTicketSeq++),
// ter(tecNO_PERMISSION));
// env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
// BEAST_EXPECT(env.seq(bob) == bobSeq);
// BEAST_EXPECT(channelBalance(*env.current(), chan) == chanBal);
// BEAST_EXPECT(channelAmount(*env.current(), chan) == chanAmt);
// {
// // Dst closes channel
// auto const preAlice = env.balance(alice);
// auto const preBob = env.balance(bob);
// env(claim(bob, chan),
// txflags(tfClose),
// ticket::use(bobTicketSeq++));
// env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
// BEAST_EXPECT(env.seq(bob) == bobSeq);
// BEAST_EXPECT(!channelExists(*env.current(), chan));
// auto const feeDrops = env.current()->fees().base;
// auto const delta = chanAmt - chanBal;
// assert(delta > beast::zero);
// BEAST_EXPECT(env.balance(alice) == preAlice + delta);
// BEAST_EXPECT(env.balance(bob) == preBob - feeDrops);
// }
// env.require(tickets(alice, env.seq(alice) - aliceTicketSeq));
// BEAST_EXPECT(env.seq(alice) == aliceSeq);
// env.require(tickets(bob, env.seq(bob) - bobTicketSeq));
// BEAST_EXPECT(env.seq(bob) == bobSeq);
BEAST_EXPECT(uritokenExists(*env.current(), tokenid(alice, uri)));
}
void
@@ -964,9 +1392,14 @@ struct URIToken_test : public beast::unit_test::suite
// testSellInvalid(features);
// testBuyInvalid(features);
// testClearInvalid(features);
// testMintValid(features);
// testBurnValid(features);
// testBuyValid(features);
testSellValid(features);
testClearValid(features);
// testMetaAndOwnership(features);
// testAccountDelete(features);
testUsingTickets(features);
// testUsingTickets(features);
}
public: