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/Feature.h>
26 #include <ripple/protocol/jss.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);
76 auto const jrr = env.rpc(
"ledger",
"1")[jss::result];
77 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
true);
78 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"1");
79 BEAST_EXPECT(jrr[jss::ledger][jss::accepted] ==
true);
81 jrr[jss::ledger][jss::totalCoins] ==
82 env.balance(env.master).value().getText());
87 auto const jrr = env.rpc(
"ledger",
"current")[jss::result];
88 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
false);
90 jrr[jss::ledger][jss::ledger_index] ==
93 jrr[jss::ledger_current_index] == env.current()->info().seq);
100 testcase(
"Bad Input");
101 using namespace test::jtx;
103 Account
const gw{
"gateway"};
104 auto const USD = gw[
"USD"];
105 Account
const bob{
"bob"};
107 env.fund(XRP(10000), gw, bob);
109 env.trust(USD(1000), bob);
114 jvParams[jss::ledger_index] =
"0";
116 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
123 jvParams[jss::ledger_index] = 10u;
125 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
131 auto const jrr = env.rpc(
"ledger",
"arbitrary_text")[jss::result];
138 jvParams[jss::ledger_index] =
"validated";
139 jvParams[jss::queue] =
true;
141 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
148 env.rpc(
"json",
"ledger",
"{ \"ledger_index\" : 2e15 }");
150 BEAST_EXPECT(ret[jss::error_message] ==
"Invalid parameters.");
155 auto const ret = env.rpc(
156 "json",
"ledger",
"{ \"ledger_index\" : 1000000000000000 }");
164 testcase(
"ledger_current Request");
165 using namespace test::jtx;
170 BEAST_EXPECT(env.current()->info().seq == 4);
173 auto const jrr = env.rpc(
"ledger_current")[jss::result];
175 jrr[jss::ledger_current_index] == env.current()->info().seq);
182 testcase(
"Missing ledger_entry ledger_hash");
183 using namespace test::jtx;
185 Account
const alice{
"alice"};
186 env.fund(XRP(10000), alice);
190 jvParams[jss::account_root] = alice.human();
191 jvParams[jss::ledger_hash] =
192 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
194 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
201 testcase(
"Ledger Request, Full Option");
202 using namespace test::jtx;
209 jvParams[jss::ledger_index] = 3u;
210 jvParams[jss::full] =
true;
212 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
213 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
214 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
215 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 2u);
221 testcase(
"Ledger Request, Full Option Without Admin");
222 using namespace test::jtx;
224 Env env{*
this, envconfig(no_admin)};
229 jvParams[jss::ledger_index] = 3u;
230 jvParams[jss::full] =
true;
232 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
234 jrr,
"noPermission",
"You don't have permission for this command.");
240 testcase(
"Ledger Request, Accounts Option");
241 using namespace test::jtx;
248 jvParams[jss::ledger_index] = 3u;
249 jvParams[jss::accounts] =
true;
251 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
252 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
253 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
254 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 2u);
260 testcase(
"ledger_entry Request AccountRoot");
261 using namespace test::jtx;
263 Account
const alice{
"alice"};
264 env.fund(XRP(10000), alice);
270 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
271 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
272 BEAST_EXPECT(jrr[jss::ledger_index] == 3);
279 jvParams[jss::account_root] = alice.human();
280 jvParams[jss::ledger_hash] = ledgerHash;
282 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
283 BEAST_EXPECT(jrr.
isMember(jss::node));
284 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
286 accountRootIndex = jrr[jss::index].
asString();
289 constexpr
char alicesAcctRootBinary[]{
290 "1100612200800000240000000425000000032D00000000559CE54C3B934E4"
291 "73A995B477E92EC229F99CED5B62BF4D2ACE4DC42719103AE2F6240000002"
292 "540BE4008114AE123A8556F3CF91154711376AFB0F894F832B3D"};
296 jvParams[jss::account_root] = alice.human();
297 jvParams[jss::binary] = 1;
298 jvParams[jss::ledger_hash] = ledgerHash;
300 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
301 BEAST_EXPECT(jrr.
isMember(jss::node_binary));
302 BEAST_EXPECT(jrr[jss::node_binary] == alicesAcctRootBinary);
307 jvParams[jss::index] = accountRootIndex;
309 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
310 BEAST_EXPECT(!jrr.
isMember(jss::node_binary));
311 BEAST_EXPECT(jrr.
isMember(jss::node));
312 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
318 jvParams[jss::index] = accountRootIndex;
319 jvParams[jss::binary] = 0;
321 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
322 BEAST_EXPECT(jrr.
isMember(jss::node));
323 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
330 jvParams[jss::ledger_hash] = ledgerHash;
332 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
338 jvParams[jss::account_root] = Account(
"bob").human();
339 jvParams[jss::ledger_hash] = ledgerHash;
341 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
349 testcase(
"ledger_entry Request Check");
350 using namespace test::jtx;
352 Account
const alice{
"alice"};
353 env.fund(XRP(10000), alice);
356 auto const checkId =
keylet::check(env.master, env.seq(env.master));
358 env(check::create(env.master, alice, XRP(100)));
365 jvParams[jss::check] =
to_string(checkId.key);
366 jvParams[jss::ledger_hash] = ledgerHash;
368 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
379 jvParams[jss::account_root] = alice.human();
381 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
382 accountRootIndex = jrr[jss::index].
asString();
385 jvParams[jss::check] = accountRootIndex;
386 jvParams[jss::ledger_hash] = ledgerHash;
388 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
396 testcase(
"ledger_entry Request Directory");
397 using namespace test::jtx;
399 Account
const alice{
"alice"};
400 Account
const becky{
"becky"};
402 env.fund(XRP(10000), alice, becky);
405 env(deposit::auth(alice, becky));
413 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
414 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
415 jvParams[jss::ledger_hash] = ledgerHash;
417 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
421 jss::DepositPreauth);
424 depositPreauthIndex = jrr[jss::node][jss::index].
asString();
429 jvParams[jss::deposit_preauth] = depositPreauthIndex;
430 jvParams[jss::ledger_hash] = ledgerHash;
432 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
436 jss::DepositPreauth);
443 jvParams[jss::deposit_preauth] = -5;
444 jvParams[jss::ledger_hash] = ledgerHash;
446 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
452 jvParams[jss::deposit_preauth] =
"0123456789ABCDEFG";
453 jvParams[jss::ledger_hash] = ledgerHash;
455 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
461 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
462 jvParams[jss::ledger_hash] = ledgerHash;
464 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
470 jvParams[jss::deposit_preauth][jss::owner] = 7;
471 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
472 jvParams[jss::ledger_hash] = ledgerHash;
474 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
480 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
481 jvParams[jss::ledger_hash] = ledgerHash;
483 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
489 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
490 jvParams[jss::deposit_preauth][jss::authorized] = 47;
491 jvParams[jss::ledger_hash] = ledgerHash;
493 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
499 jvParams[jss::deposit_preauth][jss::owner] =
500 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
502 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
503 jvParams[jss::ledger_hash] = ledgerHash;
505 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
511 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
512 jvParams[jss::deposit_preauth][jss::authorized] =
513 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
515 jvParams[jss::ledger_hash] = ledgerHash;
517 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
525 testcase(
"ledger_entry Request Directory");
526 using namespace test::jtx;
528 Account
const alice{
"alice"};
529 Account
const gw{
"gateway"};
530 auto const USD = gw[
"USD"];
531 env.fund(XRP(10000), alice, gw);
534 env.trust(USD(1000), alice);
539 for (
int d = 1
'000'032; d >= 1
'000'000; --d)
541 env(offer(alice, USD(1), drops(d)));
548 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
549 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
550 BEAST_EXPECT(jrr[jss::ledger_index] == 5);
554 "A33EC6BB85FB5674074C4A3A43373BB17645308F3EAE1933E3E35252162B217D";
558 jvParams[jss::directory] = dirRootIndex;
559 jvParams[jss::ledger_hash] = ledgerHash;
561 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
568 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
570 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
571 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
577 jvParams[jss::directory][jss::owner] = alice.human();
578 jvParams[jss::ledger_hash] = ledgerHash;
580 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
581 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
587 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
588 jvParams[jss::directory][jss::sub_index] = 1;
590 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
591 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
598 jvParams[jss::directory][jss::owner] = alice.human();
599 jvParams[jss::directory][jss::sub_index] = 1;
600 jvParams[jss::ledger_hash] = ledgerHash;
602 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
603 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
610 jvParams[jss::ledger_hash] = ledgerHash;
612 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
619 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
620 jvParams[jss::directory][jss::sub_index] = 1.5;
621 jvParams[jss::ledger_hash] = ledgerHash;
623 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
632 jvParams[jss::directory][jss::owner] = badAddress;
633 jvParams[jss::ledger_hash] = ledgerHash;
635 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
642 jvParams[jss::directory][jss::owner] = alice.human();
643 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
644 jvParams[jss::ledger_hash] = ledgerHash;
646 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
653 jvParams[jss::directory][jss::sub_index] = 1;
654 jvParams[jss::ledger_hash] = ledgerHash;
656 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
664 testcase(
"ledger_entry Request Escrow");
665 using namespace test::jtx;
667 Account
const alice{
"alice"};
668 env.fund(XRP(10000), alice);
677 jv[jss::TransactionType] = jss::EscrowCreate;
679 jv[jss::Account] = account.human();
680 jv[jss::Destination] = to.human();
683 cancelAfter.time_since_epoch().count() + 2;
687 using namespace std::chrono_literals;
688 env(escrowCreate(alice, alice, XRP(333), env.now() + 2s));
697 jvParams[jss::escrow][jss::owner] = alice.human();
698 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
700 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
702 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
703 escrowIndex = jrr[jss::index].
asString();
708 jvParams[jss::escrow] = escrowIndex;
709 jvParams[jss::ledger_hash] = ledgerHash;
711 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
713 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
721 jvParams[jss::escrow][jss::owner] = badAddress;
722 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
723 jvParams[jss::ledger_hash] = ledgerHash;
725 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
732 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
733 jvParams[jss::ledger_hash] = ledgerHash;
735 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
742 jvParams[jss::escrow][jss::owner] = alice.human();
743 jvParams[jss::ledger_hash] = ledgerHash;
745 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
752 jvParams[jss::escrow][jss::owner] = alice.human();
753 jvParams[jss::escrow][jss::seq] =
755 jvParams[jss::ledger_hash] = ledgerHash;
757 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
765 testcase(
"ledger_entry Request Offer");
766 using namespace test::jtx;
768 Account
const alice{
"alice"};
769 Account
const gw{
"gateway"};
770 auto const USD = gw[
"USD"];
771 env.fund(XRP(10000), alice, gw);
774 env(offer(alice, USD(321), XRP(322)));
783 jvParams[jss::offer][jss::account] = alice.human();
784 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
785 jvParams[jss::ledger_hash] = ledgerHash;
787 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
788 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
789 offerIndex = jrr[jss::index].
asString();
794 jvParams[jss::offer] = offerIndex;
796 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
797 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
805 jvParams[jss::offer][jss::account] = badAddress;
806 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
807 jvParams[jss::ledger_hash] = ledgerHash;
809 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
816 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
817 jvParams[jss::ledger_hash] = ledgerHash;
819 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
826 jvParams[jss::offer][jss::account] = alice.human();
827 jvParams[jss::ledger_hash] = ledgerHash;
829 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
836 jvParams[jss::offer][jss::account] = alice.human();
837 jvParams[jss::offer][jss::seq] =
std::to_string(env.seq(alice) - 1);
838 jvParams[jss::ledger_hash] = ledgerHash;
840 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
848 testcase(
"ledger_entry Request Pay Chan");
849 using namespace test::jtx;
850 using namespace std::literals::chrono_literals;
852 Account
const alice{
"alice"};
854 env.fund(XRP(10000), alice);
864 jv[jss::TransactionType] = jss::PaymentChannelCreate;
865 jv[jss::Account] = account.human();
866 jv[jss::Destination] = to.human();
873 env(payChanCreate(alice, env.master, XRP(57), 18s, alice.pk()));
883 jvParams[jss::payment_channel] =
to_string(payChanIndex);
884 jvParams[jss::ledger_hash] = ledgerHash;
886 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
894 jvParams[jss::payment_channel] = ledgerHash;
895 jvParams[jss::ledger_hash] = ledgerHash;
897 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
905 testcase(
"ledger_entry Request RippleState");
906 using namespace test::jtx;
908 Account
const alice{
"alice"};
909 Account
const gw{
"gateway"};
910 auto const USD = gw[
"USD"];
911 env.fund(XRP(10000), alice, gw);
914 env.trust(USD(999), alice);
917 env(pay(gw, alice, USD(97)));
926 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
927 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
928 jvParams[jss::ripple_state][jss::currency] =
"USD";
929 jvParams[jss::ledger_hash] = ledgerHash;
931 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
940 jvParams[jss::ripple_state] =
"ripple_state";
941 jvParams[jss::ledger_hash] = ledgerHash;
943 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
951 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
952 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
953 jvParams[jss::ledger_hash] = ledgerHash;
955 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
962 jvParams[jss::ripple_state][jss::accounts] = 2;
963 jvParams[jss::ripple_state][jss::currency] =
"USD";
964 jvParams[jss::ledger_hash] = ledgerHash;
966 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
974 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
975 jvParams[jss::ripple_state][jss::currency] =
"USD";
976 jvParams[jss::ledger_hash] = ledgerHash;
978 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
986 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
987 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
988 jvParams[jss::ripple_state][jss::accounts][2u] = alice.human();
989 jvParams[jss::ripple_state][jss::currency] =
"USD";
990 jvParams[jss::ledger_hash] = ledgerHash;
992 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1000 jvParams[jss::ripple_state][jss::accounts][0u] = 44;
1001 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1002 jvParams[jss::ripple_state][jss::currency] =
"USD";
1003 jvParams[jss::ledger_hash] = ledgerHash;
1005 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1013 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1014 jvParams[jss::ripple_state][jss::accounts][1u] = 21;
1015 jvParams[jss::ripple_state][jss::currency] =
"USD";
1016 jvParams[jss::ledger_hash] = ledgerHash;
1018 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1026 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1027 jvParams[jss::ripple_state][jss::accounts][1u] = alice.human();
1028 jvParams[jss::ripple_state][jss::currency] =
"USD";
1029 jvParams[jss::ledger_hash] = ledgerHash;
1031 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1039 jvParams[jss::ripple_state][jss::accounts][0u] =
1041 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1042 jvParams[jss::ripple_state][jss::currency] =
"USD";
1043 jvParams[jss::ledger_hash] = ledgerHash;
1045 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1053 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1054 jvParams[jss::ripple_state][jss::accounts][1u] =
1056 jvParams[jss::ripple_state][jss::currency] =
"USD";
1057 jvParams[jss::ledger_hash] = ledgerHash;
1059 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1067 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1068 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1069 jvParams[jss::ripple_state][jss::currency] =
"USDollars";
1070 jvParams[jss::ledger_hash] = ledgerHash;
1072 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1080 testcase(
"ledger_entry Request Unknown Option");
1081 using namespace test::jtx;
1088 jvParams[jss::features] = ledgerHash;
1089 jvParams[jss::ledger_hash] = ledgerHash;
1091 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1102 testcase(
"Lookup ledger");
1103 using namespace test::jtx;
1106 env.fund(XRP(10000),
"alice");
1108 env.fund(XRP(10000),
"bob");
1110 env.fund(XRP(10000),
"jim");
1112 env.fund(XRP(10000),
"jill");
1124 jvParams[jss::ledger] =
"closed";
1128 boost::lexical_cast<std::string>(jvParams))[jss::result];
1129 BEAST_EXPECT(jrr.isMember(jss::ledger));
1130 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1131 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1133 jvParams[jss::ledger] =
"validated";
1137 boost::lexical_cast<std::string>(jvParams))[jss::result];
1138 BEAST_EXPECT(jrr.isMember(jss::ledger));
1139 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1140 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1142 jvParams[jss::ledger] =
"current";
1146 boost::lexical_cast<std::string>(jvParams))[jss::result];
1147 BEAST_EXPECT(jrr.isMember(jss::ledger));
1148 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1151 jvParams[jss::ledger] =
"invalid";
1155 boost::lexical_cast<std::string>(jvParams))[jss::result];
1156 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1157 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1160 jvParams[jss::ledger] = 4;
1164 boost::lexical_cast<std::string>(jvParams))[jss::result];
1165 BEAST_EXPECT(jrr.isMember(jss::ledger));
1166 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1167 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"4");
1170 jvParams[jss::ledger] = 20;
1174 boost::lexical_cast<std::string>(jvParams))[jss::result];
1175 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1176 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1182 jvParams[jss::ledger_hash] =
1183 "7C3EEDB3124D92E49E75D81A8826A2E6"
1184 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1188 boost::lexical_cast<std::string>(jvParams))[jss::result];
1189 BEAST_EXPECT(jrr.isMember(jss::ledger));
1190 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1191 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"3");
1194 jvParams[jss::ledger_hash] =
1196 "7C3EEDB3124D92E49E75D81A8826A2E6"
1197 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1201 boost::lexical_cast<std::string>(jvParams))[jss::result];
1202 BEAST_EXPECT(jrr.isMember(jss::ledger));
1203 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1204 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"3");
1207 jvParams[jss::ledger_hash] = 2;
1211 boost::lexical_cast<std::string>(jvParams))[jss::result];
1212 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1213 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashNotString");
1216 jvParams[jss::ledger_hash] =
1217 "ZZZZZZZZZZZD92E49E75D81A8826A2E6"
1218 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1222 boost::lexical_cast<std::string>(jvParams))[jss::result];
1223 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1224 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1227 jvParams[jss::ledger_hash] =
1228 "8C3EEDB3124D92E49E75D81A8826A2E6"
1229 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1233 boost::lexical_cast<std::string>(jvParams))[jss::result];
1234 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1235 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1241 jvParams[jss::ledger_index] =
"closed";
1245 boost::lexical_cast<std::string>(jvParams))[jss::result];
1246 BEAST_EXPECT(jrr.isMember(jss::ledger));
1247 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1248 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1249 BEAST_EXPECT(jrr.isMember(jss::ledger_index));
1251 jvParams[jss::ledger_index] =
"validated";
1255 boost::lexical_cast<std::string>(jvParams))[jss::result];
1256 BEAST_EXPECT(jrr.isMember(jss::ledger));
1257 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1258 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1260 jvParams[jss::ledger_index] =
"current";
1264 boost::lexical_cast<std::string>(jvParams))[jss::result];
1265 BEAST_EXPECT(jrr.isMember(jss::ledger));
1266 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1267 BEAST_EXPECT(jrr.isMember(jss::ledger_current_index));
1270 jvParams[jss::ledger_index] =
"invalid";
1274 boost::lexical_cast<std::string>(jvParams))[jss::result];
1275 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1276 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1279 for (
auto i : {1, 2, 3, 4, 5, 6})
1281 jvParams[jss::ledger_index] = i;
1285 boost::lexical_cast<std::string>(jvParams))[jss::result];
1286 BEAST_EXPECT(jrr.isMember(jss::ledger));
1288 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1294 jvParams[jss::ledger_index] = 7;
1298 boost::lexical_cast<std::string>(jvParams))[jss::result];
1299 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1300 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1307 testcase(
"Ledger with queueing disabled");
1308 using namespace test::jtx;
1312 jv[jss::ledger_index] =
"current";
1313 jv[jss::queue] =
true;
1314 jv[jss::expand] =
true;
1316 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1317 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1323 testcase(
"Ledger with Queued Transactions");
1324 using namespace test::jtx;
1326 auto& section = cfg->section(
"transaction_queue");
1327 section.set(
"minimum_txn_in_ledger_standalone",
"3");
1328 section.set(
"normal_consensus_increase_percent",
"0");
1333 jv[jss::ledger_index] =
"current";
1334 jv[jss::queue] =
true;
1335 jv[jss::expand] =
true;
1337 Account
const alice{
"alice"};
1338 Account
const bob{
"bob"};
1339 Account
const charlie{
"charlie"};
1340 Account
const daria{
"daria"};
1341 env.fund(XRP(10000), alice);
1342 env.fund(XRP(10000), bob);
1344 env.fund(XRP(10000), charlie);
1345 env.fund(XRP(10000), daria);
1348 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1349 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1354 auto metrics = env.app().getTxQ().getMetrics(*env.current());
1355 if (metrics.openLedgerFeeLevel > metrics.minProcessingFeeLevel)
1360 BEAST_EXPECT(env.current()->info().seq == 5);
1363 auto aliceSeq = env.seq(alice);
1364 env(pay(alice,
"george", XRP(1000)),
1365 json(R
"({"LastLedgerSequence":7})"),
1367 env(offer(alice, XRP(50000), alice["USD"](5000)),
1370 env(noop(alice), seq(aliceSeq + 2), ter(
terQUEUED));
1372 auto batch = [&env](Account a) {
1373 auto aSeq = env.seq(a);
1375 for (
int i = 0; i < 10; ++i)
1377 env(noop(a), fee(1000 + i), seq(aSeq + i), ter(
terQUEUED));
1386 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1387 BEAST_EXPECT(jrr[jss::queue_data].size() == 33);
1393 BEAST_EXPECT(env.current()->info().seq == 8);
1395 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1396 BEAST_EXPECT(jrr[jss::queue_data].size() == 11);
1400 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1403 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1405 auto const& txj = jrr[jss::queue_data][0u];
1406 BEAST_EXPECT(txj[jss::account] == alice.human());
1407 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1408 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1409 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
1410 BEAST_EXPECT(txj.isMember(jss::tx));
1411 auto const& tx = txj[jss::tx];
1412 BEAST_EXPECT(tx[jss::Account] == alice.human());
1413 BEAST_EXPECT(tx[jss::TransactionType] == jss::OfferCreate);
1414 txid1 = tx[jss::hash].asString();
1419 jv[jss::expand] =
false;
1421 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1422 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1424 auto const& txj = jrr[jss::queue_data][0u];
1425 BEAST_EXPECT(txj[jss::account] == alice.human());
1426 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1427 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1428 BEAST_EXPECT(txj[
"retries_remaining"] == 9);
1429 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1430 BEAST_EXPECT(txj.isMember(jss::tx));
1431 BEAST_EXPECT(txj[jss::tx] == txid1);
1436 jv[jss::expand] =
true;
1437 jv[jss::binary] =
true;
1439 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1440 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1442 auto const& txj = jrr[jss::queue_data][0u];
1443 BEAST_EXPECT(txj[jss::account] == alice.human());
1444 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1445 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1446 BEAST_EXPECT(txj[
"retries_remaining"] == 8);
1447 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1448 BEAST_EXPECT(txj.isMember(jss::tx));
1449 BEAST_EXPECT(txj[jss::tx].isMember(jss::tx_blob));
1451 auto const& txj2 = jrr[jss::queue_data][1u];
1452 BEAST_EXPECT(txj2[jss::account] == alice.human());
1453 BEAST_EXPECT(txj2[jss::fee_level] ==
"256");
1454 BEAST_EXPECT(txj2[
"preflight_result"] ==
"tesSUCCESS");
1455 BEAST_EXPECT(txj2[
"retries_remaining"] == 10);
1456 BEAST_EXPECT(!txj2.isMember(
"last_result"));
1457 BEAST_EXPECT(txj2.isMember(jss::tx));
1458 BEAST_EXPECT(txj2[jss::tx].isMember(jss::tx_blob));
1461 for (
int i = 0; i != 9; ++i)
1466 jv[jss::expand] =
false;
1467 jv[jss::binary] =
false;
1469 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1470 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1472 auto const& txj = jrr[jss::queue_data][0u];
1473 BEAST_EXPECT(txj[jss::account] == alice.human());
1474 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1475 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1476 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1477 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1478 BEAST_EXPECT(txj.isMember(jss::tx));
1479 BEAST_EXPECT(txj[jss::tx] != txid1);
1480 txid2 = txj[jss::tx].asString();
1483 jv[jss::full] =
true;
1485 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1486 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1488 auto const& txj = jrr[jss::queue_data][0u];
1489 BEAST_EXPECT(txj[jss::account] == alice.human());
1490 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1491 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1492 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1493 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1494 BEAST_EXPECT(txj.isMember(jss::tx));
1495 auto const& tx = txj[jss::tx];
1496 BEAST_EXPECT(tx[jss::Account] == alice.human());
1497 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
1498 BEAST_EXPECT(tx[jss::hash] == txid2);
1505 testcase(
"Ledger Request, Accounts Option");
1506 using namespace test::jtx;
1515 jvParams[jss::ledger_index] = 3u;
1516 jvParams[jss::accounts] =
true;
1517 jvParams[jss::expand] =
true;
1518 jvParams[jss::type] =
"hashes";
1520 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1521 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1522 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1523 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1525 jrr[jss::ledger][jss::accountState][0u][
"LedgerEntryType"] ==
1527 index = jrr[jss::ledger][jss::accountState][0u][
"index"].asString();
1531 jvParams[jss::ledger_index] = 3u;
1532 jvParams[jss::accounts] =
true;
1533 jvParams[jss::expand] =
false;
1534 jvParams[jss::type] =
"hashes";
1536 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1537 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1538 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1539 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1540 BEAST_EXPECT(jrr[jss::ledger][jss::accountState][0u] == index);