20 #include <ripple/app/misc/Manifest.h>
21 #include <ripple/app/misc/TxQ.h>
22 #include <ripple/basics/StringUtilities.h>
23 #include <ripple/beast/unit_test.h>
24 #include <ripple/protocol/ErrorCodes.h>
25 #include <ripple/protocol/jss.h>
26 #include <ripple/rpc/impl/RPCHelpers.h>
39 if (BEAST_EXPECT(jv.
isMember(jss::status)))
40 BEAST_EXPECT(jv[jss::status] ==
"error");
41 if (BEAST_EXPECT(jv.
isMember(jss::error)))
42 BEAST_EXPECT(jv[jss::error] == err);
47 jv[jss::error_message] ==
"");
49 else if (BEAST_EXPECT(jv.
isMember(jss::error_message)))
50 BEAST_EXPECT(jv[jss::error_message] == msg);
66 testcase(
"Basic Request");
67 using namespace test::jtx;
72 BEAST_EXPECT(env.current()->info().seq == 4);
77 jvParams[jss::ledger_index] = 1;
79 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
80 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
true);
81 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"1");
86 jvParams[jss::ledger_index] =
"1";
88 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
89 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
true);
90 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"1");
95 auto const jrr = env.rpc(
"ledger",
"current")[jss::result];
96 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
false);
98 jrr[jss::ledger][jss::ledger_index] ==
101 jrr[jss::ledger_current_index] == env.current()->info().seq);
108 testcase(
"Bad Input");
109 using namespace test::jtx;
111 Account
const gw{
"gateway"};
112 auto const USD = gw[
"USD"];
113 Account
const bob{
"bob"};
115 env.fund(XRP(10000), gw, bob);
117 env.trust(USD(1000), bob);
123 jvParams[jss::ledger_index] =
"potato";
125 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
132 jvParams[jss::ledger_index] = -1;
134 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
141 jvParams[jss::ledger_index] = 10u;
143 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
149 auto const jrr = env.rpc(
"ledger",
"arbitrary_text")[jss::result];
156 jvParams[jss::ledger_index] =
"validated";
157 jvParams[jss::queue] =
true;
159 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
166 env.rpc(
"json",
"ledger",
"{ \"ledger_index\" : 2e15 }");
168 BEAST_EXPECT(ret[jss::error_message] ==
"Invalid parameters.");
173 auto const ret = env.rpc(
174 "json",
"ledger",
"{ \"ledger_index\" : 1000000000000000 }");
182 testcase(
"ledger_current Request");
183 using namespace test::jtx;
188 BEAST_EXPECT(env.current()->info().seq == 4);
191 auto const jrr = env.rpc(
"ledger_current")[jss::result];
193 jrr[jss::ledger_current_index] == env.current()->info().seq);
200 testcase(
"Missing ledger_entry ledger_hash");
201 using namespace test::jtx;
203 Account
const alice{
"alice"};
204 env.fund(XRP(10000), alice);
208 jvParams[jss::account_root] = alice.human();
209 jvParams[jss::ledger_hash] =
210 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
212 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
219 testcase(
"Ledger Request, Full Option");
220 using namespace test::jtx;
227 jvParams[jss::ledger_index] = 3u;
228 jvParams[jss::full] =
true;
230 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
231 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
232 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
233 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u);
239 testcase(
"Ledger Request, Full Option Without Admin");
240 using namespace test::jtx;
242 Env env{*
this, envconfig(no_admin)};
247 jvParams[jss::ledger_index] = 1u;
248 jvParams[jss::full] =
true;
250 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
252 jrr,
"noPermission",
"You don't have permission for this command.");
258 testcase(
"Ledger Request, Accounts Option");
259 using namespace test::jtx;
266 jvParams[jss::ledger_index] = 3u;
267 jvParams[jss::accounts] =
true;
269 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
270 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
271 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
272 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u);
278 testcase(
"ledger_entry Request AccountRoot");
279 using namespace test::jtx;
281 Account
const alice{
"alice"};
282 env.fund(XRP(10000), alice);
288 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
289 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
290 BEAST_EXPECT(jrr[jss::ledger_index] == 3);
297 jvParams[jss::account_root] = alice.human();
298 jvParams[jss::ledger_hash] = ledgerHash;
300 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
301 BEAST_EXPECT(jrr.
isMember(jss::node));
302 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
304 accountRootIndex = jrr[jss::index].
asString();
307 constexpr
char alicesAcctRootBinary[]{
308 "1100612200800000240000000425000000032D00000000559CE54C3B934E4"
309 "73A995B477E92EC229F99CED5B62BF4D2ACE4DC42719103AE2F6240000002"
310 "540BE4008114AE123A8556F3CF91154711376AFB0F894F832B3D"};
314 jvParams[jss::account_root] = alice.human();
315 jvParams[jss::binary] = 1;
316 jvParams[jss::ledger_hash] = ledgerHash;
318 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
319 BEAST_EXPECT(jrr.
isMember(jss::node_binary));
320 BEAST_EXPECT(jrr[jss::node_binary] == alicesAcctRootBinary);
325 jvParams[jss::index] = accountRootIndex;
327 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
328 BEAST_EXPECT(!jrr.
isMember(jss::node_binary));
329 BEAST_EXPECT(jrr.
isMember(jss::node));
330 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
336 jvParams[jss::index] = accountRootIndex;
337 jvParams[jss::binary] = 0;
339 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
340 BEAST_EXPECT(jrr.
isMember(jss::node));
341 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
348 jvParams[jss::ledger_hash] = ledgerHash;
350 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
356 jvParams[jss::account_root] = Account(
"bob").human();
357 jvParams[jss::ledger_hash] = ledgerHash;
359 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
367 testcase(
"ledger_entry Request Check");
368 using namespace test::jtx;
370 Account
const alice{
"alice"};
371 env.fund(XRP(10000), alice);
374 auto const checkId =
keylet::check(env.master, env.seq(env.master));
376 env(check::create(env.master, alice, XRP(100)));
383 jvParams[jss::check] =
to_string(checkId.key);
384 jvParams[jss::ledger_hash] = ledgerHash;
386 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
397 jvParams[jss::account_root] = alice.human();
399 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
400 accountRootIndex = jrr[jss::index].
asString();
403 jvParams[jss::check] = accountRootIndex;
404 jvParams[jss::ledger_hash] = ledgerHash;
406 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
414 testcase(
"ledger_entry Deposit Preauth");
416 using namespace test::jtx;
419 Account
const alice{
"alice"};
420 Account
const becky{
"becky"};
422 env.fund(XRP(10000), alice, becky);
425 env(deposit::auth(alice, becky));
433 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
434 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
435 jvParams[jss::ledger_hash] = ledgerHash;
437 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
441 jss::DepositPreauth);
444 depositPreauthIndex = jrr[jss::node][jss::index].
asString();
449 jvParams[jss::deposit_preauth] = depositPreauthIndex;
450 jvParams[jss::ledger_hash] = ledgerHash;
452 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
456 jss::DepositPreauth);
463 jvParams[jss::deposit_preauth] = -5;
464 jvParams[jss::ledger_hash] = ledgerHash;
466 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
472 jvParams[jss::deposit_preauth] =
"0123456789ABCDEFG";
473 jvParams[jss::ledger_hash] = ledgerHash;
475 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
481 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
482 jvParams[jss::ledger_hash] = ledgerHash;
484 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
490 jvParams[jss::deposit_preauth][jss::owner] = 7;
491 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
492 jvParams[jss::ledger_hash] = ledgerHash;
494 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
500 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
501 jvParams[jss::ledger_hash] = ledgerHash;
503 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
509 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
510 jvParams[jss::deposit_preauth][jss::authorized] = 47;
511 jvParams[jss::ledger_hash] = ledgerHash;
513 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
519 jvParams[jss::deposit_preauth][jss::owner] =
520 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
522 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
523 jvParams[jss::ledger_hash] = ledgerHash;
525 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
531 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
532 jvParams[jss::deposit_preauth][jss::authorized] =
533 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
535 jvParams[jss::ledger_hash] = ledgerHash;
537 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
545 testcase(
"ledger_entry Request Directory");
546 using namespace test::jtx;
548 Account
const alice{
"alice"};
549 Account
const gw{
"gateway"};
550 auto const USD = gw[
"USD"];
551 env.fund(XRP(10000), alice, gw);
554 env.trust(USD(1000), alice);
559 for (
int d = 1
'000'032; d >= 1
'000'000; --d)
561 env(offer(alice, USD(1), drops(d)));
568 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
569 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
570 BEAST_EXPECT(jrr[jss::ledger_index] == 5);
574 "A33EC6BB85FB5674074C4A3A43373BB17645308F3EAE1933E3E35252162B217D";
578 jvParams[jss::directory] = dirRootIndex;
579 jvParams[jss::ledger_hash] = ledgerHash;
581 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
588 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
590 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
591 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
597 jvParams[jss::directory][jss::owner] = alice.human();
598 jvParams[jss::ledger_hash] = ledgerHash;
600 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
601 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
607 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
608 jvParams[jss::directory][jss::sub_index] = 1;
610 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
611 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
618 jvParams[jss::directory][jss::owner] = alice.human();
619 jvParams[jss::directory][jss::sub_index] = 1;
620 jvParams[jss::ledger_hash] = ledgerHash;
622 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
623 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
630 jvParams[jss::ledger_hash] = ledgerHash;
632 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
639 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
640 jvParams[jss::directory][jss::sub_index] = 1.5;
641 jvParams[jss::ledger_hash] = ledgerHash;
643 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
652 jvParams[jss::directory][jss::owner] = badAddress;
653 jvParams[jss::ledger_hash] = ledgerHash;
655 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
662 jvParams[jss::directory][jss::owner] = alice.human();
663 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
664 jvParams[jss::ledger_hash] = ledgerHash;
666 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
673 jvParams[jss::directory][jss::sub_index] = 1;
674 jvParams[jss::ledger_hash] = ledgerHash;
676 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
684 testcase(
"ledger_entry Request Escrow");
685 using namespace test::jtx;
687 Account
const alice{
"alice"};
688 env.fund(XRP(10000), alice);
697 jv[jss::TransactionType] = jss::EscrowCreate;
699 jv[jss::Account] = account.human();
700 jv[jss::Destination] = to.human();
703 cancelAfter.time_since_epoch().count() + 2;
707 using namespace std::chrono_literals;
708 env(escrowCreate(alice, alice, XRP(333), env.now() + 2s));
717 jvParams[jss::escrow][jss::owner] = alice.human();
718 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
720 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
722 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
723 escrowIndex = jrr[jss::index].
asString();
728 jvParams[jss::escrow] = escrowIndex;
729 jvParams[jss::ledger_hash] = ledgerHash;
731 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
733 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
741 jvParams[jss::escrow][jss::owner] = badAddress;
742 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
743 jvParams[jss::ledger_hash] = ledgerHash;
745 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
752 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
753 jvParams[jss::ledger_hash] = ledgerHash;
755 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
762 jvParams[jss::escrow][jss::owner] = alice.human();
763 jvParams[jss::ledger_hash] = ledgerHash;
765 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
772 jvParams[jss::escrow][jss::owner] = alice.human();
773 jvParams[jss::escrow][jss::seq] =
775 jvParams[jss::ledger_hash] = ledgerHash;
777 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
785 testcase(
"ledger_entry Request Offer");
786 using namespace test::jtx;
788 Account
const alice{
"alice"};
789 Account
const gw{
"gateway"};
790 auto const USD = gw[
"USD"];
791 env.fund(XRP(10000), alice, gw);
794 env(offer(alice, USD(321), XRP(322)));
803 jvParams[jss::offer][jss::account] = alice.human();
804 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
805 jvParams[jss::ledger_hash] = ledgerHash;
807 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
808 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
809 offerIndex = jrr[jss::index].
asString();
814 jvParams[jss::offer] = offerIndex;
816 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
817 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
825 jvParams[jss::offer][jss::account] = badAddress;
826 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
827 jvParams[jss::ledger_hash] = ledgerHash;
829 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
836 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
837 jvParams[jss::ledger_hash] = ledgerHash;
839 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
846 jvParams[jss::offer][jss::account] = alice.human();
847 jvParams[jss::ledger_hash] = ledgerHash;
849 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
856 jvParams[jss::offer][jss::account] = alice.human();
857 jvParams[jss::offer][jss::seq] =
std::to_string(env.seq(alice) - 1);
858 jvParams[jss::ledger_hash] = ledgerHash;
860 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
868 testcase(
"ledger_entry Request Pay Chan");
869 using namespace test::jtx;
870 using namespace std::literals::chrono_literals;
872 Account
const alice{
"alice"};
874 env.fund(XRP(10000), alice);
884 jv[jss::TransactionType] = jss::PaymentChannelCreate;
885 jv[jss::Account] = account.human();
886 jv[jss::Destination] = to.human();
893 env(payChanCreate(alice, env.master, XRP(57), 18s, alice.pk()));
903 jvParams[jss::payment_channel] =
to_string(payChanIndex);
904 jvParams[jss::ledger_hash] = ledgerHash;
906 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
914 jvParams[jss::payment_channel] = ledgerHash;
915 jvParams[jss::ledger_hash] = ledgerHash;
917 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
925 testcase(
"ledger_entry Request RippleState");
926 using namespace test::jtx;
928 Account
const alice{
"alice"};
929 Account
const gw{
"gateway"};
930 auto const USD = gw[
"USD"];
931 env.fund(XRP(10000), alice, gw);
934 env.trust(USD(999), alice);
937 env(pay(gw, alice, USD(97)));
946 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
947 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
948 jvParams[jss::ripple_state][jss::currency] =
"USD";
949 jvParams[jss::ledger_hash] = ledgerHash;
951 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
960 jvParams[jss::ripple_state] =
"ripple_state";
961 jvParams[jss::ledger_hash] = ledgerHash;
963 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
971 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
972 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
973 jvParams[jss::ledger_hash] = ledgerHash;
975 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
982 jvParams[jss::ripple_state][jss::accounts] = 2;
983 jvParams[jss::ripple_state][jss::currency] =
"USD";
984 jvParams[jss::ledger_hash] = ledgerHash;
986 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
994 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
995 jvParams[jss::ripple_state][jss::currency] =
"USD";
996 jvParams[jss::ledger_hash] = ledgerHash;
998 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1006 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1007 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1008 jvParams[jss::ripple_state][jss::accounts][2u] = alice.human();
1009 jvParams[jss::ripple_state][jss::currency] =
"USD";
1010 jvParams[jss::ledger_hash] = ledgerHash;
1012 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1020 jvParams[jss::ripple_state][jss::accounts][0u] = 44;
1021 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1022 jvParams[jss::ripple_state][jss::currency] =
"USD";
1023 jvParams[jss::ledger_hash] = ledgerHash;
1025 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1033 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1034 jvParams[jss::ripple_state][jss::accounts][1u] = 21;
1035 jvParams[jss::ripple_state][jss::currency] =
"USD";
1036 jvParams[jss::ledger_hash] = ledgerHash;
1038 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1046 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1047 jvParams[jss::ripple_state][jss::accounts][1u] = alice.human();
1048 jvParams[jss::ripple_state][jss::currency] =
"USD";
1049 jvParams[jss::ledger_hash] = ledgerHash;
1051 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1059 jvParams[jss::ripple_state][jss::accounts][0u] =
1061 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1062 jvParams[jss::ripple_state][jss::currency] =
"USD";
1063 jvParams[jss::ledger_hash] = ledgerHash;
1065 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1073 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1074 jvParams[jss::ripple_state][jss::accounts][1u] =
1076 jvParams[jss::ripple_state][jss::currency] =
"USD";
1077 jvParams[jss::ledger_hash] = ledgerHash;
1079 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1087 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1088 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1089 jvParams[jss::ripple_state][jss::currency] =
"USDollars";
1090 jvParams[jss::ledger_hash] = ledgerHash;
1092 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1100 testcase(
"ledger_entry Request Ticket");
1101 using namespace test::jtx;
1107 env(ticket::create(env.master, 2));
1117 jvParams[jss::ticket] =
1119 jvParams[jss::ledger_hash] = ledgerHash;
1121 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1128 jvParams[jss::ledger_hash] = ledgerHash;
1130 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1139 jvParams[jss::ticket][jss::account] = env.master.human();
1140 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 1;
1141 jvParams[jss::ledger_hash] = ledgerHash;
1143 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1145 jrr[jss::node][jss::index] ==
1152 jvParams[jss::ticket][jss::account] = env.master.human();
1153 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 2;
1154 jvParams[jss::ledger_hash] = ledgerHash;
1156 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1163 jvParams[jss::ledger_hash] = ledgerHash;
1165 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1174 jvParams[jss::ticket][jss::account] = badAddress;
1175 jvParams[jss::ticket][jss::ticket_seq] = env.seq(env.master) - 1;
1176 jvParams[jss::ledger_hash] = ledgerHash;
1178 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1185 jvParams[jss::ticket][jss::ticket_seq] = env.seq(env.master) - 1;
1186 jvParams[jss::ledger_hash] = ledgerHash;
1188 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1195 jvParams[jss::ticket][jss::account] = env.master.human();
1196 jvParams[jss::ledger_hash] = ledgerHash;
1198 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1205 jvParams[jss::ticket][jss::account] = env.master.human();
1206 jvParams[jss::ticket][jss::ticket_seq] =
1208 jvParams[jss::ledger_hash] = ledgerHash;
1210 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1219 "ledger_entry Request With Invalid Parameters v" +
1221 using namespace test::jtx;
1228 jvParams[jss::api_version] = apiVersion;
1229 jvParams[jss::features] = ledgerHash;
1230 jvParams[jss::ledger_hash] = ledgerHash;
1232 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1234 if (apiVersion < 2u)
1247 testcase(
"Lookup ledger");
1248 using namespace test::jtx;
1251 env.fund(XRP(10000),
"alice");
1253 env.fund(XRP(10000),
"bob");
1255 env.fund(XRP(10000),
"jim");
1257 env.fund(XRP(10000),
"jill");
1262 jvParams[jss::ledger] =
"closed";
1266 boost::lexical_cast<std::string>(jvParams))[jss::result];
1267 BEAST_EXPECT(jrr.isMember(jss::ledger));
1268 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1269 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1271 jvParams[jss::ledger] =
"validated";
1275 boost::lexical_cast<std::string>(jvParams))[jss::result];
1276 BEAST_EXPECT(jrr.isMember(jss::ledger));
1277 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1278 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1280 jvParams[jss::ledger] =
"current";
1284 boost::lexical_cast<std::string>(jvParams))[jss::result];
1285 BEAST_EXPECT(jrr.isMember(jss::ledger));
1286 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1289 jvParams[jss::ledger] =
"invalid";
1293 boost::lexical_cast<std::string>(jvParams))[jss::result];
1294 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1295 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1298 jvParams[jss::ledger] = 4;
1302 boost::lexical_cast<std::string>(jvParams))[jss::result];
1303 BEAST_EXPECT(jrr.isMember(jss::ledger));
1304 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1305 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"4");
1308 jvParams[jss::ledger] = 20;
1312 boost::lexical_cast<std::string>(jvParams))[jss::result];
1313 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1314 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1319 "E86DE7F3D7A4D9CE17EF7C8BA08A8F4D"
1320 "8F643B9552F0D895A31CDA78F541DE4E"};
1323 jvParams[jss::ledger_hash] = hash3;
1327 boost::lexical_cast<std::string>(jvParams))[jss::result];
1328 BEAST_EXPECT(jrr.isMember(jss::ledger));
1329 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1330 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"3");
1333 jvParams[jss::ledger_hash] =
"DEADBEEF" + hash3;
1337 boost::lexical_cast<std::string>(jvParams))[jss::result];
1338 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1339 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1342 jvParams[jss::ledger_hash] = 2;
1346 boost::lexical_cast<std::string>(jvParams))[jss::result];
1347 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1348 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashNotString");
1351 jvParams[jss::ledger_hash] =
1352 "2E81FC6EC0DD943197EGC7E3FBE9AE30"
1353 "7F2775F2F7485BB37307984C3C0F2340";
1357 boost::lexical_cast<std::string>(jvParams))[jss::result];
1358 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1359 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1362 jvParams[jss::ledger_hash] =
1363 "8C3EEDB3124D92E49E75D81A8826A2E6"
1364 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1368 boost::lexical_cast<std::string>(jvParams))[jss::result];
1369 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1370 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1376 jvParams[jss::ledger_index] =
"closed";
1380 boost::lexical_cast<std::string>(jvParams))[jss::result];
1381 BEAST_EXPECT(jrr.isMember(jss::ledger));
1382 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1383 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1384 BEAST_EXPECT(jrr.isMember(jss::ledger_index));
1386 jvParams[jss::ledger_index] =
"validated";
1390 boost::lexical_cast<std::string>(jvParams))[jss::result];
1391 BEAST_EXPECT(jrr.isMember(jss::ledger));
1392 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1393 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1395 jvParams[jss::ledger_index] =
"current";
1399 boost::lexical_cast<std::string>(jvParams))[jss::result];
1400 BEAST_EXPECT(jrr.isMember(jss::ledger));
1401 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1402 BEAST_EXPECT(jrr.isMember(jss::ledger_current_index));
1405 jvParams[jss::ledger_index] =
"invalid";
1409 boost::lexical_cast<std::string>(jvParams))[jss::result];
1410 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1411 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1414 for (
auto i : {1, 2, 3, 4, 5, 6})
1416 jvParams[jss::ledger_index] = i;
1420 boost::lexical_cast<std::string>(jvParams))[jss::result];
1421 BEAST_EXPECT(jrr.isMember(jss::ledger));
1423 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1429 jvParams[jss::ledger_index] = 7;
1433 boost::lexical_cast<std::string>(jvParams))[jss::result];
1434 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1435 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1442 testcase(
"Ledger with queueing disabled");
1443 using namespace test::jtx;
1447 jv[jss::ledger_index] =
"current";
1448 jv[jss::queue] =
true;
1449 jv[jss::expand] =
true;
1451 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1452 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1458 testcase(
"Ledger with Queued Transactions");
1459 using namespace test::jtx;
1461 auto& section = cfg->section(
"transaction_queue");
1462 section.set(
"minimum_txn_in_ledger_standalone",
"3");
1463 section.set(
"normal_consensus_increase_percent",
"0");
1468 jv[jss::ledger_index] =
"current";
1469 jv[jss::queue] =
true;
1470 jv[jss::expand] =
true;
1472 Account
const alice{
"alice"};
1473 Account
const bob{
"bob"};
1474 Account
const charlie{
"charlie"};
1475 Account
const daria{
"daria"};
1476 env.fund(XRP(10000), alice);
1477 env.fund(XRP(10000), bob);
1479 env.fund(XRP(10000), charlie);
1480 env.fund(XRP(10000), daria);
1483 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1484 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1489 auto metrics = env.app().getTxQ().getMetrics(*env.current());
1490 if (metrics.openLedgerFeeLevel > metrics.minProcessingFeeLevel)
1495 BEAST_EXPECT(env.current()->info().seq == 5);
1498 auto aliceSeq = env.seq(alice);
1499 env(pay(alice,
"george", XRP(1000)),
1500 json(R
"({"LastLedgerSequence":7})"),
1502 env(offer(alice, XRP(50000), alice["USD"](5000)),
1505 env(noop(alice), seq(aliceSeq + 2), ter(
terQUEUED));
1507 auto batch = [&env](Account a) {
1508 auto aSeq = env.seq(a);
1510 for (
int i = 0; i < 10; ++i)
1512 env(noop(a), fee(1000 + i), seq(aSeq + i), ter(
terQUEUED));
1521 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1522 BEAST_EXPECT(jrr[jss::queue_data].size() == 33);
1528 BEAST_EXPECT(env.current()->info().seq == 8);
1530 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1531 BEAST_EXPECT(jrr[jss::queue_data].size() == 11);
1535 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1537 auto const& parentHash = env.current()->info().parentHash;
1538 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1541 auto const& txj = jrr[jss::queue_data][1u];
1542 BEAST_EXPECT(txj[jss::account] == alice.human());
1543 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1544 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1545 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
1546 BEAST_EXPECT(txj.isMember(jss::tx));
1547 auto const& tx = txj[jss::tx];
1548 BEAST_EXPECT(tx[jss::Account] == alice.human());
1549 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
1550 return tx[jss::hash].asString();
1553 auto const& txj = jrr[jss::queue_data][0u];
1554 BEAST_EXPECT(txj[jss::account] == alice.human());
1555 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1556 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1557 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
1558 BEAST_EXPECT(txj.isMember(jss::tx));
1559 auto const& tx = txj[jss::tx];
1560 BEAST_EXPECT(tx[jss::Account] == alice.human());
1561 BEAST_EXPECT(tx[jss::TransactionType] == jss::OfferCreate);
1562 const auto txid0 = tx[jss::hash].asString();
1566 BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash));
1574 jv[jss::expand] =
false;
1576 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1577 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1579 auto const& parentHash = env.current()->info().parentHash;
1580 auto const txid1 = [&]() {
1581 auto const& txj = jrr[jss::queue_data][1u];
1582 BEAST_EXPECT(txj[jss::account] == alice.human());
1583 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1584 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1585 BEAST_EXPECT(txj.isMember(jss::tx));
1586 return txj[jss::tx].asString();
1588 auto const& txj = jrr[jss::queue_data][0u];
1589 BEAST_EXPECT(txj[jss::account] == alice.human());
1590 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1591 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1592 BEAST_EXPECT(txj[
"retries_remaining"] == 9);
1593 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1594 BEAST_EXPECT(txj.isMember(jss::tx));
1595 BEAST_EXPECT(txj[jss::tx] == txid0);
1599 BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash));
1604 jv[jss::expand] =
true;
1605 jv[jss::binary] =
true;
1607 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1608 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1610 auto const& txj = jrr[jss::queue_data][1u];
1611 BEAST_EXPECT(txj[jss::account] == alice.human());
1612 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1613 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1614 BEAST_EXPECT(txj[
"retries_remaining"] == 8);
1615 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1616 BEAST_EXPECT(txj.isMember(jss::tx));
1617 BEAST_EXPECT(txj[jss::tx].isMember(jss::tx_blob));
1619 auto const& txj2 = jrr[jss::queue_data][0u];
1620 BEAST_EXPECT(txj2[jss::account] == alice.human());
1621 BEAST_EXPECT(txj2[jss::fee_level] ==
"256");
1622 BEAST_EXPECT(txj2[
"preflight_result"] ==
"tesSUCCESS");
1623 BEAST_EXPECT(txj2[
"retries_remaining"] == 10);
1624 BEAST_EXPECT(!txj2.isMember(
"last_result"));
1625 BEAST_EXPECT(txj2.isMember(jss::tx));
1626 BEAST_EXPECT(txj2[jss::tx].isMember(jss::tx_blob));
1629 for (
int i = 0; i != 9; ++i)
1634 jv[jss::expand] =
false;
1635 jv[jss::binary] =
false;
1637 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1639 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1641 auto const& txj = jrr[jss::queue_data][0u];
1642 BEAST_EXPECT(txj[jss::account] == alice.human());
1643 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1644 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1645 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1646 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1647 BEAST_EXPECT(txj.isMember(jss::tx));
1648 BEAST_EXPECT(txj[jss::tx] != txid0);
1649 return txj[jss::tx].asString();
1654 jv[jss::full] =
true;
1656 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1657 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1659 auto const& txj = jrr[jss::queue_data][0u];
1660 BEAST_EXPECT(txj[jss::account] == alice.human());
1661 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1662 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1663 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1664 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1665 BEAST_EXPECT(txj.isMember(jss::tx));
1666 auto const& tx = txj[jss::tx];
1667 BEAST_EXPECT(tx[jss::Account] == alice.human());
1668 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
1669 BEAST_EXPECT(tx[jss::hash] == txid2);
1676 testcase(
"Ledger Request, Accounts Hashes");
1677 using namespace test::jtx;
1686 jvParams[jss::ledger_index] = 3u;
1687 jvParams[jss::accounts] =
true;
1688 jvParams[jss::expand] =
true;
1689 jvParams[jss::type] =
"hashes";
1691 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1692 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1693 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1694 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1696 jrr[jss::ledger][jss::accountState][0u][
"LedgerEntryType"] ==
1698 index = jrr[jss::ledger][jss::accountState][0u][
"index"].asString();
1702 jvParams[jss::ledger_index] = 3u;
1703 jvParams[jss::accounts] =
true;
1704 jvParams[jss::expand] =
false;
1705 jvParams[jss::type] =
"hashes";
1707 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1708 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1709 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1710 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1711 BEAST_EXPECT(jrr[jss::ledger][jss::accountState][0u] == index);