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]
140 if (j.isMember(jss::result) &&
141 (j[jss::result][jss::status] ==
"success") &&
142 (j[jss::result][jss::transactions].size() == 2) &&
143 (j[jss::result][jss::transactions][0u][jss::tx_json]
144 [jss::TransactionType] == jss::AccountSet))
146 auto const& payment =
147 j[jss::result][jss::transactions][1u];
149 return (payment.isMember(jss::tx_json)) &&
150 (payment[jss::tx_json][jss::TransactionType] ==
152 (payment[jss::tx_json][jss::DeliverMax] ==
154 (!payment[jss::tx_json].isMember(jss::Amount)) &&
155 (!payment[jss::tx_json].isMember(jss::hash)) &&
156 (payment[jss::hash] ==
157 "9F3085D85F472D1CC29627F260DF68EDE59D42D1D0C33E345"
158 "ECF0D4CE981D0A8") &&
159 (payment[jss::validated] ==
true) &&
160 (payment[jss::ledger_index] == 3) &&
161 (payment[jss::ledger_hash] ==
162 "5476DCD816EA04CBBA57D47BBF1FC58A5217CC93A5ADD79CB"
163 "580A5AFDD727E33") &&
164 (payment[jss::close_time_iso] ==
165 "2000-01-01T00:00:10Z");
176 return j.isMember(jss::result) &&
177 (j[jss::result][jss::status] ==
"success") &&
178 (j[jss::result][jss::transactions].size() == 0);
183 j[jss::result].
isMember(jss::error) &&
188 jParms[jss::api_version] = apiVersion;
194 jParms[jss::account] =
"0xDEADBEEF";
200 jParms[jss::account] = A1.human();
201 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(jParms))));
206 p[jss::ledger_index_min] = -1;
207 p[jss::ledger_index_max] = -1;
208 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
210 p[jss::ledger_index_min] = 0;
211 p[jss::ledger_index_max] = 100;
220 p[jss::ledger_index_min] = 1;
221 p[jss::ledger_index_max] = 2;
230 p[jss::ledger_index_min] = 2;
231 p[jss::ledger_index_max] = 1;
240 p[jss::ledger_index_min] = -1;
241 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
243 p[jss::ledger_index_min] = 1;
252 p[jss::ledger_index_min] = env.
current()->info().seq;
262 p[jss::ledger_index_max] = -1;
263 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
265 p[jss::ledger_index_max] = env.
current()->info().seq;
274 p[jss::ledger_index_max] = 3;
275 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
277 p[jss::ledger_index_max] = env.
closed()->info().seq;
278 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
280 p[jss::ledger_index_max] = env.
closed()->info().seq - 1;
281 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
288 p[jss::ledger_index] = env.
closed()->info().seq;
289 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
291 p[jss::ledger_index] = env.
closed()->info().seq - 1;
292 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
294 p[jss::ledger_index] = env.
current()->info().seq;
299 p[jss::ledger_index] = env.
current()->info().seq + 1;
309 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
312 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
318 jParms[jss::account] =
"0xDEADBEEF";
319 jParms[jss::account] = A1.human();
322 p[jss::ledger_index_max] = -1;
323 p[jss::ledger_index_min] = -1;
324 p[jss::ledger_index] = -1;
338 p[jss::ledger_index_max] = env.
current()->info().seq;
350 p[jss::binary] =
"asdf";
354 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
361 p[jss::binary] =
true;
363 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
365 p[jss::forward] =
"true";
367 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
373 p[jss::forward] =
false;
375 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
384 using namespace test::jtx;
385 using namespace std::chrono_literals;
391 auto const USD{gw[
"USD"]};
393 env.
fund(
XRP(1000000), alice, gw);
400 env(pay(alice, gw,
XRP(100)));
407 env(trust(alice, USD(200)),
sig(alie));
409 env(offer(alice, USD(50),
XRP(150)),
sig(alie));
416 env(signers(alice, 1, {{
"bogie", 1}, {
"demon", 1}}),
sig(alie));
421 auto escrow = [](
Account const& account,
425 escro[jss::TransactionType] = jss::EscrowCreate;
427 escro[jss::Account] = account.human();
428 escro[jss::Destination] = to.human();
437 nextTime.time_since_epoch().count();
440 env(escrowWithFinish,
sig(alie));
444 nextTime.time_since_epoch().count();
446 nextTime.time_since_epoch().count() + 1;
449 env(escrowWithCancel,
sig(alie));
454 escrowFinish[jss::TransactionType] = jss::EscrowFinish;
456 escrowFinish[jss::Account] = alice.human();
459 env(escrowFinish,
sig(alie));
463 escrowCancel[jss::TransactionType] = jss::EscrowCancel;
465 escrowCancel[jss::Account] = alice.human();
468 env(escrowCancel,
sig(alie));
477 payChanCreate[jss::TransactionType] = jss::PaymentChannelCreate;
479 payChanCreate[jss::Account] = alice.human();
480 payChanCreate[jss::Destination] = gw.human();
481 payChanCreate[jss::Amount] =
486 env(payChanCreate,
sig(alie));
494 payChanFund[jss::TransactionType] = jss::PaymentChannelFund;
496 payChanFund[jss::Account] = alice.human();
498 payChanFund[jss::Amount] =
500 env(payChanFund,
sig(alie));
505 payChanClaim[jss::TransactionType] = jss::PaymentChannelClaim;
506 payChanClaim[jss::Flags] =
tfClose;
507 payChanClaim[jss::Account] = gw.human();
518 env(check::create(alice, gw,
XRP(300)),
sig(alie));
521 env(check::create(gw, alice,
XRP(200)));
524 env(check::cash(alice, gwCheckId,
XRP(200)),
sig(alie));
525 env(check::cancel(alice, aliceCheckId),
sig(alie));
531 env(ticket::create(alice, 1),
sig(alie));
540 params[jss::account] = alice.human();
541 params[jss::ledger_index_min] = -1;
542 params[jss::ledger_index_max] = -1;
547 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
548 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
550 Json::Value const& txs{result[jss::result][jss::transactions]};
557 {0, jss::DepositPreauth, {jss::DepositPreauth}, {jss::Ticket}, {jss::AccountRoot, jss::DirectoryNode}},
558 {1, jss::TicketCreate, {jss::Ticket}, {}, {jss::AccountRoot, jss::DirectoryNode}},
559 {2, jss::CheckCancel, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
560 {3, jss::CheckCash, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
561 {4, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
562 {5, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
563 {6, jss::PaymentChannelClaim, {}, {jss::PayChannel}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
564 {7, jss::PaymentChannelFund, {}, {}, {jss::AccountRoot, jss::PayChannel}},
565 {8, jss::PaymentChannelCreate, {jss::PayChannel}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
566 {9, jss::EscrowCancel, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
567 {10, jss::EscrowFinish, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
568 {11, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
569 {12, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
570 {13, jss::SignerListSet, {jss::SignerList}, {}, {jss::AccountRoot, jss::DirectoryNode}},
571 {14, jss::OfferCancel, {}, {jss::Offer, jss::DirectoryNode}, {jss::AccountRoot, jss::DirectoryNode}},
572 {15, jss::OfferCreate, {jss::Offer, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::DirectoryNode}},
573 {16, jss::TrustSet, {jss::RippleState, jss::DirectoryNode, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::AccountRoot}},
574 {17, jss::SetRegularKey, {}, {}, {jss::AccountRoot}},
575 {18, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
576 {19, jss::AccountSet, {}, {}, {jss::AccountRoot}},
577 {20, jss::AccountSet, {}, {}, {jss::AccountRoot}},
578 {21, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
583 std::size(sanity) == result[jss::result][jss::transactions].size());
585 for (
unsigned int index{0}; index <
std::size(sanity); ++index)
597 using namespace test::jtx;
598 using namespace std::chrono_literals;
604 env.
fund(
XRP(10000), alice, becky);
609 BEAST_EXPECT(env.
closed()->exists(beckyAcctKey));
621 auto const beckyPreDelBalance{env.
balance(becky)};
623 auto const acctDelFee{
drops(env.
current()->fees().increment)};
628 BEAST_EXPECT(!env.
closed()->exists(beckyAcctKey));
640 { 0, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
641 { 1, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
642 { 2, jss::AccountDelete, {}, {jss::AccountRoot}, {jss::AccountRoot}},
643 { 3, jss::AccountSet, {}, {}, {jss::AccountRoot}},
644 { 4, jss::AccountSet, {}, {}, {jss::AccountRoot}},
645 { 5, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}}
653 params[jss::account] = becky.human();
654 params[jss::ledger_index_min] = -1;
655 params[jss::ledger_index_max] = -1;
660 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
661 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
664 constexpr
unsigned int beckyDeletedOffest = 2;
667 result[jss::result][jss::transactions].size() +
670 Json::Value const& txs{result[jss::result][jss::transactions]};
672 for (
unsigned int index = beckyDeletedOffest;
676 checkSanity(txs[index - beckyDeletedOffest], sanity[index]);
689 env(pay(alice, becky,
XRP(45)));
693 BEAST_EXPECT(env.
closed()->exists(beckyAcctKey));
697 env(pay(becky, alice,
XRP(20)));
703 params[jss::account] = becky.human();
704 params[jss::ledger_index_min] = -1;
705 params[jss::ledger_index_max] = -1;
710 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
711 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
714 std::size(sanity) == result[jss::result][jss::transactions].size());
716 Json::Value const& txs{result[jss::result][jss::transactions]};
718 for (
unsigned int index = 0; index <
std::size(sanity); ++index)