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);
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");
82 BEAST_EXPECT(jrr[jss::ledger][jss::accepted] ==
true);
84 jrr[jss::ledger][jss::totalCoins] ==
85 env.balance(env.master).value().getText());
90 jvParams[jss::ledger_index] =
"1";
92 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
93 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
true);
94 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"1");
95 BEAST_EXPECT(jrr[jss::ledger][jss::accepted] ==
true);
97 jrr[jss::ledger][jss::totalCoins] ==
98 env.balance(env.master).value().getText());
103 auto const jrr = env.rpc(
"ledger",
"current")[jss::result];
104 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
false);
106 jrr[jss::ledger][jss::ledger_index] ==
109 jrr[jss::ledger_current_index] == env.current()->info().seq);
116 testcase(
"Bad Input");
117 using namespace test::jtx;
119 Account
const gw{
"gateway"};
120 auto const USD = gw[
"USD"];
121 Account
const bob{
"bob"};
123 env.fund(XRP(10000), gw, bob);
125 env.trust(USD(1000), bob);
131 jvParams[jss::ledger_index] =
"potato";
133 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
140 jvParams[jss::ledger_index] = -1;
142 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
149 jvParams[jss::ledger_index] = 10u;
151 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
157 auto const jrr = env.rpc(
"ledger",
"arbitrary_text")[jss::result];
164 jvParams[jss::ledger_index] =
"validated";
165 jvParams[jss::queue] =
true;
167 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
174 env.rpc(
"json",
"ledger",
"{ \"ledger_index\" : 2e15 }");
176 BEAST_EXPECT(ret[jss::error_message] ==
"Invalid parameters.");
181 auto const ret = env.rpc(
182 "json",
"ledger",
"{ \"ledger_index\" : 1000000000000000 }");
190 testcase(
"ledger_current Request");
191 using namespace test::jtx;
196 BEAST_EXPECT(env.current()->info().seq == 4);
199 auto const jrr = env.rpc(
"ledger_current")[jss::result];
201 jrr[jss::ledger_current_index] == env.current()->info().seq);
208 testcase(
"Missing ledger_entry ledger_hash");
209 using namespace test::jtx;
211 Account
const alice{
"alice"};
212 env.fund(XRP(10000), alice);
216 jvParams[jss::account_root] = alice.human();
217 jvParams[jss::ledger_hash] =
218 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
220 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
227 testcase(
"Ledger Request, Full Option");
228 using namespace test::jtx;
235 jvParams[jss::ledger_index] = 3u;
236 jvParams[jss::full] =
true;
238 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
239 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
240 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
241 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 2u);
247 testcase(
"Ledger Request, Full Option Without Admin");
248 using namespace test::jtx;
250 Env env{*
this, envconfig(no_admin)};
255 jvParams[jss::ledger_index] = 1u;
256 jvParams[jss::full] =
true;
258 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
260 jrr,
"noPermission",
"You don't have permission for this command.");
266 testcase(
"Ledger Request, Accounts Option");
267 using namespace test::jtx;
274 jvParams[jss::ledger_index] = 3u;
275 jvParams[jss::accounts] =
true;
277 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
278 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
279 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
280 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 2u);
286 testcase(
"ledger_entry Request AccountRoot");
287 using namespace test::jtx;
289 Account
const alice{
"alice"};
290 env.fund(XRP(10000), alice);
296 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
297 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
298 BEAST_EXPECT(jrr[jss::ledger_index] == 3);
305 jvParams[jss::account_root] = alice.human();
306 jvParams[jss::ledger_hash] = ledgerHash;
308 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
309 BEAST_EXPECT(jrr.
isMember(jss::node));
310 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
312 accountRootIndex = jrr[jss::index].
asString();
315 constexpr
char alicesAcctRootBinary[]{
316 "1100612200800000240000000425000000032D00000000559CE54C3B934E4"
317 "73A995B477E92EC229F99CED5B62BF4D2ACE4DC42719103AE2F6240000002"
318 "540BE4008114AE123A8556F3CF91154711376AFB0F894F832B3D"};
322 jvParams[jss::account_root] = alice.human();
323 jvParams[jss::binary] = 1;
324 jvParams[jss::ledger_hash] = ledgerHash;
326 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
327 BEAST_EXPECT(jrr.
isMember(jss::node_binary));
328 BEAST_EXPECT(jrr[jss::node_binary] == alicesAcctRootBinary);
333 jvParams[jss::index] = accountRootIndex;
335 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
336 BEAST_EXPECT(!jrr.
isMember(jss::node_binary));
337 BEAST_EXPECT(jrr.
isMember(jss::node));
338 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
344 jvParams[jss::index] = accountRootIndex;
345 jvParams[jss::binary] = 0;
347 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
348 BEAST_EXPECT(jrr.
isMember(jss::node));
349 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
356 jvParams[jss::ledger_hash] = ledgerHash;
358 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
364 jvParams[jss::account_root] = Account(
"bob").human();
365 jvParams[jss::ledger_hash] = ledgerHash;
367 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
375 testcase(
"ledger_entry Request Check");
376 using namespace test::jtx;
378 Account
const alice{
"alice"};
379 env.fund(XRP(10000), alice);
382 auto const checkId =
keylet::check(env.master, env.seq(env.master));
384 env(check::create(env.master, alice, XRP(100)));
391 jvParams[jss::check] =
to_string(checkId.key);
392 jvParams[jss::ledger_hash] = ledgerHash;
394 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
405 jvParams[jss::account_root] = alice.human();
407 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
408 accountRootIndex = jrr[jss::index].
asString();
411 jvParams[jss::check] = accountRootIndex;
412 jvParams[jss::ledger_hash] = ledgerHash;
414 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
422 testcase(
"ledger_entry Deposit Preauth");
424 using namespace test::jtx;
427 Account
const alice{
"alice"};
428 Account
const becky{
"becky"};
430 env.fund(XRP(10000), alice, becky);
433 env(deposit::auth(alice, becky));
441 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
442 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
443 jvParams[jss::ledger_hash] = ledgerHash;
445 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
449 jss::DepositPreauth);
452 depositPreauthIndex = jrr[jss::node][jss::index].
asString();
457 jvParams[jss::deposit_preauth] = depositPreauthIndex;
458 jvParams[jss::ledger_hash] = ledgerHash;
460 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
464 jss::DepositPreauth);
471 jvParams[jss::deposit_preauth] = -5;
472 jvParams[jss::ledger_hash] = ledgerHash;
474 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
480 jvParams[jss::deposit_preauth] =
"0123456789ABCDEFG";
481 jvParams[jss::ledger_hash] = ledgerHash;
483 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
489 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
490 jvParams[jss::ledger_hash] = ledgerHash;
492 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
498 jvParams[jss::deposit_preauth][jss::owner] = 7;
499 jvParams[jss::deposit_preauth][jss::authorized] = becky.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::ledger_hash] = ledgerHash;
511 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
517 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
518 jvParams[jss::deposit_preauth][jss::authorized] = 47;
519 jvParams[jss::ledger_hash] = ledgerHash;
521 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
527 jvParams[jss::deposit_preauth][jss::owner] =
528 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
530 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
531 jvParams[jss::ledger_hash] = ledgerHash;
533 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
539 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
540 jvParams[jss::deposit_preauth][jss::authorized] =
541 "rP6P9ypfAmc!pw8SZHNwM4nvZHFXDraQas";
543 jvParams[jss::ledger_hash] = ledgerHash;
545 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
553 testcase(
"ledger_entry Request Directory");
554 using namespace test::jtx;
556 Account
const alice{
"alice"};
557 Account
const gw{
"gateway"};
558 auto const USD = gw[
"USD"];
559 env.fund(XRP(10000), alice, gw);
562 env.trust(USD(1000), alice);
567 for (
int d = 1
'000'032; d >= 1
'000'000; --d)
569 env(offer(alice, USD(1), drops(d)));
576 Json::Value const jrr = env.rpc(
"ledger_closed")[jss::result];
577 BEAST_EXPECT(jrr[jss::ledger_hash] == ledgerHash);
578 BEAST_EXPECT(jrr[jss::ledger_index] == 5);
582 "A33EC6BB85FB5674074C4A3A43373BB17645308F3EAE1933E3E35252162B217D";
586 jvParams[jss::directory] = dirRootIndex;
587 jvParams[jss::ledger_hash] = ledgerHash;
589 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
596 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
598 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
599 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
605 jvParams[jss::directory][jss::owner] = alice.human();
606 jvParams[jss::ledger_hash] = ledgerHash;
608 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
609 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
615 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
616 jvParams[jss::directory][jss::sub_index] = 1;
618 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
619 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
626 jvParams[jss::directory][jss::owner] = alice.human();
627 jvParams[jss::directory][jss::sub_index] = 1;
628 jvParams[jss::ledger_hash] = ledgerHash;
630 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
631 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
638 jvParams[jss::ledger_hash] = ledgerHash;
640 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
647 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
648 jvParams[jss::directory][jss::sub_index] = 1.5;
649 jvParams[jss::ledger_hash] = ledgerHash;
651 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
660 jvParams[jss::directory][jss::owner] = badAddress;
661 jvParams[jss::ledger_hash] = ledgerHash;
663 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
670 jvParams[jss::directory][jss::owner] = alice.human();
671 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
672 jvParams[jss::ledger_hash] = ledgerHash;
674 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
681 jvParams[jss::directory][jss::sub_index] = 1;
682 jvParams[jss::ledger_hash] = ledgerHash;
684 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
692 testcase(
"ledger_entry Request Escrow");
693 using namespace test::jtx;
695 Account
const alice{
"alice"};
696 env.fund(XRP(10000), alice);
705 jv[jss::TransactionType] = jss::EscrowCreate;
707 jv[jss::Account] = account.human();
708 jv[jss::Destination] = to.human();
711 cancelAfter.time_since_epoch().count() + 2;
715 using namespace std::chrono_literals;
716 env(escrowCreate(alice, alice, XRP(333), env.now() + 2s));
725 jvParams[jss::escrow][jss::owner] = alice.human();
726 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
728 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
730 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
731 escrowIndex = jrr[jss::index].
asString();
736 jvParams[jss::escrow] = escrowIndex;
737 jvParams[jss::ledger_hash] = ledgerHash;
739 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
741 jrr[jss::node][jss::Amount] == XRP(333).value().getText());
749 jvParams[jss::escrow][jss::owner] = badAddress;
750 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
751 jvParams[jss::ledger_hash] = ledgerHash;
753 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
760 jvParams[jss::escrow][jss::seq] = env.seq(alice) - 1;
761 jvParams[jss::ledger_hash] = ledgerHash;
763 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
770 jvParams[jss::escrow][jss::owner] = alice.human();
771 jvParams[jss::ledger_hash] = ledgerHash;
773 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
780 jvParams[jss::escrow][jss::owner] = alice.human();
781 jvParams[jss::escrow][jss::seq] =
783 jvParams[jss::ledger_hash] = ledgerHash;
785 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
793 testcase(
"ledger_entry Request Offer");
794 using namespace test::jtx;
796 Account
const alice{
"alice"};
797 Account
const gw{
"gateway"};
798 auto const USD = gw[
"USD"];
799 env.fund(XRP(10000), alice, gw);
802 env(offer(alice, USD(321), XRP(322)));
811 jvParams[jss::offer][jss::account] = alice.human();
812 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
813 jvParams[jss::ledger_hash] = ledgerHash;
815 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
816 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
817 offerIndex = jrr[jss::index].
asString();
822 jvParams[jss::offer] = offerIndex;
824 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
825 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
833 jvParams[jss::offer][jss::account] = badAddress;
834 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
835 jvParams[jss::ledger_hash] = ledgerHash;
837 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
844 jvParams[jss::offer][jss::seq] = env.seq(alice) - 1;
845 jvParams[jss::ledger_hash] = ledgerHash;
847 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
854 jvParams[jss::offer][jss::account] = alice.human();
855 jvParams[jss::ledger_hash] = ledgerHash;
857 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
864 jvParams[jss::offer][jss::account] = alice.human();
865 jvParams[jss::offer][jss::seq] =
std::to_string(env.seq(alice) - 1);
866 jvParams[jss::ledger_hash] = ledgerHash;
868 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
876 testcase(
"ledger_entry Request Pay Chan");
877 using namespace test::jtx;
878 using namespace std::literals::chrono_literals;
880 Account
const alice{
"alice"};
882 env.fund(XRP(10000), alice);
892 jv[jss::TransactionType] = jss::PaymentChannelCreate;
893 jv[jss::Account] = account.human();
894 jv[jss::Destination] = to.human();
901 env(payChanCreate(alice, env.master, XRP(57), 18s, alice.pk()));
911 jvParams[jss::payment_channel] =
to_string(payChanIndex);
912 jvParams[jss::ledger_hash] = ledgerHash;
914 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
922 jvParams[jss::payment_channel] = ledgerHash;
923 jvParams[jss::ledger_hash] = ledgerHash;
925 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
933 testcase(
"ledger_entry Request RippleState");
934 using namespace test::jtx;
936 Account
const alice{
"alice"};
937 Account
const gw{
"gateway"};
938 auto const USD = gw[
"USD"];
939 env.fund(XRP(10000), alice, gw);
942 env.trust(USD(999), alice);
945 env(pay(gw, alice, USD(97)));
954 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
955 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
956 jvParams[jss::ripple_state][jss::currency] =
"USD";
957 jvParams[jss::ledger_hash] = ledgerHash;
959 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
968 jvParams[jss::ripple_state] =
"ripple_state";
969 jvParams[jss::ledger_hash] = ledgerHash;
971 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
979 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
980 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
981 jvParams[jss::ledger_hash] = ledgerHash;
983 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
990 jvParams[jss::ripple_state][jss::accounts] = 2;
991 jvParams[jss::ripple_state][jss::currency] =
"USD";
992 jvParams[jss::ledger_hash] = ledgerHash;
994 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1002 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1003 jvParams[jss::ripple_state][jss::currency] =
"USD";
1004 jvParams[jss::ledger_hash] = ledgerHash;
1006 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1014 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1015 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1016 jvParams[jss::ripple_state][jss::accounts][2u] = alice.human();
1017 jvParams[jss::ripple_state][jss::currency] =
"USD";
1018 jvParams[jss::ledger_hash] = ledgerHash;
1020 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1028 jvParams[jss::ripple_state][jss::accounts][0u] = 44;
1029 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1030 jvParams[jss::ripple_state][jss::currency] =
"USD";
1031 jvParams[jss::ledger_hash] = ledgerHash;
1033 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1041 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1042 jvParams[jss::ripple_state][jss::accounts][1u] = 21;
1043 jvParams[jss::ripple_state][jss::currency] =
"USD";
1044 jvParams[jss::ledger_hash] = ledgerHash;
1046 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1054 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1055 jvParams[jss::ripple_state][jss::accounts][1u] = alice.human();
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] =
1069 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1070 jvParams[jss::ripple_state][jss::currency] =
"USD";
1071 jvParams[jss::ledger_hash] = ledgerHash;
1073 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1081 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1082 jvParams[jss::ripple_state][jss::accounts][1u] =
1084 jvParams[jss::ripple_state][jss::currency] =
"USD";
1085 jvParams[jss::ledger_hash] = ledgerHash;
1087 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1095 jvParams[jss::ripple_state][jss::accounts][0u] = alice.human();
1096 jvParams[jss::ripple_state][jss::accounts][1u] = gw.human();
1097 jvParams[jss::ripple_state][jss::currency] =
"USDollars";
1098 jvParams[jss::ledger_hash] = ledgerHash;
1100 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1108 testcase(
"ledger_entry Request Ticket");
1109 using namespace test::jtx;
1115 env(ticket::create(env.master, 2));
1125 jvParams[jss::ticket] =
1127 jvParams[jss::ledger_hash] = ledgerHash;
1129 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1136 jvParams[jss::ledger_hash] = ledgerHash;
1138 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1147 jvParams[jss::ticket][jss::account] = env.master.human();
1148 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 1;
1149 jvParams[jss::ledger_hash] = ledgerHash;
1151 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1153 jrr[jss::node][jss::index] ==
1160 jvParams[jss::ticket][jss::account] = env.master.human();
1161 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 2;
1162 jvParams[jss::ledger_hash] = ledgerHash;
1164 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1171 jvParams[jss::ledger_hash] = ledgerHash;
1173 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1182 jvParams[jss::ticket][jss::account] = badAddress;
1183 jvParams[jss::ticket][jss::ticket_seq] = env.seq(env.master) - 1;
1184 jvParams[jss::ledger_hash] = ledgerHash;
1186 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1193 jvParams[jss::ticket][jss::ticket_seq] = env.seq(env.master) - 1;
1194 jvParams[jss::ledger_hash] = ledgerHash;
1196 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1203 jvParams[jss::ticket][jss::account] = env.master.human();
1204 jvParams[jss::ledger_hash] = ledgerHash;
1206 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1213 jvParams[jss::ticket][jss::account] = env.master.human();
1214 jvParams[jss::ticket][jss::ticket_seq] =
1216 jvParams[jss::ledger_hash] = ledgerHash;
1218 "json",
"ledger_entry",
to_string(jvParams))[jss::result];
1226 testcase(
"ledger_entry Request Unknown Option");
1227 using namespace test::jtx;
1234 jvParams[jss::features] = ledgerHash;
1235 jvParams[jss::ledger_hash] = ledgerHash;
1237 env.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1248 testcase(
"Lookup ledger");
1249 using namespace test::jtx;
1252 env.fund(XRP(10000),
"alice");
1254 env.fund(XRP(10000),
"bob");
1256 env.fund(XRP(10000),
"jim");
1258 env.fund(XRP(10000),
"jill");
1270 jvParams[jss::ledger] =
"closed";
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] =
"validated";
1283 boost::lexical_cast<std::string>(jvParams))[jss::result];
1284 BEAST_EXPECT(jrr.isMember(jss::ledger));
1285 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1286 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1288 jvParams[jss::ledger] =
"current";
1292 boost::lexical_cast<std::string>(jvParams))[jss::result];
1293 BEAST_EXPECT(jrr.isMember(jss::ledger));
1294 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1297 jvParams[jss::ledger] =
"invalid";
1301 boost::lexical_cast<std::string>(jvParams))[jss::result];
1302 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1303 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1306 jvParams[jss::ledger] = 4;
1310 boost::lexical_cast<std::string>(jvParams))[jss::result];
1311 BEAST_EXPECT(jrr.isMember(jss::ledger));
1312 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1313 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"4");
1316 jvParams[jss::ledger] = 20;
1320 boost::lexical_cast<std::string>(jvParams))[jss::result];
1321 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1322 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1328 jvParams[jss::ledger_hash] =
1329 "7C3EEDB3124D92E49E75D81A8826A2E6"
1330 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1334 boost::lexical_cast<std::string>(jvParams))[jss::result];
1335 BEAST_EXPECT(jrr.isMember(jss::ledger));
1336 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1337 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"3");
1340 jvParams[jss::ledger_hash] =
1342 "7C3EEDB3124D92E49E75D81A8826A2E6"
1343 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1347 boost::lexical_cast<std::string>(jvParams))[jss::result];
1348 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1349 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1352 jvParams[jss::ledger_hash] = 2;
1356 boost::lexical_cast<std::string>(jvParams))[jss::result];
1357 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1358 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashNotString");
1361 jvParams[jss::ledger_hash] =
1362 "ZZZZZZZZZZZD92E49E75D81A8826A2E6"
1363 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1367 boost::lexical_cast<std::string>(jvParams))[jss::result];
1368 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1369 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1372 jvParams[jss::ledger_hash] =
1373 "8C3EEDB3124D92E49E75D81A8826A2E6"
1374 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1378 boost::lexical_cast<std::string>(jvParams))[jss::result];
1379 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1380 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1386 jvParams[jss::ledger_index] =
"closed";
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");
1394 BEAST_EXPECT(jrr.isMember(jss::ledger_index));
1396 jvParams[jss::ledger_index] =
"validated";
1400 boost::lexical_cast<std::string>(jvParams))[jss::result];
1401 BEAST_EXPECT(jrr.isMember(jss::ledger));
1402 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1403 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1405 jvParams[jss::ledger_index] =
"current";
1409 boost::lexical_cast<std::string>(jvParams))[jss::result];
1410 BEAST_EXPECT(jrr.isMember(jss::ledger));
1411 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1412 BEAST_EXPECT(jrr.isMember(jss::ledger_current_index));
1415 jvParams[jss::ledger_index] =
"invalid";
1419 boost::lexical_cast<std::string>(jvParams))[jss::result];
1420 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1421 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1424 for (
auto i : {1, 2, 3, 4, 5, 6})
1426 jvParams[jss::ledger_index] = i;
1430 boost::lexical_cast<std::string>(jvParams))[jss::result];
1431 BEAST_EXPECT(jrr.isMember(jss::ledger));
1433 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1439 jvParams[jss::ledger_index] = 7;
1443 boost::lexical_cast<std::string>(jvParams))[jss::result];
1444 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1445 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1452 testcase(
"Ledger with queueing disabled");
1453 using namespace test::jtx;
1457 jv[jss::ledger_index] =
"current";
1458 jv[jss::queue] =
true;
1459 jv[jss::expand] =
true;
1461 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1462 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1468 testcase(
"Ledger with Queued Transactions");
1469 using namespace test::jtx;
1471 auto& section = cfg->section(
"transaction_queue");
1472 section.set(
"minimum_txn_in_ledger_standalone",
"3");
1473 section.set(
"normal_consensus_increase_percent",
"0");
1478 jv[jss::ledger_index] =
"current";
1479 jv[jss::queue] =
true;
1480 jv[jss::expand] =
true;
1482 Account
const alice{
"alice"};
1483 Account
const bob{
"bob"};
1484 Account
const charlie{
"charlie"};
1485 Account
const daria{
"daria"};
1486 env.fund(XRP(10000), alice);
1487 env.fund(XRP(10000), bob);
1489 env.fund(XRP(10000), charlie);
1490 env.fund(XRP(10000), daria);
1493 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1494 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1499 auto metrics = env.app().getTxQ().getMetrics(*env.current());
1500 if (metrics.openLedgerFeeLevel > metrics.minProcessingFeeLevel)
1505 BEAST_EXPECT(env.current()->info().seq == 5);
1508 auto aliceSeq = env.seq(alice);
1509 env(pay(alice,
"george", XRP(1000)),
1510 json(R
"({"LastLedgerSequence":7})"),
1512 env(offer(alice, XRP(50000), alice["USD"](5000)),
1515 env(noop(alice), seq(aliceSeq + 2), ter(
terQUEUED));
1517 auto batch = [&env](Account a) {
1518 auto aSeq = env.seq(a);
1520 for (
int i = 0; i < 10; ++i)
1522 env(noop(a), fee(1000 + i), seq(aSeq + i), ter(
terQUEUED));
1531 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1532 BEAST_EXPECT(jrr[jss::queue_data].size() == 33);
1538 BEAST_EXPECT(env.current()->info().seq == 8);
1540 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1541 BEAST_EXPECT(jrr[jss::queue_data].size() == 11);
1545 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1548 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1550 auto const& txj = jrr[jss::queue_data][0u];
1551 BEAST_EXPECT(txj[jss::account] == alice.human());
1552 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1553 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1554 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
1555 BEAST_EXPECT(txj.isMember(jss::tx));
1556 auto const& tx = txj[jss::tx];
1557 BEAST_EXPECT(tx[jss::Account] == alice.human());
1558 BEAST_EXPECT(tx[jss::TransactionType] == jss::OfferCreate);
1559 txid1 = tx[jss::hash].asString();
1564 jv[jss::expand] =
false;
1566 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1567 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1569 auto const& txj = jrr[jss::queue_data][0u];
1570 BEAST_EXPECT(txj[jss::account] == alice.human());
1571 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1572 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1573 BEAST_EXPECT(txj[
"retries_remaining"] == 9);
1574 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1575 BEAST_EXPECT(txj.isMember(jss::tx));
1576 BEAST_EXPECT(txj[jss::tx] == txid1);
1581 jv[jss::expand] =
true;
1582 jv[jss::binary] =
true;
1584 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1585 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
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"] == 8);
1592 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1593 BEAST_EXPECT(txj.isMember(jss::tx));
1594 BEAST_EXPECT(txj[jss::tx].isMember(jss::tx_blob));
1596 auto const& txj2 = jrr[jss::queue_data][1u];
1597 BEAST_EXPECT(txj2[jss::account] == alice.human());
1598 BEAST_EXPECT(txj2[jss::fee_level] ==
"256");
1599 BEAST_EXPECT(txj2[
"preflight_result"] ==
"tesSUCCESS");
1600 BEAST_EXPECT(txj2[
"retries_remaining"] == 10);
1601 BEAST_EXPECT(!txj2.isMember(
"last_result"));
1602 BEAST_EXPECT(txj2.isMember(jss::tx));
1603 BEAST_EXPECT(txj2[jss::tx].isMember(jss::tx_blob));
1606 for (
int i = 0; i != 9; ++i)
1611 jv[jss::expand] =
false;
1612 jv[jss::binary] =
false;
1614 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1615 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1617 auto const& txj = jrr[jss::queue_data][0u];
1618 BEAST_EXPECT(txj[jss::account] == alice.human());
1619 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1620 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1621 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1622 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1623 BEAST_EXPECT(txj.isMember(jss::tx));
1624 BEAST_EXPECT(txj[jss::tx] != txid1);
1625 txid2 = txj[jss::tx].asString();
1628 jv[jss::full] =
true;
1630 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1631 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1633 auto const& txj = jrr[jss::queue_data][0u];
1634 BEAST_EXPECT(txj[jss::account] == alice.human());
1635 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1636 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1637 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1638 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1639 BEAST_EXPECT(txj.isMember(jss::tx));
1640 auto const& tx = txj[jss::tx];
1641 BEAST_EXPECT(tx[jss::Account] == alice.human());
1642 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
1643 BEAST_EXPECT(tx[jss::hash] == txid2);
1650 testcase(
"Ledger Request, Accounts Option");
1651 using namespace test::jtx;
1660 jvParams[jss::ledger_index] = 3u;
1661 jvParams[jss::accounts] =
true;
1662 jvParams[jss::expand] =
true;
1663 jvParams[jss::type] =
"hashes";
1665 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1666 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1667 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1668 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1670 jrr[jss::ledger][jss::accountState][0u][
"LedgerEntryType"] ==
1672 index = jrr[jss::ledger][jss::accountState][0u][
"index"].asString();
1676 jvParams[jss::ledger_index] = 3u;
1677 jvParams[jss::accounts] =
true;
1678 jvParams[jss::expand] =
false;
1679 jvParams[jss::type] =
"hashes";
1681 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1682 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1683 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1684 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1685 BEAST_EXPECT(jrr[jss::ledger][jss::accountState][0u] == index);