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>
38 if (BEAST_EXPECT(jv.
isMember(jss::status)))
39 BEAST_EXPECT(jv[jss::status] ==
"error");
40 if (BEAST_EXPECT(jv.
isMember(jss::error)))
41 BEAST_EXPECT(jv[jss::error] == err);
46 jv[jss::error_message] ==
"");
48 else if (BEAST_EXPECT(jv.
isMember(jss::error_message)))
49 BEAST_EXPECT(jv[jss::error_message] == msg);
65 testcase(
"Basic Request");
66 using namespace test::jtx;
71 BEAST_EXPECT(env.current()->info().seq == 4);
76 jvParams[jss::ledger_index] = 1;
78 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
79 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
true);
80 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"1");
85 jvParams[jss::ledger_index] =
"1";
87 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
88 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
true);
89 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"1");
94 auto const jrr = env.rpc(
"ledger",
"current")[jss::result];
95 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
false);
97 jrr[jss::ledger][jss::ledger_index] ==
100 jrr[jss::ledger_current_index] == env.current()->info().seq);
107 testcase(
"Bad Input");
108 using namespace test::jtx;
110 Account
const gw{
"gateway"};
111 auto const USD = gw[
"USD"];
112 Account
const bob{
"bob"};
114 env.fund(XRP(10000), gw, bob);
116 env.trust(USD(1000), bob);
122 jvParams[jss::ledger_index] =
"potato";
124 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
131 jvParams[jss::ledger_index] = -1;
133 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
140 jvParams[jss::ledger_index] = 10u;
142 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
148 auto const jrr = env.rpc(
"ledger",
"arbitrary_text")[jss::result];
155 jvParams[jss::ledger_index] =
"validated";
156 jvParams[jss::queue] =
true;
158 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
165 env.rpc(
"json",
"ledger",
"{ \"ledger_index\" : 2e15 }");
167 BEAST_EXPECT(ret[jss::error_message] ==
"Invalid parameters.");
172 auto const ret = env.rpc(
173 "json",
"ledger",
"{ \"ledger_index\" : 1000000000000000 }");
181 testcase(
"ledger_current Request");
182 using namespace test::jtx;
187 BEAST_EXPECT(env.current()->info().seq == 4);
190 auto const jrr = env.rpc(
"ledger_current")[jss::result];
192 jrr[jss::ledger_current_index] == env.current()->info().seq);
199 testcase(
"Missing ledger_entry ledger_hash");
200 using namespace test::jtx;
202 Account
const alice{
"alice"};
203 env.fund(XRP(10000), alice);
207 jvParams[jss::account_root] = alice.human();
208 jvParams[jss::ledger_hash] =
209 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
211 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
218 testcase(
"Ledger Request, Full Option");
219 using namespace test::jtx;
226 jvParams[jss::ledger_index] = 3u;
227 jvParams[jss::full] =
true;
229 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
230 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
231 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
232 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u);
238 testcase(
"Ledger Request, Full Option Without Admin");
239 using namespace test::jtx;
241 Env env{*
this, envconfig(no_admin)};
246 jvParams[jss::ledger_index] = 1u;
247 jvParams[jss::full] =
true;
249 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
251 jrr,
"noPermission",
"You don't have permission for this command.");
257 testcase(
"Ledger Request, Accounts Option");
258 using namespace test::jtx;
265 jvParams[jss::ledger_index] = 3u;
266 jvParams[jss::accounts] =
true;
268 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
269 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
270 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
271 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 3u);
277 testcase(
"ledger_entry Request AccountRoot");
278 using namespace test::jtx;
280 Account
const alice{
"alice"};
281 env.fund(XRP(10000), alice);
287 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
288 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
289 BEAST_EXPECT(jrr[jss::ledger_index] == 3);
296 jvParams[jss::account_root] = alice.human();
297 jvParams[jss::ledger_hash] = ledgerHash;
299 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
300 BEAST_EXPECT(jrr.
isMember(jss::node));
301 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
303 accountRootIndex = jrr[jss::index].
asString();
306 constexpr
char alicesAcctRootBinary[]{
307 "1100612200800000240000000425000000032D00000000559CE54C3B934E4"
308 "73A995B477E92EC229F99CED5B62BF4D2ACE4DC42719103AE2F6240000002"
309 "540BE4008114AE123A8556F3CF91154711376AFB0F894F832B3D"};
313 jvParams[jss::account_root] = alice.human();
314 jvParams[jss::binary] = 1;
315 jvParams[jss::ledger_hash] = ledgerHash;
317 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
318 BEAST_EXPECT(jrr.
isMember(jss::node_binary));
319 BEAST_EXPECT(jrr[jss::node_binary] == alicesAcctRootBinary);
324 jvParams[jss::index] = accountRootIndex;
326 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
327 BEAST_EXPECT(!jrr.
isMember(jss::node_binary));
328 BEAST_EXPECT(jrr.
isMember(jss::node));
329 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
335 jvParams[jss::index] = accountRootIndex;
336 jvParams[jss::binary] = 0;
338 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
339 BEAST_EXPECT(jrr.
isMember(jss::node));
340 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
347 jvParams[jss::ledger_hash] = ledgerHash;
349 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
355 jvParams[jss::account_root] = Account(
"bob").human();
356 jvParams[jss::ledger_hash] = ledgerHash;
358 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
366 testcase(
"ledger_entry Request Check");
367 using namespace test::jtx;
369 Account
const alice{
"alice"};
370 env.fund(XRP(10000), alice);
373 auto const checkId =
keylet::check(env.master, env.seq(env.master));
375 env(check::create(env.master, alice, XRP(100)));
382 jvParams[jss::check] =
to_string(checkId.key);
383 jvParams[jss::ledger_hash] = ledgerHash;
385 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
396 jvParams[jss::account_root] = alice.human();
398 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
399 accountRootIndex = jrr[jss::index].
asString();
402 jvParams[jss::check] = accountRootIndex;
403 jvParams[jss::ledger_hash] = ledgerHash;
405 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
413 testcase(
"ledger_entry Deposit Preauth");
415 using namespace test::jtx;
418 Account
const alice{
"alice"};
419 Account
const becky{
"becky"};
421 env.fund(XRP(10000), alice, becky);
424 env(deposit::auth(alice, becky));
432 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
433 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
434 jvParams[jss::ledger_hash] = ledgerHash;
436 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
440 jss::DepositPreauth);
443 depositPreauthIndex = jrr[jss::node][jss::index].
asString();
448 jvParams[jss::deposit_preauth] = depositPreauthIndex;
449 jvParams[jss::ledger_hash] = ledgerHash;
451 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
455 jss::DepositPreauth);
462 jvParams[jss::deposit_preauth] = -5;
463 jvParams[jss::ledger_hash] = ledgerHash;
465 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
471 jvParams[jss::deposit_preauth] =
"0123456789ABCDEFG";
472 jvParams[jss::ledger_hash] = ledgerHash;
474 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
480 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
481 jvParams[jss::ledger_hash] = ledgerHash;
483 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
489 jvParams[jss::deposit_preauth][jss::owner] = 7;
490 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
491 jvParams[jss::ledger_hash] = ledgerHash;
493 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
499 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
500 jvParams[jss::ledger_hash] = ledgerHash;
502 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
508 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
509 jvParams[jss::deposit_preauth][jss::authorized] = 47;
510 jvParams[jss::ledger_hash] = ledgerHash;
512 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
518 jvParams[jss::deposit_preauth][jss::owner] =
519 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
521 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
522 jvParams[jss::ledger_hash] = ledgerHash;
524 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
530 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
531 jvParams[jss::deposit_preauth][jss::authorized] =
532 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
534 jvParams[jss::ledger_hash] = ledgerHash;
536 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
544 testcase(
"ledger_entry Request Directory");
545 using namespace test::jtx;
547 Account
const alice{
"alice"};
548 Account
const gw{
"gateway"};
549 auto const USD = gw[
"USD"];
550 env.fund(XRP(10000), alice, gw);
553 env.trust(USD(1000), alice);
558 for (
int d = 1
'000'032; d >= 1
'000'000; --d)
560 env(offer(alice, USD(1), drops(d)));
567 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
568 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
569 BEAST_EXPECT(jrr[jss::ledger_index] == 5);
573 "A33EC6BB85FB5674074C4A3A43373BB17645308F3EAE1933E3E35252162B217D";
577 jvParams[jss::directory] = dirRootIndex;
578 jvParams[jss::ledger_hash] = ledgerHash;
580 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
587 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
589 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
590 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
596 jvParams[jss::directory][jss::owner] = alice.human();
597 jvParams[jss::ledger_hash] = ledgerHash;
599 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
600 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
606 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
607 jvParams[jss::directory][jss::sub_index] = 1;
609 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
610 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
617 jvParams[jss::directory][jss::owner] = alice.human();
618 jvParams[jss::directory][jss::sub_index] = 1;
619 jvParams[jss::ledger_hash] = ledgerHash;
621 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
622 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
629 jvParams[jss::ledger_hash] = ledgerHash;
631 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
638 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
639 jvParams[jss::directory][jss::sub_index] = 1.5;
640 jvParams[jss::ledger_hash] = ledgerHash;
642 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
651 jvParams[jss::directory][jss::owner] = badAddress;
652 jvParams[jss::ledger_hash] = ledgerHash;
654 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
661 jvParams[jss::directory][jss::owner] = alice.human();
662 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
663 jvParams[jss::ledger_hash] = ledgerHash;
665 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
672 jvParams[jss::directory][jss::sub_index] = 1;
673 jvParams[jss::ledger_hash] = ledgerHash;
675 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
683 testcase(
"ledger_entry Request Escrow");
684 using namespace test::jtx;
686 Account
const alice{
"alice"};
687 env.fund(XRP(10000), alice);
696 jv[jss::TransactionType] = jss::EscrowCreate;
698 jv[jss::Account] = account.human();
699 jv[jss::Destination] = to.human();
702 cancelAfter.time_since_epoch().count() + 2;
706 using namespace std::chrono_literals;
707 env(escrowCreate(alice, alice, XRP(333), env.now() + 2s));
716 jvParams[jss::escrow][jss::owner] = alice.human();
717 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
719 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
721 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
722 escrowIndex = jrr[jss::index].
asString();
727 jvParams[jss::escrow] = escrowIndex;
728 jvParams[jss::ledger_hash] = ledgerHash;
730 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
732 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
740 jvParams[jss::escrow][jss::owner] = badAddress;
741 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
742 jvParams[jss::ledger_hash] = ledgerHash;
744 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
751 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
752 jvParams[jss::ledger_hash] = ledgerHash;
754 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
761 jvParams[jss::escrow][jss::owner] = alice.human();
762 jvParams[jss::ledger_hash] = ledgerHash;
764 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
771 jvParams[jss::escrow][jss::owner] = alice.human();
772 jvParams[jss::escrow][jss::seq] =
774 jvParams[jss::ledger_hash] = ledgerHash;
776 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
784 testcase(
"ledger_entry Request Offer");
785 using namespace test::jtx;
787 Account
const alice{
"alice"};
788 Account
const gw{
"gateway"};
789 auto const USD = gw[
"USD"];
790 env.fund(XRP(10000), alice, gw);
793 env(offer(alice, USD(321), XRP(322)));
802 jvParams[jss::offer][jss::account] = alice.human();
803 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
804 jvParams[jss::ledger_hash] = ledgerHash;
806 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
807 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
808 offerIndex = jrr[jss::index].
asString();
813 jvParams[jss::offer] = offerIndex;
815 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
816 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
824 jvParams[jss::offer][jss::account] = badAddress;
825 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
826 jvParams[jss::ledger_hash] = ledgerHash;
828 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
835 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
836 jvParams[jss::ledger_hash] = ledgerHash;
838 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
845 jvParams[jss::offer][jss::account] = alice.human();
846 jvParams[jss::ledger_hash] = ledgerHash;
848 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
855 jvParams[jss::offer][jss::account] = alice.human();
856 jvParams[jss::offer][jss::seq] =
std::to_string(env.seq(alice) - 1);
857 jvParams[jss::ledger_hash] = ledgerHash;
859 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
867 testcase(
"ledger_entry Request Pay Chan");
868 using namespace test::jtx;
869 using namespace std::literals::chrono_literals;
871 Account
const alice{
"alice"};
873 env.fund(XRP(10000), alice);
883 jv[jss::TransactionType] = jss::PaymentChannelCreate;
884 jv[jss::Account] = account.human();
885 jv[jss::Destination] = to.human();
892 env(payChanCreate(alice, env.master, XRP(57), 18s, alice.pk()));
902 jvParams[jss::payment_channel] =
to_string(payChanIndex);
903 jvParams[jss::ledger_hash] = ledgerHash;
905 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
913 jvParams[jss::payment_channel] = ledgerHash;
914 jvParams[jss::ledger_hash] = ledgerHash;
916 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
924 testcase(
"ledger_entry Request RippleState");
925 using namespace test::jtx;
927 Account
const alice{
"alice"};
928 Account
const gw{
"gateway"};
929 auto const USD = gw[
"USD"];
930 env.fund(XRP(10000), alice, gw);
933 env.trust(USD(999), alice);
936 env(pay(gw, alice, USD(97)));
945 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
946 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
947 jvParams[jss::ripple_state][jss::currency] =
"USD";
948 jvParams[jss::ledger_hash] = ledgerHash;
950 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
959 jvParams[jss::ripple_state] =
"ripple_state";
960 jvParams[jss::ledger_hash] = ledgerHash;
962 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
970 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
971 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
972 jvParams[jss::ledger_hash] = ledgerHash;
974 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
981 jvParams[jss::ripple_state][jss::accounts] = 2;
982 jvParams[jss::ripple_state][jss::currency] =
"USD";
983 jvParams[jss::ledger_hash] = ledgerHash;
985 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
993 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
994 jvParams[jss::ripple_state][jss::currency] =
"USD";
995 jvParams[jss::ledger_hash] = ledgerHash;
997 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1005 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1006 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1007 jvParams[jss::ripple_state][jss::accounts][2u] = alice.human();
1008 jvParams[jss::ripple_state][jss::currency] =
"USD";
1009 jvParams[jss::ledger_hash] = ledgerHash;
1011 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1019 jvParams[jss::ripple_state][jss::accounts][0u] = 44;
1020 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1021 jvParams[jss::ripple_state][jss::currency] =
"USD";
1022 jvParams[jss::ledger_hash] = ledgerHash;
1024 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1032 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1033 jvParams[jss::ripple_state][jss::accounts][1u] = 21;
1034 jvParams[jss::ripple_state][jss::currency] =
"USD";
1035 jvParams[jss::ledger_hash] = ledgerHash;
1037 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1045 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1046 jvParams[jss::ripple_state][jss::accounts][1u] = alice.human();
1047 jvParams[jss::ripple_state][jss::currency] =
"USD";
1048 jvParams[jss::ledger_hash] = ledgerHash;
1050 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1058 jvParams[jss::ripple_state][jss::accounts][0u] =
1060 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1061 jvParams[jss::ripple_state][jss::currency] =
"USD";
1062 jvParams[jss::ledger_hash] = ledgerHash;
1064 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1072 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1073 jvParams[jss::ripple_state][jss::accounts][1u] =
1075 jvParams[jss::ripple_state][jss::currency] =
"USD";
1076 jvParams[jss::ledger_hash] = ledgerHash;
1078 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1086 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1087 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1088 jvParams[jss::ripple_state][jss::currency] =
"USDollars";
1089 jvParams[jss::ledger_hash] = ledgerHash;
1091 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1099 testcase(
"ledger_entry Request Ticket");
1100 using namespace test::jtx;
1106 env(ticket::create(env.master, 2));
1116 jvParams[jss::ticket] =
1118 jvParams[jss::ledger_hash] = ledgerHash;
1120 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1127 jvParams[jss::ledger_hash] = ledgerHash;
1129 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1138 jvParams[jss::ticket][jss::account] = env.master.human();
1139 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 1;
1140 jvParams[jss::ledger_hash] = ledgerHash;
1142 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1144 jrr[jss::node][jss::index] ==
1151 jvParams[jss::ticket][jss::account] = env.master.human();
1152 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 2;
1153 jvParams[jss::ledger_hash] = ledgerHash;
1155 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1162 jvParams[jss::ledger_hash] = ledgerHash;
1164 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1173 jvParams[jss::ticket][jss::account] = badAddress;
1174 jvParams[jss::ticket][jss::ticket_seq] = env.seq(env.master) - 1;
1175 jvParams[jss::ledger_hash] = ledgerHash;
1177 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1184 jvParams[jss::ticket][jss::ticket_seq] = env.seq(env.master) - 1;
1185 jvParams[jss::ledger_hash] = ledgerHash;
1187 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1194 jvParams[jss::ticket][jss::account] = env.master.human();
1195 jvParams[jss::ledger_hash] = ledgerHash;
1197 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1204 jvParams[jss::ticket][jss::account] = env.master.human();
1205 jvParams[jss::ticket][jss::ticket_seq] =
1207 jvParams[jss::ledger_hash] = ledgerHash;
1209 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1218 "ledger_entry Request With Invalid Parameters v" +
1220 using namespace test::jtx;
1227 jvParams[jss::api_version] = apiVersion;
1228 jvParams[jss::features] = ledgerHash;
1229 jvParams[jss::ledger_hash] = ledgerHash;
1231 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1233 if (apiVersion < 2u)
1246 testcase(
"Lookup ledger");
1247 using namespace test::jtx;
1250 env.fund(XRP(10000),
"alice");
1252 env.fund(XRP(10000),
"bob");
1254 env.fund(XRP(10000),
"jim");
1256 env.fund(XRP(10000),
"jill");
1261 jvParams[jss::ledger] =
"closed";
1265 boost::lexical_cast<std::string>(jvParams))[jss::result];
1266 BEAST_EXPECT(jrr.isMember(jss::ledger));
1267 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1268 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1270 jvParams[jss::ledger] =
"validated";
1274 boost::lexical_cast<std::string>(jvParams))[jss::result];
1275 BEAST_EXPECT(jrr.isMember(jss::ledger));
1276 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1277 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1279 jvParams[jss::ledger] =
"current";
1283 boost::lexical_cast<std::string>(jvParams))[jss::result];
1284 BEAST_EXPECT(jrr.isMember(jss::ledger));
1285 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1288 jvParams[jss::ledger] =
"invalid";
1292 boost::lexical_cast<std::string>(jvParams))[jss::result];
1293 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1294 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1297 jvParams[jss::ledger] = 4;
1301 boost::lexical_cast<std::string>(jvParams))[jss::result];
1302 BEAST_EXPECT(jrr.isMember(jss::ledger));
1303 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1304 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"4");
1307 jvParams[jss::ledger] = 20;
1311 boost::lexical_cast<std::string>(jvParams))[jss::result];
1312 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1313 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1318 "E86DE7F3D7A4D9CE17EF7C8BA08A8F4D"
1319 "8F643B9552F0D895A31CDA78F541DE4E"};
1322 jvParams[jss::ledger_hash] = hash3;
1326 boost::lexical_cast<std::string>(jvParams))[jss::result];
1327 BEAST_EXPECT(jrr.isMember(jss::ledger));
1328 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1329 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"3");
1332 jvParams[jss::ledger_hash] =
"DEADBEEF" + hash3;
1336 boost::lexical_cast<std::string>(jvParams))[jss::result];
1337 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1338 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1341 jvParams[jss::ledger_hash] = 2;
1345 boost::lexical_cast<std::string>(jvParams))[jss::result];
1346 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1347 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashNotString");
1350 jvParams[jss::ledger_hash] =
1351 "2E81FC6EC0DD943197EGC7E3FBE9AE30"
1352 "7F2775F2F7485BB37307984C3C0F2340";
1356 boost::lexical_cast<std::string>(jvParams))[jss::result];
1357 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1358 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1361 jvParams[jss::ledger_hash] =
1362 "8C3EEDB3124D92E49E75D81A8826A2E6"
1363 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1367 boost::lexical_cast<std::string>(jvParams))[jss::result];
1368 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1369 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1375 jvParams[jss::ledger_index] =
"closed";
1379 boost::lexical_cast<std::string>(jvParams))[jss::result];
1380 BEAST_EXPECT(jrr.isMember(jss::ledger));
1381 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1382 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1383 BEAST_EXPECT(jrr.isMember(jss::ledger_index));
1385 jvParams[jss::ledger_index] =
"validated";
1389 boost::lexical_cast<std::string>(jvParams))[jss::result];
1390 BEAST_EXPECT(jrr.isMember(jss::ledger));
1391 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1392 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1394 jvParams[jss::ledger_index] =
"current";
1398 boost::lexical_cast<std::string>(jvParams))[jss::result];
1399 BEAST_EXPECT(jrr.isMember(jss::ledger));
1400 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1401 BEAST_EXPECT(jrr.isMember(jss::ledger_current_index));
1404 jvParams[jss::ledger_index] =
"invalid";
1408 boost::lexical_cast<std::string>(jvParams))[jss::result];
1409 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1410 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1413 for (
auto i : {1, 2, 3, 4, 5, 6})
1415 jvParams[jss::ledger_index] = i;
1419 boost::lexical_cast<std::string>(jvParams))[jss::result];
1420 BEAST_EXPECT(jrr.isMember(jss::ledger));
1422 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1428 jvParams[jss::ledger_index] = 7;
1432 boost::lexical_cast<std::string>(jvParams))[jss::result];
1433 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1434 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1441 testcase(
"Ledger with queueing disabled");
1442 using namespace test::jtx;
1446 jv[jss::ledger_index] =
"current";
1447 jv[jss::queue] =
true;
1448 jv[jss::expand] =
true;
1450 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1451 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1457 testcase(
"Ledger with Queued Transactions");
1458 using namespace test::jtx;
1460 auto& section = cfg->section(
"transaction_queue");
1461 section.set(
"minimum_txn_in_ledger_standalone",
"3");
1462 section.set(
"normal_consensus_increase_percent",
"0");
1467 jv[jss::ledger_index] =
"current";
1468 jv[jss::queue] =
true;
1469 jv[jss::expand] =
true;
1471 Account
const alice{
"alice"};
1472 Account
const bob{
"bob"};
1473 Account
const charlie{
"charlie"};
1474 Account
const daria{
"daria"};
1475 env.fund(XRP(10000), alice);
1476 env.fund(XRP(10000), bob);
1478 env.fund(XRP(10000), charlie);
1479 env.fund(XRP(10000), daria);
1482 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1483 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1488 auto metrics = env.app().getTxQ().getMetrics(*env.current());
1489 if (metrics.openLedgerFeeLevel > metrics.minProcessingFeeLevel)
1494 BEAST_EXPECT(env.current()->info().seq == 5);
1497 auto aliceSeq = env.seq(alice);
1498 env(pay(alice,
"george", XRP(1000)),
1499 json(R
"({"LastLedgerSequence":7})"),
1501 env(offer(alice, XRP(50000), alice["USD"](5000)),
1504 env(noop(alice), seq(aliceSeq + 2), ter(
terQUEUED));
1506 auto batch = [&env](Account a) {
1507 auto aSeq = env.seq(a);
1509 for (
int i = 0; i < 10; ++i)
1511 env(noop(a), fee(1000 + i), seq(aSeq + i), ter(
terQUEUED));
1520 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1521 BEAST_EXPECT(jrr[jss::queue_data].size() == 33);
1527 BEAST_EXPECT(env.current()->info().seq == 8);
1529 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1530 BEAST_EXPECT(jrr[jss::queue_data].size() == 11);
1534 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1536 auto const& parentHash = env.current()->info().parentHash;
1537 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1540 auto const& txj = jrr[jss::queue_data][1u];
1541 BEAST_EXPECT(txj[jss::account] == alice.human());
1542 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1543 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1544 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
1545 BEAST_EXPECT(txj.isMember(jss::tx));
1546 auto const& tx = txj[jss::tx];
1547 BEAST_EXPECT(tx[jss::Account] == alice.human());
1548 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
1549 return tx[jss::hash].asString();
1552 auto const& txj = jrr[jss::queue_data][0u];
1553 BEAST_EXPECT(txj[jss::account] == alice.human());
1554 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1555 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1556 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
1557 BEAST_EXPECT(txj.isMember(jss::tx));
1558 auto const& tx = txj[jss::tx];
1559 BEAST_EXPECT(tx[jss::Account] == alice.human());
1560 BEAST_EXPECT(tx[jss::TransactionType] == jss::OfferCreate);
1561 const auto txid0 = tx[jss::hash].asString();
1565 BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash));
1573 jv[jss::expand] =
false;
1575 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1576 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1578 auto const& parentHash = env.current()->info().parentHash;
1579 auto const txid1 = [&]() {
1580 auto const& txj = jrr[jss::queue_data][1u];
1581 BEAST_EXPECT(txj[jss::account] == alice.human());
1582 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1583 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1584 BEAST_EXPECT(txj.isMember(jss::tx));
1585 return txj[jss::tx].asString();
1587 auto const& txj = jrr[jss::queue_data][0u];
1588 BEAST_EXPECT(txj[jss::account] == alice.human());
1589 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1590 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1591 BEAST_EXPECT(txj[
"retries_remaining"] == 9);
1592 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1593 BEAST_EXPECT(txj.isMember(jss::tx));
1594 BEAST_EXPECT(txj[jss::tx] == txid0);
1598 BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash));
1603 jv[jss::expand] =
true;
1604 jv[jss::binary] =
true;
1606 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1607 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1609 auto const& txj = jrr[jss::queue_data][1u];
1610 BEAST_EXPECT(txj[jss::account] == alice.human());
1611 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1612 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1613 BEAST_EXPECT(txj[
"retries_remaining"] == 8);
1614 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1615 BEAST_EXPECT(txj.isMember(jss::tx));
1616 BEAST_EXPECT(txj[jss::tx].isMember(jss::tx_blob));
1618 auto const& txj2 = jrr[jss::queue_data][0u];
1619 BEAST_EXPECT(txj2[jss::account] == alice.human());
1620 BEAST_EXPECT(txj2[jss::fee_level] ==
"256");
1621 BEAST_EXPECT(txj2[
"preflight_result"] ==
"tesSUCCESS");
1622 BEAST_EXPECT(txj2[
"retries_remaining"] == 10);
1623 BEAST_EXPECT(!txj2.isMember(
"last_result"));
1624 BEAST_EXPECT(txj2.isMember(jss::tx));
1625 BEAST_EXPECT(txj2[jss::tx].isMember(jss::tx_blob));
1628 for (
int i = 0; i != 9; ++i)
1633 jv[jss::expand] =
false;
1634 jv[jss::binary] =
false;
1636 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1638 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1640 auto const& txj = jrr[jss::queue_data][0u];
1641 BEAST_EXPECT(txj[jss::account] == alice.human());
1642 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1643 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1644 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1645 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1646 BEAST_EXPECT(txj.isMember(jss::tx));
1647 BEAST_EXPECT(txj[jss::tx] != txid0);
1648 return txj[jss::tx].asString();
1653 jv[jss::full] =
true;
1655 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1656 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1658 auto const& txj = jrr[jss::queue_data][0u];
1659 BEAST_EXPECT(txj[jss::account] == alice.human());
1660 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1661 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1662 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1663 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1664 BEAST_EXPECT(txj.isMember(jss::tx));
1665 auto const& tx = txj[jss::tx];
1666 BEAST_EXPECT(tx[jss::Account] == alice.human());
1667 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
1668 BEAST_EXPECT(tx[jss::hash] == txid2);
1675 testcase(
"Ledger Request, Accounts Hashes");
1676 using namespace test::jtx;
1685 jvParams[jss::ledger_index] = 3u;
1686 jvParams[jss::accounts] =
true;
1687 jvParams[jss::expand] =
true;
1688 jvParams[jss::type] =
"hashes";
1690 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1691 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1692 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1693 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1695 jrr[jss::ledger][jss::accountState][0u][
"LedgerEntryType"] ==
1697 index = jrr[jss::ledger][jss::accountState][0u][
"index"].asString();
1701 jvParams[jss::ledger_index] = 3u;
1702 jvParams[jss::accounts] =
true;
1703 jvParams[jss::expand] =
false;
1704 jvParams[jss::type] =
"hashes";
1706 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1707 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1708 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1709 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1710 BEAST_EXPECT(jrr[jss::ledger][jss::accountState][0u] == index);