20 #include <ripple/beast/unit_test.h>
21 #include <ripple/protocol/ErrorCodes.h>
22 #include <ripple/protocol/TxFlags.h>
23 #include <ripple/protocol/jss.h>
36 testcase(
"account_lines");
38 using namespace test::jtx;
42 auto const lines =
env.rpc(
"json",
"account_lines",
"{ }");
44 lines[jss::result][jss::error_message] ==
49 auto const lines =
env.rpc(
53 R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"})");
55 lines[jss::result][jss::error_message] ==
58 Account const alice{
"alice"};
61 auto const lines =
env.rpc(
64 R
"({"account": ")" + alice.human() + R"("})");
66 lines[jss::result][jss::error_message] ==
69 env.fund(XRP(10000), alice);
76 auto const lines =
env.rpc(
79 R
"({"account": ")" + alice.human() + R"("})");
81 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 0);
85 auto const lines =
env.rpc(
88 R
"({"account": ")" + alice.human() +
90 R"("ledger_index": "nonsense"})");
92 lines[jss::result][jss::error_message] ==
93 "ledgerIndexMalformed");
97 auto const lines =
env.rpc(
100 R
"({"account": ")" + alice.human() +
102 R"("ledger_index": 50000})");
104 lines[jss::result][jss::error_message] == "ledgerNotFound");
107 Account
const gw1{
"gw1"};
108 env.fund(XRP(10000),
gw1);
111 for (
char c = 0; c <= (
'Z' -
'A'); ++c)
119 env(trust(alice, gw1Currency(100 + c)));
120 env(pay(
gw1, alice, gw1Currency(50 + c)));
128 Account
const gw2{
"gw2"};
129 env.fund(XRP(10000),
gw2);
136 for (
char c = 0; c <= (
'Z' -
'A'); ++c)
144 env(trust(alice, gw2Currency(200 + c)));
147 env(pay(
gw2, alice, gw2Currency(100 + c)));
159 Account
const& account,
163 auto const linesSeq =
env.rpc(
166 R
"({"account": ")" + account.human() +
168 R"("ledger_index": )" +
170 BEAST_EXPECT(linesSeq[jss::result][jss::lines].isArray());
171 BEAST_EXPECT(linesSeq[jss::result][jss::lines].size() == count);
174 auto const linesHash =
env.rpc(
177 R
"({"account": ")" + account.human() +
179 R"("ledger_hash": ")" +
181 BEAST_EXPECT(linesHash[jss::result][jss::lines].isArray());
182 BEAST_EXPECT(linesHash[jss::result][jss::lines].size() == count);
197 auto const lines =
env.rpc(
200 R
"({"account": ")" + alice.human() +
202 R"("ledger_hash": ")" +
205 R"("ledger_index": )" +
208 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
212 auto const lines =
env.rpc(
215 R
"({"account": ")" + alice.human() + R"("})");
217 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 52);
221 auto const lines =
env.rpc(
224 R
"({"account": ")" + alice.human() +
227 gw1.human() + R"("})");
229 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
233 auto const lines =
env.rpc(
236 R
"({"account": ")" + alice.human() +
239 R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"})");
241 lines[jss::result][jss::error_message] ==
246 auto const lines =
env.rpc(
249 R
"({"account": ")" + alice.human() +
253 lines[jss::result][jss::error_message] ==
258 auto const linesA =
env.rpc(
261 R
"({"account": ")" + alice.human() +
264 BEAST_EXPECT(linesA[jss::result][jss::lines].isArray());
265 BEAST_EXPECT(linesA[jss::result][jss::lines].size() == 1);
268 auto marker = linesA[jss::result][jss::marker].asString();
272 R
"({"account": ")" + alice.human() +
283 R
"({"account": ")" + alice.human() +
296 R
"({"account": ")" + alice.human() +
301 linesD[jss::result][jss::error_message] ==
306 auto const lines =
env.rpc(
309 R
"({"account": ")" + alice.human() +
311 R"("marker": true})");
313 lines[jss::result][jss::error_message] ==
318 auto const lines =
env.rpc(
321 R
"({"account": ")" + alice.human() +
325 gw2.human() + R"("})");
326 auto const&
line = lines[jss::result][jss::lines][0u];
333 auto const linesA =
env.rpc(
336 R
"({"account": ")" + gw2.human() +
340 alice.human() + R"("})");
341 auto const&
lineA = linesA[jss::result][jss::lines][0u];
347 BEAST_EXPECT(linesA[jss::result].isMember(jss::marker));
348 auto const marker = linesA[jss::result][jss::marker].asString();
352 R
"({"account": ")" + gw2.human() +
359 alice.human() + R"("})");
367 testAccountLinesMarker()
369 testcase(
"Entry pointed to by marker is not owned by account");
370 using namespace test::jtx;
379 Account
const alice{
"alice"};
380 Account
const becky{
"becky"};
381 Account
const gw1{
"gw1"};
386 Account
const bogie{
"bogie"};
390 auto const EUR =
gw1[
"EUR"];
402 R
"({"account": ")" + alice.human() +
406 aliceObjects[jss::result][jss::account_objects][0u];
410 "alice's account objects are misordered. "
411 "Please reorder the objects so the SignerList is first.",
419 auto const aliceLines1 =
env.rpc(
422 R
"({"account": ")" + alice.human() + R"(", "limit": 1})");
423 BEAST_EXPECT(aliceLines1[jss::result].isMember(jss::marker));
427 aliceLines1[jss::result][jss::marker].asString();
430 BEAST_EXPECT(markerIndex == aliceSignerList[jss::index].asString());
433 auto const aliceLines2 =
env.rpc(
436 R
"({"account": ")" + alice.human() + R"(", "marker": ")" +
437 aliceMarker + R"("})");
439 BEAST_EXPECT(!aliceLines2[jss::result].isMember(jss::marker));
443 auto const beckyLines =
env.rpc(
446 R
"({"account": ")" + becky.human() + R"(", "marker": ")" +
447 aliceMarker + R"("})");
448 BEAST_EXPECT(beckyLines[jss::result].isMember(jss::error_message));
452 testAccountLineDelete()
454 testcase(
"Entry pointed to by marker is removed");
455 using namespace test::jtx;
469 Account
const alice{
"alice"};
470 Account
const becky{
"becky"};
471 Account
const cheri{
"cheri"};
472 Account
const gw1{
"gw1"};
473 Account
const gw2{
"gw2"};
477 auto const USD =
gw1[
"USD"];
478 auto const AUD =
gw1[
"AUD"];
479 auto const EUR =
gw2[
"EUR"];
499 auto const linesBeg =
env.rpc(
502 R
"({"account": ")" + alice.human() +
506 linesBeg[jss::result][jss::lines][0u][jss::currency] == "USD");
507 BEAST_EXPECT(linesBeg[jss::result].isMember(jss::marker));
510 env(
pay(alice, cheri, EUR(100)));
515 auto const linesEnd =
env.rpc(
518 R
"({"account": ")" + alice.human() +
521 linesBeg[jss::result][jss::marker].asString() + R"("})");
523 linesEnd[jss::result][jss::error_message] ==
528 testAccountLinesWalkMarkers()
530 testcase(
"Marker can point to any appropriate ledger entry type");
531 using namespace test::jtx;
532 using namespace std::chrono_literals;
541 Account
const alice{
"alice"};
542 Account
const becky{
"becky"};
543 Account
const gw1{
"gw1"};
549 Account
const& account,
551 STAmount
const& amount) {
553 jv[jss::TransactionType] = jss::EscrowCreate;
555 jv[jss::Account] = account.human();
556 jv[jss::Destination] = to.human();
563 auto payChan = [](Account
const& account,
565 STAmount
const& amount,
567 PublicKey
const& pk) {
569 jv[jss::TransactionType] = jss::PaymentChannelCreate;
571 jv[jss::Account] = account.human();
572 jv[jss::Destination] = to.human();
574 jv[
"SettleDelay"] = settleDelay.count();
575 jv[
"PublicKey"] =
strHex(pk.slice());
584 Account
const bogie{
"bogie"};
593 auto const EUR =
gw1[
"EUR"];
616 env(token::createOffer(alice, beckyNFtokenID,
drops(1)),
617 token::owner(becky));
618 env(token::createOffer(becky, aliceNFtokenID,
drops(1)),
619 token::owner(alice));
621 env(token::createOffer(becky, beckyNFtokenID,
drops(1)),
623 token::destination(alice));
624 env(token::createOffer(alice, aliceNFtokenID,
drops(1)),
626 token::destination(becky));
628 env(token::createOffer(
gw1, beckyNFtokenID,
drops(1)),
630 token::destination(alice));
631 env(token::createOffer(
gw1, aliceNFtokenID,
drops(1)),
633 token::destination(becky));
635 env(token::createOffer(becky, beckyNFtokenID,
drops(1)),
637 env(token::createOffer(alice, aliceNFtokenID,
drops(1)),
641 env(check::create(alice, becky,
XRP(50)));
642 env(check::create(becky, alice,
XRP(50)));
645 env(deposit::auth(alice, becky));
646 env(deposit::auth(becky, alice));
650 auto const USDalice = alice[
"USD"];
655 env(ticket::create(alice, 2));
658 auto const BTCbecky = becky[
"BTC"];
667 auto getNextLine = [](Env&
env,
668 Account
const& alice,
671 params[jss::account] = alice.human();
672 params[jss::limit] = 1;
674 params[jss::marker] = *
marker;
676 return env.rpc(
"json",
"account_lines",
to_string(params));
679 auto aliceLines = getNextLine(
env, alice, std::nullopt);
684 auto hasMarker = [](
auto const& aliceLines) {
685 return aliceLines[jss::result].isMember(jss::marker);
687 auto marker = [](
auto const& aliceLines) {
688 return aliceLines[jss::result][jss::marker].asString();
690 auto checkLines = [](
auto const& aliceLines) {
691 return aliceLines.isMember(jss::result) &&
692 !aliceLines[jss::result].isMember(jss::error_message) &&
693 aliceLines[jss::result].isMember(jss::lines) &&
694 aliceLines[jss::result][jss::lines].isArray() &&
695 aliceLines[jss::result][jss::lines].size() <= 1;
704 while (hasMarker(aliceLines))
707 aliceLines = getNextLine(
env, alice,
marker(aliceLines));
709 foundLines += aliceLines[jss::result][jss::lines].size();
717 R
"({"account": ")" + alice.human() +
722 !aliceObjects[jss::result].isMember(jss::error_message));
724 aliceObjects[jss::result].isMember(jss::account_objects));
726 aliceObjects[jss::result][jss::account_objects].isArray());
731 aliceObjects[jss::result][jss::account_objects].
size() ==
742 R
"({"account": ")" + becky.human() +
747 !beckyObjects[jss::result].isMember(jss::error_message));
749 beckyObjects[jss::result].isMember(jss::account_objects));
751 beckyObjects[jss::result][jss::account_objects].isArray());
755 beckyObjects[jss::result][jss::account_objects].
size() ==
756 aliceObjects[jss::result][jss::account_objects].
size() - 2);
764 testcase(
"V2: account_lines");
766 using namespace test::jtx;
770 auto const lines =
env.rpc(
773 R
"("method" : "account_lines",)"
774 R"("jsonrpc" : "2.0",)"
775 R"("ripplerpc" : "2.0")"
778 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
780 lines.isMember(jss::ripplerpc) &&
781 lines[jss::ripplerpc] ==
"2.0");
785 auto const lines =
env.rpc(
788 R
"("method" : "account_lines",)"
789 R"("jsonrpc" : "2.0",)"
790 R"("ripplerpc" : "2.0",)"
794 lines[jss::error][jss::message] ==
797 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
799 lines.isMember(jss::ripplerpc) &&
800 lines[jss::ripplerpc] ==
"2.0");
801 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
805 auto const lines =
env.rpc(
808 R
"("method" : "account_lines",)"
809 R"("jsonrpc" : "2.0",)"
810 R"("ripplerpc" : "2.0",)"
814 R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"}})");
816 lines[jss::error][jss::message] ==
819 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
821 lines.isMember(jss::ripplerpc) &&
822 lines[jss::ripplerpc] ==
"2.0");
823 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
825 Account
const alice{
"alice"};
828 auto const lines =
env.rpc(
831 R
"("method" : "account_lines",)"
832 R"("jsonrpc" : "2.0",)"
833 R"("ripplerpc" : "2.0",)"
837 alice.human() + R"("}})");
839 lines[jss::error][jss::message] ==
842 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
844 lines.isMember(jss::ripplerpc) &&
845 lines[jss::ripplerpc] ==
"2.0");
846 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
848 env.fund(XRP(10000), alice);
855 auto const lines =
env.rpc(
858 R
"("method" : "account_lines",)"
859 R"("jsonrpc" : "2.0",)"
860 R"("ripplerpc" : "2.0",)"
864 alice.human() + R"("}})");
866 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 0);
868 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
870 lines.isMember(jss::ripplerpc) &&
871 lines[jss::ripplerpc] ==
"2.0");
872 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
876 auto const lines =
env.rpc(
879 R
"("method" : "account_lines",)"
880 R"("jsonrpc" : "2.0",)"
881 R"("ripplerpc" : "2.0",)"
887 R"("ledger_index": "nonsense"}})");
889 lines[jss::error][jss::message] == "ledgerIndexMalformed");
891 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
893 lines.isMember(jss::ripplerpc) &&
894 lines[jss::ripplerpc] ==
"2.0");
895 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
899 auto const lines =
env.rpc(
902 R
"("method" : "account_lines",)"
903 R"("jsonrpc" : "2.0",)"
904 R"("ripplerpc" : "2.0",)"
910 R"("ledger_index": 50000}})");
911 BEAST_EXPECT(lines[jss::error][jss::message] == "ledgerNotFound");
913 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
915 lines.isMember(jss::ripplerpc) &&
916 lines[jss::ripplerpc] ==
"2.0");
917 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
921 env.fund(XRP(10000),
gw1);
924 for (
char c = 0; c <= (
'Z' -
'A'); ++c)
932 env(trust(alice, gw1Currency(100 + c)));
933 env(pay(
gw1, alice, gw1Currency(50 + c)));
942 env.fund(XRP(10000),
gw2);
949 for (
char c = 0; c <= (
'Z' -
'A'); ++c)
957 env(trust(alice, gw2Currency(200 + c)));
960 env(pay(
gw2, alice, gw2Currency(100 + c)));
972 Account
const& account,
976 auto const linesSeq =
env.rpc(
979 R
"("method" : "account_lines",)"
980 R"("jsonrpc" : "2.0",)"
981 R"("ripplerpc" : "2.0",)"
987 R"("ledger_index": )" +
989 BEAST_EXPECT(linesSeq[jss::result][jss::lines].isArray());
990 BEAST_EXPECT(linesSeq[jss::result][jss::lines].size() == count);
992 linesSeq.isMember(jss::jsonrpc) &&
993 linesSeq[jss::jsonrpc] ==
"2.0");
995 linesSeq.isMember(jss::ripplerpc) &&
996 linesSeq[jss::ripplerpc] ==
"2.0");
997 BEAST_EXPECT(linesSeq.isMember(jss::id) && linesSeq[jss::id] == 5);
1000 auto const linesHash =
env.rpc(
1003 R
"("method" : "account_lines",)"
1004 R"("jsonrpc" : "2.0",)"
1005 R"("ripplerpc" : "2.0",)"
1008 R"({"account": ")" +
1011 R"("ledger_hash": ")" +
1013 BEAST_EXPECT(linesHash[jss::result][jss::lines].isArray());
1014 BEAST_EXPECT(linesHash[jss::result][jss::lines].size() == count);
1016 linesHash.isMember(jss::jsonrpc) &&
1017 linesHash[jss::jsonrpc] == "2.0");
1019 linesHash.isMember(jss::ripplerpc) &&
1020 linesHash[jss::ripplerpc] ==
"2.0");
1022 linesHash.isMember(jss::id) && linesHash[jss::id] == 5);
1037 auto const lines =
env.rpc(
1040 R
"("method" : "account_lines",)"
1041 R"("jsonrpc" : "2.0",)"
1042 R"("ripplerpc" : "2.0",)"
1045 R"({"account": ")" +
1048 R"("ledger_hash": ")" +
1051 R"("ledger_index": )" +
1053 BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
1054 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
1056 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
1058 lines.isMember(jss::ripplerpc) &&
1059 lines[jss::ripplerpc] ==
"2.0");
1060 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
1064 auto const lines =
env.rpc(
1067 R
"("method" : "account_lines",)"
1068 R"("jsonrpc" : "2.0",)"
1069 R"("ripplerpc" : "2.0",)"
1072 R"({"account": ")" +
1073 alice.human() + R"("}})");
1074 BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
1075 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 52);
1077 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
1079 lines.isMember(jss::ripplerpc) &&
1080 lines[jss::ripplerpc] ==
"2.0");
1081 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
1085 auto const lines =
env.rpc(
1088 R
"("method" : "account_lines",)"
1089 R"("jsonrpc" : "2.0",)"
1090 R"("ripplerpc" : "2.0",)"
1093 R"({"account": ")" +
1097 gw1.human() + R"("}})");
1098 BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
1099 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
1101 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
1103 lines.isMember(jss::ripplerpc) &&
1104 lines[jss::ripplerpc] ==
"2.0");
1105 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
1112 R
"("method" : "account_lines",)"
1113 R"("jsonrpc" : "2.0",)"
1114 R"("ripplerpc" : "2.0",)"
1117 R"({"account": ")" +
1121 R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"}})");
1123 lines[jss::error][jss::message] ==
1126 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
1128 lines.isMember(jss::ripplerpc) &&
1129 lines[jss::ripplerpc] ==
"2.0");
1137 R
"("method" : "account_lines",)"
1138 R"("jsonrpc" : "2.0",)"
1139 R"("ripplerpc" : "2.0",)"
1142 R"({"account": ")" +
1145 R"("limit": -1}})");
1147 lines[jss::error][jss::message] ==
1150 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
1152 lines.isMember(jss::ripplerpc) &&
1153 lines[jss::ripplerpc] ==
"2.0");
1158 auto const linesA =
env.rpc(
1161 R
"("method" : "account_lines",)"
1162 R"("jsonrpc" : "2.0",)"
1163 R"("ripplerpc" : "2.0",)"
1166 R"({"account": ")" +
1170 BEAST_EXPECT(linesA[jss::result][jss::lines].isArray());
1173 linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] == "2.0");
1175 linesA.isMember(jss::ripplerpc) &&
1176 linesA[jss::ripplerpc] ==
"2.0");
1177 BEAST_EXPECT(linesA.isMember(jss::id) && linesA[jss::id] == 5);
1180 auto marker = linesA[jss::result][jss::marker].asString();
1184 R
"("method" : "account_lines",)"
1185 R"("jsonrpc" : "2.0",)"
1186 R"("ripplerpc" : "2.0",)"
1189 R"({"account": ")" +
1197 linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0");
1199 linesB.isMember(jss::ripplerpc) &&
1200 linesB[jss::ripplerpc] ==
"2.0");
1207 R
"("method" : "account_lines",)"
1208 R"("jsonrpc" : "2.0",)"
1209 R"("ripplerpc" : "2.0",)"
1212 R"({"account": ")" +
1221 linesC.isMember(jss::jsonrpc) && linesC[jss::jsonrpc] == "2.0");
1223 linesC.isMember(jss::ripplerpc) &&
1224 linesC[jss::ripplerpc] ==
"2.0");
1232 R
"("method" : "account_lines",)"
1233 R"("jsonrpc" : "2.0",)"
1234 R"("ripplerpc" : "2.0",)"
1237 R"({"account": ")" +
1243 linesD[jss::error][jss::message] ==
1246 linesD.isMember(jss::jsonrpc) && linesD[jss::jsonrpc] == "2.0");
1248 linesD.isMember(jss::ripplerpc) &&
1249 linesD[jss::ripplerpc] ==
"2.0");
1254 auto const lines =
env.rpc(
1257 R
"("method" : "account_lines",)"
1258 R"("jsonrpc" : "2.0",)"
1259 R"("ripplerpc" : "2.0",)"
1262 R"({"account": ")" +
1265 R"("marker": true}})");
1267 lines[jss::error][jss::message] ==
1270 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
1272 lines.isMember(jss::ripplerpc) &&
1273 lines[jss::ripplerpc] ==
"2.0");
1274 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
1278 auto const lines =
env.rpc(
1281 R
"("method" : "account_lines",)"
1282 R"("jsonrpc" : "2.0",)"
1283 R"("ripplerpc" : "2.0",)"
1286 R"({"account": ")" +
1291 gw2.human() + R"("}})");
1292 auto const&
line = lines[jss::result][jss::lines][0u];
1297 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
1299 lines.isMember(jss::ripplerpc) &&
1300 lines[jss::ripplerpc] ==
"2.0");
1301 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
1305 auto const linesA =
env.rpc(
1308 R
"("method" : "account_lines",)"
1309 R"("jsonrpc" : "2.0",)"
1310 R"("ripplerpc" : "2.0",)"
1313 R"({"account": ")" +
1318 alice.human() + R"("}})");
1319 auto const&
lineA = linesA[jss::result][jss::lines][0u];
1324 linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] ==
"2.0");
1326 linesA.isMember(jss::ripplerpc) &&
1327 linesA[jss::ripplerpc] ==
"2.0");
1328 BEAST_EXPECT(linesA.isMember(jss::id) && linesA[jss::id] == 5);
1331 BEAST_EXPECT(linesA[jss::result].isMember(jss::marker));
1332 auto const marker = linesA[jss::result][jss::marker].asString();
1336 R
"("method" : "account_lines",)"
1337 R"("jsonrpc" : "2.0",)"
1338 R"("ripplerpc" : "2.0",)"
1341 R"({"account": ")" +
1349 alice.human() + R"("}})");
1354 linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0");
1356 linesB.isMember(jss::ripplerpc) &&
1357 linesB[jss::ripplerpc] ==
"2.0");
1366 testcase(
"V2: account_lines with removed marker");
1368 using namespace test::jtx;
1382 Account
const alice{
"alice"};
1383 Account
const becky{
"becky"};
1384 Account
const cheri{
"cheri"};
1385 Account
const gw1{
"gw1"};
1386 Account
const gw2{
"gw2"};
1387 env.fund(XRP(10000), alice, becky, cheri,
gw1,
gw2);
1390 auto const USD =
gw1[
"USD"];
1391 auto const AUD =
gw1[
"AUD"];
1392 auto const EUR =
gw2[
"EUR"];
1393 env(trust(alice, USD(200)));
1394 env(trust(alice, AUD(200)));
1395 env(trust(becky, EUR(200)));
1396 env(trust(cheri, EUR(200)));
1400 env(pay(
gw2, becky, EUR(100)));
1404 env(offer(alice, EUR(100), XRP(100)));
1408 env(offer(becky, XRP(100), EUR(100)));
1412 auto const linesBeg =
env.rpc(
1415 R
"("method" : "account_lines",)"
1416 R"("jsonrpc" : "2.0",)"
1417 R"("ripplerpc" : "2.0",)"
1420 R"({"account": ")" +
1425 linesBeg[jss::result][jss::lines][0u][jss::currency] == "USD");
1426 BEAST_EXPECT(linesBeg[jss::result].isMember(jss::marker));
1428 linesBeg.isMember(jss::jsonrpc) && linesBeg[jss::jsonrpc] ==
"2.0");
1430 linesBeg.isMember(jss::ripplerpc) &&
1431 linesBeg[jss::ripplerpc] ==
"2.0");
1432 BEAST_EXPECT(linesBeg.isMember(jss::id) && linesBeg[jss::id] == 5);
1435 env(pay(alice, cheri, EUR(100)));
1440 auto const linesEnd =
env.rpc(
1443 R
"("method" : "account_lines",)"
1444 R"("jsonrpc" : "2.0",)"
1445 R"("ripplerpc" : "2.0",)"
1448 R"({"account": ")" +
1452 linesBeg[jss::result][jss::marker].asString() + R"("}})");
1454 linesEnd[jss::error][jss::message] ==
1457 linesEnd.isMember(jss::jsonrpc) && linesEnd[jss::jsonrpc] == "2.0");
1459 linesEnd.isMember(jss::ripplerpc) &&
1460 linesEnd[jss::ripplerpc] ==
"2.0");
1461 BEAST_EXPECT(linesEnd.isMember(jss::id) && linesEnd[jss::id] == 5);
1468 testAccountLinesMarker();
1469 testAccountLineDelete();
1470 testAccountLinesWalkMarkers();