20 #include <ripple/beast/unit_test.h>
21 #include <ripple/protocol/ErrorCodes.h>
22 #include <ripple/protocol/jss.h>
25 #include <boost/container/flat_set.hpp>
39 boost::container::flat_set<std::string>
created;
40 boost::container::flat_set<std::string>
deleted;
41 boost::container::flat_set<std::string>
modified;
51 auto buildSet = [](
auto&& init) {
52 boost::container::flat_set<std::string> r;
53 r.reserve(init.size());
69 BEAST_EXPECT(
txNode[jss::validated].asBool() ==
true);
75 boost::container::flat_set<std::string> createdNodes;
76 boost::container::flat_set<std::string> deletedNodes;
77 boost::container::flat_set<std::string> modifiedNodes;
99 "Unexpected or unlabeled node type in metadata.",
104 BEAST_EXPECT(createdNodes == sane.
created);
105 BEAST_EXPECT(deletedNodes == sane.
deleted);
106 BEAST_EXPECT(modifiedNodes == sane.
modified);
112 using namespace test::jtx;
126 return j.isMember(jss::result) &&
127 (j[jss::result][jss::status] ==
"success") &&
128 (j[jss::result][jss::transactions].size() == 2) &&
129 (j[jss::result][jss::transactions][0u][jss::tx]
130 [jss::TransactionType] == jss::AccountSet) &&
131 (j[jss::result][jss::transactions][1u][jss::tx]
132 [jss::TransactionType] == jss::Payment) &&
133 (j[jss::result][jss::transactions][1u][jss::tx]
134 [jss::DeliverMax] ==
"10000000010") &&
135 (j[jss::result][jss::transactions][1u][jss::tx]
137 j[jss::result][jss::transactions][1u][jss::tx]
141 if (j.isMember(jss::result) &&
142 (j[jss::result][jss::status] ==
"success") &&
143 (j[jss::result][jss::transactions].size() == 2) &&
144 (j[jss::result][jss::transactions][0u][jss::tx_json]
145 [jss::TransactionType] == jss::AccountSet))
147 auto const& payment =
148 j[jss::result][jss::transactions][1u];
150 return (payment.isMember(jss::tx_json)) &&
151 (payment[jss::tx_json][jss::TransactionType] ==
153 (payment[jss::tx_json][jss::DeliverMax] ==
155 (!payment[jss::tx_json].isMember(jss::Amount)) &&
156 (!payment[jss::tx_json].isMember(jss::hash)) &&
157 (payment[jss::hash] ==
158 "9F3085D85F472D1CC29627F260DF68EDE59D42D1D0C33E345"
159 "ECF0D4CE981D0A8") &&
160 (payment[jss::validated] ==
true) &&
161 (payment[jss::ledger_index] == 3) &&
162 (payment[jss::ledger_hash] ==
163 "5476DCD816EA04CBBA57D47BBF1FC58A5217CC93A5ADD79CB"
164 "580A5AFDD727E33") &&
165 (payment[jss::close_time_iso] ==
166 "2000-01-01T00:00:10Z");
177 return j.isMember(jss::result) &&
178 (j[jss::result][jss::status] ==
"success") &&
179 (j[jss::result][jss::transactions].size() == 0);
184 j[jss::result].
isMember(jss::error) &&
189 jParms[jss::api_version] = apiVersion;
195 jParms[jss::account] =
"0xDEADBEEF";
201 jParms[jss::account] = A1.human();
203 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(jParms))));
208 p[jss::ledger_index_min] = -1;
209 p[jss::ledger_index_max] = -1;
211 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
213 p[jss::ledger_index_min] = 0;
214 p[jss::ledger_index_max] = 100;
217 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
223 p[jss::ledger_index_min] = 1;
224 p[jss::ledger_index_max] = 2;
233 p[jss::ledger_index_min] = 2;
234 p[jss::ledger_index_max] = 1;
243 p[jss::ledger_index_min] = -1;
245 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
247 p[jss::ledger_index_min] = 1;
250 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
256 p[jss::ledger_index_min] = env.
current()->info().seq;
266 p[jss::ledger_index_max] = -1;
268 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
270 p[jss::ledger_index_max] = env.
current()->info().seq;
273 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
279 p[jss::ledger_index_max] = 3;
281 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
283 p[jss::ledger_index_max] = env.
closed()->info().seq;
285 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
287 p[jss::ledger_index_max] = env.
closed()->info().seq - 1;
288 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
295 p[jss::ledger_index] = env.
closed()->info().seq;
297 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
299 p[jss::ledger_index] = env.
closed()->info().seq - 1;
300 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
302 p[jss::ledger_index] = env.
current()->info().seq;
307 p[jss::ledger_index] = env.
current()->info().seq + 1;
318 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
321 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
327 jParms[jss::account] =
"0xDEADBEEF";
328 jParms[jss::account] = A1.human();
331 p[jss::ledger_index_max] = -1;
332 p[jss::ledger_index_min] = -1;
333 p[jss::ledger_index] = -1;
337 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
347 p[jss::ledger_index_max] = env.
current()->info().seq;
350 env.
rpc(apiVersion,
"json",
"account_tx",
to_string(p))));
359 p[jss::binary] =
"asdf";
363 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
370 p[jss::binary] =
true;
372 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
374 p[jss::forward] =
"true";
376 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
382 p[jss::forward] =
false;
384 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
393 using namespace test::jtx;
394 using namespace std::chrono_literals;
400 auto const USD{gw[
"USD"]};
402 env.
fund(
XRP(1000000), alice, gw);
409 env(pay(alice, gw,
XRP(100)));
416 env(trust(alice, USD(200)),
sig(alie));
418 env(offer(alice, USD(50),
XRP(150)),
sig(alie));
425 env(signers(alice, 1, {{
"bogie", 1}, {
"demon", 1}}),
sig(alie));
430 auto escrow = [](
Account const& account,
434 escro[jss::TransactionType] = jss::EscrowCreate;
436 escro[jss::Account] = account.human();
437 escro[jss::Destination] = to.human();
446 nextTime.time_since_epoch().count();
449 env(escrowWithFinish,
sig(alie));
453 nextTime.time_since_epoch().count();
455 nextTime.time_since_epoch().count() + 1;
458 env(escrowWithCancel,
sig(alie));
463 escrowFinish[jss::TransactionType] = jss::EscrowFinish;
465 escrowFinish[jss::Account] = alice.human();
468 env(escrowFinish,
sig(alie));
472 escrowCancel[jss::TransactionType] = jss::EscrowCancel;
474 escrowCancel[jss::Account] = alice.human();
477 env(escrowCancel,
sig(alie));
486 payChanCreate[jss::TransactionType] = jss::PaymentChannelCreate;
488 payChanCreate[jss::Account] = alice.human();
489 payChanCreate[jss::Destination] = gw.human();
490 payChanCreate[jss::Amount] =
495 env(payChanCreate,
sig(alie));
503 payChanFund[jss::TransactionType] = jss::PaymentChannelFund;
505 payChanFund[jss::Account] = alice.human();
507 payChanFund[jss::Amount] =
509 env(payChanFund,
sig(alie));
514 payChanClaim[jss::TransactionType] = jss::PaymentChannelClaim;
515 payChanClaim[jss::Flags] =
tfClose;
516 payChanClaim[jss::Account] = gw.human();
527 env(check::create(alice, gw,
XRP(300)),
sig(alie));
530 env(check::create(gw, alice,
XRP(200)));
533 env(check::cash(alice, gwCheckId,
XRP(200)),
sig(alie));
534 env(check::cancel(alice, aliceCheckId),
sig(alie));
540 env(ticket::create(alice, 1),
sig(alie));
549 params[jss::account] = alice.human();
550 params[jss::ledger_index_min] = -1;
551 params[jss::ledger_index_max] = -1;
556 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
557 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
559 Json::Value const& txs{result[jss::result][jss::transactions]};
566 {0, jss::DepositPreauth, {jss::DepositPreauth}, {jss::Ticket}, {jss::AccountRoot, jss::DirectoryNode}},
567 {1, jss::TicketCreate, {jss::Ticket}, {}, {jss::AccountRoot, jss::DirectoryNode}},
568 {2, jss::CheckCancel, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
569 {3, jss::CheckCash, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
570 {4, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
571 {5, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
572 {6, jss::PaymentChannelClaim, {}, {jss::PayChannel}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
573 {7, jss::PaymentChannelFund, {}, {}, {jss::AccountRoot, jss::PayChannel}},
574 {8, jss::PaymentChannelCreate, {jss::PayChannel}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
575 {9, jss::EscrowCancel, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
576 {10, jss::EscrowFinish, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
577 {11, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
578 {12, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
579 {13, jss::SignerListSet, {jss::SignerList}, {}, {jss::AccountRoot, jss::DirectoryNode}},
580 {14, jss::OfferCancel, {}, {jss::Offer, jss::DirectoryNode}, {jss::AccountRoot, jss::DirectoryNode}},
581 {15, jss::OfferCreate, {jss::Offer, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::DirectoryNode}},
582 {16, jss::TrustSet, {jss::RippleState, jss::DirectoryNode, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::AccountRoot}},
583 {17, jss::SetRegularKey, {}, {}, {jss::AccountRoot}},
584 {18, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
585 {19, jss::AccountSet, {}, {}, {jss::AccountRoot}},
586 {20, jss::AccountSet, {}, {}, {jss::AccountRoot}},
587 {21, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
592 std::size(sanity) == result[jss::result][jss::transactions].size());
594 for (
unsigned int index{0}; index <
std::size(sanity); ++index)
606 using namespace test::jtx;
607 using namespace std::chrono_literals;
613 env.
fund(
XRP(10000), alice, becky);
618 BEAST_EXPECT(env.
closed()->exists(beckyAcctKey));
630 auto const beckyPreDelBalance{env.
balance(becky)};
632 auto const acctDelFee{
drops(env.
current()->fees().increment)};
637 BEAST_EXPECT(!env.
closed()->exists(beckyAcctKey));
649 { 0, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
650 { 1, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
651 { 2, jss::AccountDelete, {}, {jss::AccountRoot}, {jss::AccountRoot}},
652 { 3, jss::AccountSet, {}, {}, {jss::AccountRoot}},
653 { 4, jss::AccountSet, {}, {}, {jss::AccountRoot}},
654 { 5, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}}
662 params[jss::account] = becky.human();
663 params[jss::ledger_index_min] = -1;
664 params[jss::ledger_index_max] = -1;
669 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
670 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
673 constexpr
unsigned int beckyDeletedOffest = 2;
676 result[jss::result][jss::transactions].size() +
679 Json::Value const& txs{result[jss::result][jss::transactions]};
681 for (
unsigned int index = beckyDeletedOffest;
685 checkSanity(txs[index - beckyDeletedOffest], sanity[index]);
698 env(pay(alice, becky,
XRP(45)));
702 BEAST_EXPECT(env.
closed()->exists(beckyAcctKey));
706 env(pay(becky, alice,
XRP(20)));
712 params[jss::account] = becky.human();
713 params[jss::ledger_index_min] = -1;
714 params[jss::ledger_index_max] = -1;
719 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
720 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
723 std::size(sanity) == result[jss::result][jss::transactions].size());
725 Json::Value const& txs{result[jss::result][jss::transactions]};
727 for (
unsigned int index = 0; index <
std::size(sanity); ++index)