2#include <test/jtx/Account.h>
3#include <test/jtx/Env.h>
4#include <test/jtx/TestHelpers.h>
5#include <test/jtx/acctdelete.h>
6#include <test/jtx/amount.h>
7#include <test/jtx/balance.h>
8#include <test/jtx/check.h>
9#include <test/jtx/credentials.h>
10#include <test/jtx/deposit.h>
11#include <test/jtx/did.h>
12#include <test/jtx/escrow.h>
13#include <test/jtx/fee.h>
14#include <test/jtx/flags.h>
15#include <test/jtx/multisign.h>
16#include <test/jtx/noop.h>
17#include <test/jtx/offer.h>
18#include <test/jtx/owners.h>
19#include <test/jtx/pay.h>
20#include <test/jtx/regkey.h>
21#include <test/jtx/sig.h>
22#include <test/jtx/ter.h>
23#include <test/jtx/ticket.h>
24#include <test/jtx/trust.h>
25#include <test/jtx/txflags.h>
26#include <test/jtx/vault.h>
28#include <xrpl/basics/base_uint.h>
29#include <xrpl/basics/chrono.h>
30#include <xrpl/basics/strHex.h>
31#include <xrpl/beast/unit_test/suite.h>
32#include <xrpl/json/json_value.h>
33#include <xrpl/json/to_string.h>
34#include <xrpl/ledger/ReadView.h>
35#include <xrpl/protocol/Feature.h>
36#include <xrpl/protocol/Indexes.h>
37#include <xrpl/protocol/Issue.h>
38#include <xrpl/protocol/Keylet.h>
39#include <xrpl/protocol/PublicKey.h>
40#include <xrpl/protocol/SField.h>
41#include <xrpl/protocol/STAmount.h>
42#include <xrpl/protocol/SeqProxy.h>
43#include <xrpl/protocol/TER.h>
44#include <xrpl/protocol/TxFlags.h>
45#include <xrpl/protocol/jss.h>
76 if (!BEAST_EXPECT(meta.
isMember(sfDeliveredAmount.jsonName)))
82 BEAST_EXPECT(meta[sfDeliveredAmount.jsonName] == jsonExpect);
83 BEAST_EXPECT(meta[jss::delivered_amount] == jsonExpect);
88 ledgerParams[jss::ledger_index] = txResult[jss::ledger_index].
asUInt();
89 ledgerParams[jss::transactions] =
true;
90 ledgerParams[jss::expand] =
true;
92 auto const ledgerResult = env.
rpc(
"json",
"ledger",
to_string(ledgerParams));
93 auto const& ledgerTx = ledgerResult[jss::result][jss::ledger][jss::transactions][0u];
94 BEAST_EXPECT(ledgerTx[jss::hash].asString() == txHash);
96 json::Value const& ledgerMeta = ledgerTx[jss::metaData];
97 BEAST_EXPECT(ledgerMeta[sfDeliveredAmount.jsonName] == jsonExpect);
98 BEAST_EXPECT(ledgerMeta[jss::delivered_amount] == jsonExpect);
112 jv[jss::TransactionType] = jss::PaymentChannelCreate;
113 jv[jss::Account] = account.human();
114 jv[jss::Destination] = to.
human();
116 jv[sfSettleDelay.jsonName] = settleDelay.
count();
136 env.
fund(
XRP(10000), alice, becky, carol, gw);
150 auto const acctDelFee{
drops(env.
current()->fees().increment)};
160 env(
trust(becky, gw[
"USD"](1000)));
167 env(
offer(carol, gw[
"USD"](51),
XRP(51)));
170 env(
signers(carol, 1, {{alice, 1}, {becky, 1}}));
189 auto const aliceOldBalance{env.
balance(alice)};
190 auto const beckyOldBalance{env.
balance(becky)};
205 BEAST_EXPECT(env.
balance(becky) == aliceOldBalance + beckyOldBalance - acctDelFee);
226 for (
int i = 0; i < 8; ++i)
230 auto const beckyOldBalance{env.
balance(becky)};
231 auto const carolOldBalance{env.
balance(carol)};
238 BEAST_EXPECT(env.
closed()->exists(
240 BEAST_EXPECT(env.
closed()->exists(
254 BEAST_EXPECT(!env.
closed()->exists(
256 BEAST_EXPECT(!env.
closed()->exists(
261 BEAST_EXPECT(env.
balance(becky) == carolOldBalance + beckyOldBalance - acctDelFee);
283 env.
fund(
XRP(10000), alice, gw);
287 for (
int i{0}; i < 45; ++i)
289 env(
offer(alice, gw[
"USD"](1),
XRP(1)));
300 BEAST_EXPECT(env.
closed()->exists(aliceRootKey));
301 BEAST_EXPECT(env.
closed()->exists(alicePageKey));
304 auto const acctDelFee{
drops(env.
current()->fees().increment)};
305 auto const aliceBalance{env.
balance(alice)};
311 BEAST_EXPECT(!env.
closed()->exists(aliceRootKey));
312 BEAST_EXPECT(!env.
closed()->exists(alicePageKey));
328 env.
fund(
XRP(100000), alice, becky, gw);
334 for (
int i{0}; i < 200; ++i)
336 env(
offer(alice, gw[
"USD"](1),
XRP(1)));
337 env(
offer(becky, gw[
"USD"](1),
XRP(1)));
355 auto const acctDelFee{
drops(env.
current()->fees().increment)};
366 using namespace std::chrono_literals;
382 bool const withTokenEscrow = env.
current()->rules().enabled(featureTokenEscrow);
387 auto const usd = gw1[
"USD"];
388 env.
fund(
XRP(100000), carol, gw1);
389 env(
fset(gw1, asfAllowTrustLineLocking));
391 env.
trust(usd(10000), carol);
393 env(
pay(gw1, carol, usd(100)));
414 Keylet const alicePayChanKey{
422 auto const beckyBalance{env.
balance(becky)};
434 jv[jss::TransactionType] = jss::PaymentChannelClaim;
435 jv[jss::Flags] = tfClose;
436 jv[jss::Account] = account.human();
437 jv[sfChannel.jsonName] =
to_string(payChanKeylet.key);
438 jv[sfPublicKey.jsonName] =
strHex(pk.slice());
441 env(payChanClose(alice, alicePayChanKey, alice.
pk()));
446 Keylet const gwPayChanKey{
458 env(payChanClose(alice, gwPayChanKey, alice.
pk()));
462 auto const aliceBalance{env.
balance(alice)};
481 env.
fund(
XRP(10000000), alice, gw);
491 static constexpr int kOfferCount{1001};
492 for (
int i{0}; i < kOfferCount; ++i)
494 env(
offer(alice, gw[currency](1),
XRP(1)));
499 if (currency[0] >
'Z')
504 if (currency[1] >
'Z')
509 if (currency[2] >
'Z')
525 BEAST_EXPECT(closed->exists(aliceOwnerDirKey));
529 BEAST_EXPECT(closed->exists(
keylet::page(aliceOwnerDirKey, i)));
534 BEAST_EXPECT(closed->exists(
541 auto const acctDelFee{
drops(env.
current()->fees().increment)};
552 auto const alicePreDelBal{env.
balance(alice)};
562 BEAST_EXPECT(!closed->exists(aliceOwnerDirKey));
566 BEAST_EXPECT(!closed->exists(
keylet::page(aliceOwnerDirKey, i)));
571 BEAST_EXPECT(!closed->exists(
584 testcase(
"Implicitly created trust line");
589 auto const bux{gw[
"BUX"]};
591 env.
fund(
XRP(10000), alice, gw);
596 env(
offer(alice, bux(30),
XRP(30)));
609 auto const acctDelFee{
drops(env.
current()->fees().increment)};
629 testcase(
"Balance too small for fee");
645 auto const acctDelFee{
drops(env.
current()->fees().increment)};
646 BEAST_EXPECT(acctDelFee > env.
balance(alice));
684 env.
fund(
XRP(100000), alice, bob);
708 auto const acctDelFee{
drops(env.
current()->fees().increment)};
709 auto const bobOldBalance{env.
balance(bob)};
727 testcase(
"Destination Constraints");
736 Env env{*
this, features};
737 env.
fund(
XRP(100000), alice, becky, carol);
743 env(
fset(alice, asfDepositAuth));
746 env(
fset(carol, asfRequireDest));
750 Vault const vault{env};
751 auto [tx,
keylet] = vault.create({.owner = alice, .asset =
xrpIssue()});
754 auto const sleVault = env.
le(
keylet);
755 if (!BEAST_EXPECT(sleVault))
757 Account const vaultPseudo{
"vaultPseudo", sleVault->at(sfAccount)};
764 auto const acctDelFee{
drops(env.
current()->fees().increment)};
787 auto const beckyOldBalance{env.
balance(becky)};
797 testcase(
"Destination Constraints with DepositPreauth and Credentials");
806 char const credType[] =
"abcd";
809 env.
fund(
XRP(100000), alice, becky, carol, daria);
818 std::string const credIdx = jv[jss::result][jss::index].asString();
823 auto const acctDelFee{
drops(env.
current()->fees().increment)};
836 env(
fset(alice, asfDepositAuth));
877 credentials::Ids({
"48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6E"
891 jNoCred.isObject() && jNoCred.isMember(jss::result) &&
892 jNoCred[jss::result].isMember(jss::error) &&
893 jNoCred[jss::result][jss::error] ==
"entryNotFound");
896 testcase(
"Credentials that aren't required");
915 jNoCred.isObject() && jNoCred.isMember(jss::result) &&
916 jNoCred[jss::result].isMember(jss::error) &&
917 jNoCred[jss::result][jss::error] ==
"entryNotFound");
924 env.
fund(
XRP(5000), eaton, fred);
936 env(
fset(fred, asfDepositAuth));
943 auto const acctDelFee{
drops(env.
current()->fees().increment)};
954 jNoCred.isObject() && jNoCred.isMember(jss::result) &&
955 jNoCred[jss::result].isMember(jss::error) &&
956 jNoCred[jss::result][jss::error] ==
"entryNotFound");
968 env.
current()->header().parentCloseTime.time_since_epoch().count() + 20;
969 jv[sfExpiration.jsonName] = t;
975 std::string const credIdx = jv[jss::result][jss::index].asString();
991 jv.isObject() && jv.isMember(jss::result) &&
992 jv[jss::result].isMember(jss::error) &&
993 jv[jss::result][jss::error] ==
"entryNotFound");
999 testcase(
"Credentials feature disabled");
1007 env.
fund(
XRP(100000), alice, becky, carol);
1013 env(
fset(alice, asfDepositAuth));
1019 auto const acctDelFee{
drops(env.
current()->fees().increment)};
1022 "098B7F1B146470A1C5084DC7832C04A72939E3EBC58E68AB8B579BA072B0CE"
1041 testcase(
"Deleting Issuer deletes issued credentials");
1049 char const credType[] =
"abcd";
1052 env.
fund(
XRP(100000), alice, becky, carol);
1063 std::string const credIdx = jv[jss::result][jss::index].asString();
1068 auto const acctDelFee{
drops(env.
current()->fees().increment)};
1073 BEAST_EXPECT(!env.
le(credIdx));
1076 jv.isObject() && jv.isMember(jss::result) &&
1077 jv[jss::result].isMember(jss::error) &&
1078 jv[jss::result][jss::error] ==
"entryNotFound");
1083 testcase(
"Deleting Subject deletes issued credentials");
1091 char const credType[] =
"abcd";
1094 env.
fund(
XRP(100000), alice, becky, carol);
1105 std::string const credIdx = jv[jss::result][jss::index].asString();
1110 auto const acctDelFee{
drops(env.
current()->fees().increment)};
1115 BEAST_EXPECT(!env.
le(credIdx));
1118 jv.isObject() && jv.isMember(jss::result) &&
1119 jv[jss::result].isMember(jss::error) &&
1120 jv[jss::result][jss::error] ==
"entryNotFound");
TestcaseT testcase
Memberspace for declaring test cases.
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
std::chrono::time_point< NetClock > time_point
std::chrono::duration< rep, period > duration
Slice slice() const noexcept
json::Value getJson(JsonOptions=JsonOptions::Values::None) const override
static constexpr SeqProxy rawSequence(std::uint32_t v)
Factory function to return a sequence-based SeqProxy.
static constexpr SeqProxy rawTicket(std::uint32_t v)
Factory function to return a ticket-based SeqProxy.
void testDest(FeatureBitset features)
void run() override
Runs the suite.
static json::Value payChanCreate(jtx::Account const &account, jtx::Account const &to, STAmount const &amount, NetClock::duration const &settleDelay, NetClock::time_point const &cancelAfter, PublicKey const &pk)
void testDeleteCredentialsOwner()
void verifyDeliveredAmount(jtx::Env &env, STAmount const &amount)
void testBalanceTooSmallForFee()
void testDestinationDepositAuthCredentials()
void testImplicitlyCreatedTrustline()
Immutable cryptographic account descriptor.
std::string const & human() const
Returns the human readable public key.
PublicKey const & pk() const
Return the public key.
AccountID id() const
Returns the Account ID.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
SLE::const_pointer le(Account const &account) const
Return an account root.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
std::shared_ptr< STTx const > tx() const
Return the tx data for the last JTx.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
NetClock::time_point now()
Returns the current network time.
Set a multisignature on a JTx.
Match the number of items in the account's owner directory.
Set the regular signature on a JTx.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Set a ticket sequence on a JTx.
Keylet computation functions.
Keylet payChannel(AccountID const &src, AccountID const &dst, SeqProxy const &seq) noexcept
A PaymentChannel.
Keylet offer(AccountID const &id, SeqProxy const &seq) noexcept
An offer from an account.
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Keylet signerList(AccountID const &account) noexcept
A SignerList.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet check(AccountID const &id, SeqProxy const &seq) noexcept
A Check.
Keylet ticket(AccountID const &id, SeqProxy const &ticketSeq)
A ticket belonging to an account.
Keylet page(UInt256 const &root, std::uint64_t const index=0) noexcept
A page in a directory.
Keylet account(AccountID const &id) noexcept
AccountID root.
json::Value cancel(jtx::Account const &dest, UInt256 const &checkId)
Cancel a check.
json::Value create(A const &account, A const &dest, STAmount const &sendMax)
Create a check.
json::Value accept(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
json::Value create(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
json::Value ledgerEntry(jtx::Env &env, jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
json::Value authCredentials(jtx::Account const &account, std::vector< AuthorizeCredentials > const &auth)
json::Value auth(Account const &account, Account const &auth)
Preauthorize for deposit.
json::Value setValid(jtx::Account const &account)
json::Value create(AccountID const &account, AccountID const &to, STAmount const &amount)
json::Value cancel(AccountID const &account, Account const &from, std::uint32_t seq)
auto const kCancelTime
Set the "CancelAfter" time tag on a JTx.
auto const kFinishTime
Set the "FinishAfter" time tag on a JTx.
json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
json::Value regkey(Account const &account, DisabledT)
Disable the regular key.
json::Value offerCancel(Account const &account, std::uint32_t offerSeq)
Cancel an offer.
XrpT const XRP
Converts to XRP Issue or STAmount.
json::Value noop(Account const &account)
The null transaction.
FeatureBitset testableAmendments()
OwnerCount< ltOFFER > Offers
Match the number of offers in the account's owner directory.
json::Value acctdelete(Account const &account, Account const &dest)
Delete account.
void incLgrSeqForAccDel(jtx::Env &env, jtx::Account const &acc, std::uint32_t margin=0)
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
json::Value signers(Account const &account, std::uint32_t quorum, std::vector< Signer > const &v)
json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
BEAST_DEFINE_TESTSUITE_PRIO(AccountDelete, app, xrpl, 2)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
std::string strHex(FwdIt begin, FwdIt end)
std::string to_string(BaseUInt< Bits, Tag > const &a)
A pair of SHAMap key and LedgerEntryType.
T time_since_epoch(T... args)