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;
123 return j.isMember(jss::result) &&
124 (j[jss::result][jss::status] ==
"success") &&
125 (j[jss::result][jss::transactions].size() == 2) &&
126 (j[jss::result][jss::transactions][0u][jss::tx]
127 [jss::TransactionType] == jss::AccountSet) &&
128 (j[jss::result][jss::transactions][1u][jss::tx]
129 [jss::TransactionType] == jss::Payment);
133 return j.isMember(jss::result) &&
134 (j[jss::result][jss::status] ==
"success") &&
135 (j[jss::result][jss::transactions].size() == 0);
140 j[jss::result].
isMember(jss::error) &&
145 jParms[jss::api_version] = apiVersion;
151 jParms[jss::account] =
"0xDEADBEEF";
157 jParms[jss::account] = A1.human();
158 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(jParms))));
163 p[jss::ledger_index_min] = -1;
164 p[jss::ledger_index_max] = -1;
165 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
167 p[jss::ledger_index_min] = 0;
168 p[jss::ledger_index_max] = 100;
177 p[jss::ledger_index_min] = 1;
178 p[jss::ledger_index_max] = 2;
187 p[jss::ledger_index_min] = 2;
188 p[jss::ledger_index_max] = 1;
197 p[jss::ledger_index_min] = -1;
198 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
200 p[jss::ledger_index_min] = 1;
209 p[jss::ledger_index_min] = env.
current()->info().seq;
219 p[jss::ledger_index_max] = -1;
220 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
222 p[jss::ledger_index_max] = env.
current()->info().seq;
231 p[jss::ledger_index_max] = 3;
232 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
234 p[jss::ledger_index_max] = env.
closed()->info().seq;
235 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
237 p[jss::ledger_index_max] = env.
closed()->info().seq - 1;
238 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
245 p[jss::ledger_index] = env.
closed()->info().seq;
246 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
248 p[jss::ledger_index] = env.
closed()->info().seq - 1;
249 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
251 p[jss::ledger_index] = env.
current()->info().seq;
256 p[jss::ledger_index] = env.
current()->info().seq + 1;
266 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
269 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
275 jParms[jss::account] =
"0xDEADBEEF";
276 jParms[jss::account] = A1.human();
279 p[jss::ledger_index_max] = -1;
280 p[jss::ledger_index_min] = -1;
281 p[jss::ledger_index] = -1;
295 p[jss::ledger_index_max] = env.
current()->info().seq;
307 p[jss::binary] =
"asdf";
311 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
318 p[jss::binary] =
true;
320 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
322 p[jss::forward] =
"true";
324 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
330 p[jss::forward] =
false;
332 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
341 using namespace test::jtx;
342 using namespace std::chrono_literals;
348 auto const USD{gw[
"USD"]};
350 env.
fund(
XRP(1000000), alice, gw);
357 env(pay(alice, gw,
XRP(100)));
364 env(trust(alice, USD(200)),
sig(alie));
366 env(offer(alice, USD(50),
XRP(150)),
sig(alie));
373 env(signers(alice, 1, {{
"bogie", 1}, {
"demon", 1}}),
sig(alie));
378 auto escrow = [](
Account const& account,
382 escro[jss::TransactionType] = jss::EscrowCreate;
384 escro[jss::Account] = account.human();
385 escro[jss::Destination] = to.human();
394 nextTime.time_since_epoch().count();
397 env(escrowWithFinish,
sig(alie));
401 nextTime.time_since_epoch().count();
403 nextTime.time_since_epoch().count() + 1;
406 env(escrowWithCancel,
sig(alie));
411 escrowFinish[jss::TransactionType] = jss::EscrowFinish;
413 escrowFinish[jss::Account] = alice.human();
416 env(escrowFinish,
sig(alie));
420 escrowCancel[jss::TransactionType] = jss::EscrowCancel;
422 escrowCancel[jss::Account] = alice.human();
425 env(escrowCancel,
sig(alie));
434 payChanCreate[jss::TransactionType] = jss::PaymentChannelCreate;
436 payChanCreate[jss::Account] = alice.human();
437 payChanCreate[jss::Destination] = gw.human();
438 payChanCreate[jss::Amount] =
443 env(payChanCreate,
sig(alie));
451 payChanFund[jss::TransactionType] = jss::PaymentChannelFund;
453 payChanFund[jss::Account] = alice.human();
455 payChanFund[jss::Amount] =
457 env(payChanFund,
sig(alie));
462 payChanClaim[jss::TransactionType] = jss::PaymentChannelClaim;
463 payChanClaim[jss::Flags] =
tfClose;
464 payChanClaim[jss::Account] = gw.human();
475 env(check::create(alice, gw,
XRP(300)),
sig(alie));
478 env(check::create(gw, alice,
XRP(200)));
481 env(check::cash(alice, gwCheckId,
XRP(200)),
sig(alie));
482 env(check::cancel(alice, aliceCheckId),
sig(alie));
488 env(ticket::create(alice, 1),
sig(alie));
497 params[jss::account] = alice.human();
498 params[jss::ledger_index_min] = -1;
499 params[jss::ledger_index_max] = -1;
504 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
505 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
507 Json::Value const& txs{result[jss::result][jss::transactions]};
514 {0, jss::DepositPreauth, {jss::DepositPreauth}, {jss::Ticket}, {jss::AccountRoot, jss::DirectoryNode}},
515 {1, jss::TicketCreate, {jss::Ticket}, {}, {jss::AccountRoot, jss::DirectoryNode}},
516 {2, jss::CheckCancel, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
517 {3, jss::CheckCash, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
518 {4, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
519 {5, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
520 {6, jss::PaymentChannelClaim, {}, {jss::PayChannel}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
521 {7, jss::PaymentChannelFund, {}, {}, {jss::AccountRoot, jss::PayChannel}},
522 {8, jss::PaymentChannelCreate, {jss::PayChannel}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
523 {9, jss::EscrowCancel, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
524 {10, jss::EscrowFinish, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
525 {11, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
526 {12, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
527 {13, jss::SignerListSet, {jss::SignerList}, {}, {jss::AccountRoot, jss::DirectoryNode}},
528 {14, jss::OfferCancel, {}, {jss::Offer, jss::DirectoryNode}, {jss::AccountRoot, jss::DirectoryNode}},
529 {15, jss::OfferCreate, {jss::Offer, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::DirectoryNode}},
530 {16, jss::TrustSet, {jss::RippleState, jss::DirectoryNode, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::AccountRoot}},
531 {17, jss::SetRegularKey, {}, {}, {jss::AccountRoot}},
532 {18, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
533 {19, jss::AccountSet, {}, {}, {jss::AccountRoot}},
534 {20, jss::AccountSet, {}, {}, {jss::AccountRoot}},
535 {21, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
540 std::size(sanity) == result[jss::result][jss::transactions].size());
542 for (
unsigned int index{0}; index <
std::size(sanity); ++index)
554 using namespace test::jtx;
555 using namespace std::chrono_literals;
561 env.
fund(
XRP(10000), alice, becky);
566 BEAST_EXPECT(env.
closed()->exists(beckyAcctKey));
578 auto const beckyPreDelBalance{env.
balance(becky)};
580 auto const acctDelFee{
drops(env.
current()->fees().increment)};
585 BEAST_EXPECT(!env.
closed()->exists(beckyAcctKey));
597 { 0, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
598 { 1, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
599 { 2, jss::AccountDelete, {}, {jss::AccountRoot}, {jss::AccountRoot}},
600 { 3, jss::AccountSet, {}, {}, {jss::AccountRoot}},
601 { 4, jss::AccountSet, {}, {}, {jss::AccountRoot}},
602 { 5, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}}
610 params[jss::account] = becky.human();
611 params[jss::ledger_index_min] = -1;
612 params[jss::ledger_index_max] = -1;
617 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
618 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
621 constexpr
unsigned int beckyDeletedOffest = 2;
624 result[jss::result][jss::transactions].size() +
627 Json::Value const& txs{result[jss::result][jss::transactions]};
629 for (
unsigned int index = beckyDeletedOffest;
633 checkSanity(txs[index - beckyDeletedOffest], sanity[index]);
646 env(pay(alice, becky,
XRP(45)));
650 BEAST_EXPECT(env.
closed()->exists(beckyAcctKey));
654 env(pay(becky, alice,
XRP(20)));
660 params[jss::account] = becky.human();
661 params[jss::ledger_index_min] = -1;
662 params[jss::ledger_index_max] = -1;
667 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
668 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
671 std::size(sanity) == result[jss::result][jss::transactions].size());
673 Json::Value const& txs{result[jss::result][jss::transactions]};
675 for (
unsigned int index = 0; index <
std::size(sanity); ++index)