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) &&
150 jParms[jss::account] =
"0xDEADBEEF";
156 jParms[jss::account] = A1.human();
157 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(jParms))));
162 p[jss::ledger_index_min] = -1;
163 p[jss::ledger_index_max] = -1;
164 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
166 p[jss::ledger_index_min] = 0;
167 p[jss::ledger_index_max] = 100;
168 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
170 p[jss::ledger_index_min] = 1;
171 p[jss::ledger_index_max] = 2;
172 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
174 p[jss::ledger_index_min] = 2;
175 p[jss::ledger_index_max] = 1;
184 p[jss::ledger_index_min] = -1;
185 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
187 p[jss::ledger_index_min] = 1;
188 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
190 p[jss::ledger_index_min] = env.
current()->info().seq;
199 p[jss::ledger_index_max] = -1;
200 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
202 p[jss::ledger_index_max] = env.
current()->info().seq;
203 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
205 p[jss::ledger_index_max] = env.
closed()->info().seq;
206 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
208 p[jss::ledger_index_max] = env.
closed()->info().seq - 1;
209 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
216 p[jss::ledger_index] = env.
closed()->info().seq;
217 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
219 p[jss::ledger_index] = env.
closed()->info().seq - 1;
220 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
222 p[jss::ledger_index] = env.
current()->info().seq;
227 p[jss::ledger_index] = env.
current()->info().seq + 1;
237 BEAST_EXPECT(hasTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
240 BEAST_EXPECT(noTxs(env.
rpc(
"json",
"account_tx",
to_string(p))));
249 using namespace test::jtx;
250 using namespace std::chrono_literals;
256 auto const USD{gw[
"USD"]};
258 env.
fund(
XRP(1000000), alice, gw);
265 env(
pay(alice, gw,
XRP(100)));
272 env(
trust(alice, USD(200)),
sig(alie));
274 env(offer(alice, USD(50),
XRP(150)),
sig(alie));
279 cancelOffer[jss::Account] = alice.human();
280 cancelOffer[jss::OfferSequence] = offerSeq;
281 cancelOffer[jss::TransactionType] = jss::OfferCancel;
282 env(cancelOffer,
sig(alie));
287 env(signers(alice, 1, {{
"bogie", 1}, {
"demon", 1}}),
sig(alie));
292 auto escrow = [](
Account const& account,
296 escro[jss::TransactionType] = jss::EscrowCreate;
298 escro[jss::Account] = account.human();
299 escro[jss::Destination] = to.human();
308 nextTime.time_since_epoch().count();
311 env(escrowWithFinish,
sig(alie));
315 nextTime.time_since_epoch().count();
317 nextTime.time_since_epoch().count() + 1;
320 env(escrowWithCancel,
sig(alie));
325 escrowFinish[jss::TransactionType] = jss::EscrowFinish;
327 escrowFinish[jss::Account] = alice.human();
330 env(escrowFinish,
sig(alie));
334 escrowCancel[jss::TransactionType] = jss::EscrowCancel;
336 escrowCancel[jss::Account] = alice.human();
339 env(escrowCancel,
sig(alie));
348 payChanCreate[jss::TransactionType] = jss::PaymentChannelCreate;
350 payChanCreate[jss::Account] = alice.human();
351 payChanCreate[jss::Destination] = gw.human();
352 payChanCreate[jss::Amount] =
357 env(payChanCreate,
sig(alie));
365 payChanFund[jss::TransactionType] = jss::PaymentChannelFund;
367 payChanFund[jss::Account] = alice.human();
369 payChanFund[jss::Amount] =
371 env(payChanFund,
sig(alie));
376 payChanClaim[jss::TransactionType] = jss::PaymentChannelClaim;
377 payChanClaim[jss::Flags] =
tfClose;
378 payChanClaim[jss::Account] = gw.human();
389 env(check::create(alice, gw,
XRP(300)),
sig(alie));
392 env(check::create(gw, alice,
XRP(200)));
395 env(check::cash(alice, gwCheckId,
XRP(200)),
sig(alie));
396 env(check::cancel(alice, aliceCheckId),
sig(alie));
401 env(deposit::auth(alice, gw),
sig(alie));
406 params[jss::account] = alice.human();
407 params[jss::ledger_index_min] = -1;
408 params[jss::ledger_index_max] = -1;
413 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
414 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
416 Json::Value const& txs{result[jss::result][jss::transactions]};
423 { 0, jss::DepositPreauth, {jss::DepositPreauth}, {}, {jss::AccountRoot, jss::DirectoryNode}},
424 { 1, jss::CheckCancel, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
425 { 2, jss::CheckCash, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
426 { 3, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
427 { 4, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
428 { 5, jss::PaymentChannelClaim, {}, {jss::PayChannel}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
429 { 6, jss::PaymentChannelFund, {}, {}, {jss::AccountRoot, jss::PayChannel }},
430 { 7, jss::PaymentChannelCreate, {jss::PayChannel}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}},
431 { 8, jss::EscrowCancel, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
432 { 9, jss::EscrowFinish, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}},
433 { 10, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
434 { 11, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},
435 { 12, jss::SignerListSet, {jss::SignerList}, {}, {jss::AccountRoot, jss::DirectoryNode}},
436 { 13, jss::OfferCancel, {}, {jss::Offer, jss::DirectoryNode}, {jss::AccountRoot, jss::DirectoryNode}},
437 { 14, jss::OfferCreate, {jss::Offer, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::DirectoryNode}},
438 { 15, jss::TrustSet, {jss::RippleState, jss::DirectoryNode, jss::DirectoryNode}, {}, {jss::AccountRoot, jss::AccountRoot}},
439 { 16, jss::SetRegularKey, {}, {}, {jss::AccountRoot}},
440 { 17, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
441 { 18, jss::AccountSet, {}, {}, {jss::AccountRoot}},
442 { 19, jss::AccountSet, {}, {}, {jss::AccountRoot}},
443 { 20, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
448 std::size(sanity) == result[jss::result][jss::transactions].size());
450 for (
unsigned int index{0}; index <
std::size(sanity); ++index)
462 using namespace test::jtx;
463 using namespace std::chrono_literals;
469 env.
fund(
XRP(10000), alice, becky);
474 BEAST_EXPECT(env.
closed()->exists(beckyAcctKey));
486 auto const beckyPreDelBalance{env.
balance(becky)};
488 auto const acctDelFee{
drops(env.
current()->fees().increment)};
493 BEAST_EXPECT(!env.
closed()->exists(beckyAcctKey));
505 { 0, jss::Payment, {}, {}, {jss::AccountRoot, jss::AccountRoot}},
506 { 1, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}},
507 { 2, jss::AccountDelete, {}, {jss::AccountRoot}, {jss::AccountRoot}},
508 { 3, jss::AccountSet, {}, {}, {jss::AccountRoot}},
509 { 4, jss::AccountSet, {}, {}, {jss::AccountRoot}},
510 { 5, jss::Payment, {jss::AccountRoot}, {}, {jss::AccountRoot}}
518 params[jss::account] = becky.human();
519 params[jss::ledger_index_min] = -1;
520 params[jss::ledger_index_max] = -1;
525 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
526 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
529 constexpr
unsigned int beckyDeletedOffest = 2;
532 result[jss::result][jss::transactions].size() +
535 Json::Value const& txs{result[jss::result][jss::transactions]};
537 for (
unsigned int index = beckyDeletedOffest;
541 checkSanity(txs[index - beckyDeletedOffest], sanity[index]);
551 env(
pay(alice, becky,
XRP(45)));
555 BEAST_EXPECT(env.
closed()->exists(beckyAcctKey));
559 env(
pay(becky, alice,
XRP(20)));
565 params[jss::account] = becky.human();
566 params[jss::ledger_index_min] = -1;
567 params[jss::ledger_index_max] = -1;
572 BEAST_EXPECT(result[jss::result][jss::status] ==
"success");
573 BEAST_EXPECT(result[jss::result][jss::transactions].isArray());
576 std::size(sanity) == result[jss::result][jss::transactions].size());
578 Json::Value const& txs{result[jss::result][jss::transactions]};
580 for (
unsigned int index = 0; index <
std::size(sanity); ++index)