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 log << env.closed()->info().hash;
1255 env.fund(XRP(10000),
"bob");
1257 log << env.closed()->info().hash;
1258 env.fund(XRP(10000),
"jim");
1260 log << env.closed()->info().hash;
1261 env.fund(XRP(10000),
"jill");
1266 jvParams[jss::ledger] =
"closed";
1270 boost::lexical_cast<std::string>(jvParams))[jss::result];
1271 BEAST_EXPECT(jrr.isMember(jss::ledger));
1272 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1273 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1275 jvParams[jss::ledger] =
"validated";
1279 boost::lexical_cast<std::string>(jvParams))[jss::result];
1280 BEAST_EXPECT(jrr.isMember(jss::ledger));
1281 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1282 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1284 jvParams[jss::ledger] =
"current";
1288 boost::lexical_cast<std::string>(jvParams))[jss::result];
1289 BEAST_EXPECT(jrr.isMember(jss::ledger));
1290 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1293 jvParams[jss::ledger] =
"invalid";
1297 boost::lexical_cast<std::string>(jvParams))[jss::result];
1298 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1299 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1302 jvParams[jss::ledger] = 4;
1306 boost::lexical_cast<std::string>(jvParams))[jss::result];
1307 BEAST_EXPECT(jrr.isMember(jss::ledger));
1308 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1309 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"4");
1312 jvParams[jss::ledger] = 20;
1316 boost::lexical_cast<std::string>(jvParams))[jss::result];
1317 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1318 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1324 jvParams[jss::ledger_hash] =
1325 "2E81FC6EC0DD943197E0C7E3FBE9AE30"
1326 "7F2775F2F7485BB37307984C3C0F2340";
1330 boost::lexical_cast<std::string>(jvParams))[jss::result];
1331 BEAST_EXPECT(jrr.isMember(jss::ledger));
1332 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1333 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"3");
1336 jvParams[jss::ledger_hash] =
1338 "2E81FC6EC0DD943197E0C7E3FBE9AE30"
1339 "7F2775F2F7485BB37307984C3C0F2340";
1343 boost::lexical_cast<std::string>(jvParams))[jss::result];
1344 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1345 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1348 jvParams[jss::ledger_hash] = 2;
1352 boost::lexical_cast<std::string>(jvParams))[jss::result];
1353 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1354 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashNotString");
1357 jvParams[jss::ledger_hash] =
1358 "2E81FC6EC0DD943197EGC7E3FBE9AE30"
1359 "7F2775F2F7485BB37307984C3C0F2340";
1363 boost::lexical_cast<std::string>(jvParams))[jss::result];
1364 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1365 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerHashMalformed");
1368 jvParams[jss::ledger_hash] =
1369 "8C3EEDB3124D92E49E75D81A8826A2E6"
1370 "5A75FD71FC3FD6F36FEB803C5F1D812D";
1374 boost::lexical_cast<std::string>(jvParams))[jss::result];
1375 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1376 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1382 jvParams[jss::ledger_index] =
"closed";
1386 boost::lexical_cast<std::string>(jvParams))[jss::result];
1387 BEAST_EXPECT(jrr.isMember(jss::ledger));
1388 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1389 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1390 BEAST_EXPECT(jrr.isMember(jss::ledger_index));
1392 jvParams[jss::ledger_index] =
"validated";
1396 boost::lexical_cast<std::string>(jvParams))[jss::result];
1397 BEAST_EXPECT(jrr.isMember(jss::ledger));
1398 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1399 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
1401 jvParams[jss::ledger_index] =
"current";
1405 boost::lexical_cast<std::string>(jvParams))[jss::result];
1406 BEAST_EXPECT(jrr.isMember(jss::ledger));
1407 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
1408 BEAST_EXPECT(jrr.isMember(jss::ledger_current_index));
1411 jvParams[jss::ledger_index] =
"invalid";
1415 boost::lexical_cast<std::string>(jvParams))[jss::result];
1416 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
1417 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerIndexMalformed");
1420 for (
auto i : {1, 2, 3, 4, 5, 6})
1422 jvParams[jss::ledger_index] = i;
1426 boost::lexical_cast<std::string>(jvParams))[jss::result];
1427 BEAST_EXPECT(jrr.isMember(jss::ledger));
1429 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
1435 jvParams[jss::ledger_index] = 7;
1439 boost::lexical_cast<std::string>(jvParams))[jss::result];
1440 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
1441 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
1448 testcase(
"Ledger with queueing disabled");
1449 using namespace test::jtx;
1453 jv[jss::ledger_index] =
"current";
1454 jv[jss::queue] =
true;
1455 jv[jss::expand] =
true;
1457 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1458 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1464 testcase(
"Ledger with Queued Transactions");
1465 using namespace test::jtx;
1467 auto& section = cfg->section(
"transaction_queue");
1468 section.set(
"minimum_txn_in_ledger_standalone",
"3");
1469 section.set(
"normal_consensus_increase_percent",
"0");
1474 jv[jss::ledger_index] =
"current";
1475 jv[jss::queue] =
true;
1476 jv[jss::expand] =
true;
1478 Account
const alice{
"alice"};
1479 Account
const bob{
"bob"};
1480 Account
const charlie{
"charlie"};
1481 Account
const daria{
"daria"};
1482 env.fund(XRP(10000), alice);
1483 env.fund(XRP(10000), bob);
1485 env.fund(XRP(10000), charlie);
1486 env.fund(XRP(10000), daria);
1489 auto jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1490 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
1495 auto metrics = env.app().getTxQ().getMetrics(*env.current());
1496 if (metrics.openLedgerFeeLevel > metrics.minProcessingFeeLevel)
1501 BEAST_EXPECT(env.current()->info().seq == 5);
1504 auto aliceSeq = env.seq(alice);
1505 env(pay(alice,
"george", XRP(1000)),
1506 json(R
"({"LastLedgerSequence":7})"),
1508 env(offer(alice, XRP(50000), alice["USD"](5000)),
1511 env(noop(alice), seq(aliceSeq + 2), ter(
terQUEUED));
1513 auto batch = [&env](Account a) {
1514 auto aSeq = env.seq(a);
1516 for (
int i = 0; i < 10; ++i)
1518 env(noop(a), fee(1000 + i), seq(aSeq + i), ter(
terQUEUED));
1527 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1528 BEAST_EXPECT(jrr[jss::queue_data].size() == 33);
1534 BEAST_EXPECT(env.current()->info().seq == 8);
1536 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1537 BEAST_EXPECT(jrr[jss::queue_data].size() == 11);
1541 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1544 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1546 auto const& txj = jrr[jss::queue_data][0u];
1547 BEAST_EXPECT(txj[jss::account] == alice.human());
1548 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1549 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1550 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
1551 BEAST_EXPECT(txj.isMember(jss::tx));
1552 auto const& tx = txj[jss::tx];
1553 BEAST_EXPECT(tx[jss::Account] == alice.human());
1554 BEAST_EXPECT(tx[jss::TransactionType] == jss::OfferCreate);
1555 txid1 = tx[jss::hash].asString();
1560 jv[jss::expand] =
false;
1562 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1563 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1565 auto const& txj = jrr[jss::queue_data][0u];
1566 BEAST_EXPECT(txj[jss::account] == alice.human());
1567 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1568 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1569 BEAST_EXPECT(txj[
"retries_remaining"] == 9);
1570 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1571 BEAST_EXPECT(txj.isMember(jss::tx));
1572 BEAST_EXPECT(txj[jss::tx] == txid1);
1577 jv[jss::expand] =
true;
1578 jv[jss::binary] =
true;
1580 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1581 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
1583 auto const& txj = jrr[jss::queue_data][0u];
1584 BEAST_EXPECT(txj[jss::account] == alice.human());
1585 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1586 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1587 BEAST_EXPECT(txj[
"retries_remaining"] == 8);
1588 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1589 BEAST_EXPECT(txj.isMember(jss::tx));
1590 BEAST_EXPECT(txj[jss::tx].isMember(jss::tx_blob));
1592 auto const& txj2 = jrr[jss::queue_data][1u];
1593 BEAST_EXPECT(txj2[jss::account] == alice.human());
1594 BEAST_EXPECT(txj2[jss::fee_level] ==
"256");
1595 BEAST_EXPECT(txj2[
"preflight_result"] ==
"tesSUCCESS");
1596 BEAST_EXPECT(txj2[
"retries_remaining"] == 10);
1597 BEAST_EXPECT(!txj2.isMember(
"last_result"));
1598 BEAST_EXPECT(txj2.isMember(jss::tx));
1599 BEAST_EXPECT(txj2[jss::tx].isMember(jss::tx_blob));
1602 for (
int i = 0; i != 9; ++i)
1607 jv[jss::expand] =
false;
1608 jv[jss::binary] =
false;
1610 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1611 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1613 auto const& txj = jrr[jss::queue_data][0u];
1614 BEAST_EXPECT(txj[jss::account] == alice.human());
1615 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1616 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1617 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1618 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1619 BEAST_EXPECT(txj.isMember(jss::tx));
1620 BEAST_EXPECT(txj[jss::tx] != txid1);
1621 txid2 = txj[jss::tx].asString();
1624 jv[jss::full] =
true;
1626 jrr = env.rpc(
"json",
"ledger",
to_string(jv))[jss::result];
1627 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
1629 auto const& txj = jrr[jss::queue_data][0u];
1630 BEAST_EXPECT(txj[jss::account] == alice.human());
1631 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
1632 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
1633 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
1634 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
1635 BEAST_EXPECT(txj.isMember(jss::tx));
1636 auto const& tx = txj[jss::tx];
1637 BEAST_EXPECT(tx[jss::Account] == alice.human());
1638 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
1639 BEAST_EXPECT(tx[jss::hash] == txid2);
1646 testcase(
"Ledger Request, Accounts Option");
1647 using namespace test::jtx;
1656 jvParams[jss::ledger_index] = 3u;
1657 jvParams[jss::accounts] =
true;
1658 jvParams[jss::expand] =
true;
1659 jvParams[jss::type] =
"hashes";
1661 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1662 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1663 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1664 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1666 jrr[jss::ledger][jss::accountState][0u][
"LedgerEntryType"] ==
1668 index = jrr[jss::ledger][jss::accountState][0u][
"index"].asString();
1672 jvParams[jss::ledger_index] = 3u;
1673 jvParams[jss::accounts] =
true;
1674 jvParams[jss::expand] =
false;
1675 jvParams[jss::type] =
"hashes";
1677 env.rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
1678 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
1679 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
1680 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].size() == 1u);
1681 BEAST_EXPECT(jrr[jss::ledger][jss::accountState][0u] == index);