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);
685 auto hasMarker = [](
auto const& aliceLines) {
686 return aliceLines[jss::result].isMember(jss::marker);
688 auto marker = [](
auto const& aliceLines) {
689 return aliceLines[jss::result][jss::marker].asString();
691 auto checkLines = [](
auto const& aliceLines) {
692 return aliceLines.isMember(jss::result) &&
693 !aliceLines[jss::result].isMember(jss::error_message) &&
694 aliceLines[jss::result].isMember(jss::lines) &&
695 aliceLines[jss::result][jss::lines].isArray() &&
696 aliceLines[jss::result][jss::lines].size() <= 1;
705 while (hasMarker(aliceLines))
708 aliceLines = getNextLine(
env, alice,
marker(aliceLines));
710 foundLines += aliceLines[jss::result][jss::lines].size();
718 R
"({"account": ")" + alice.human() +
723 !aliceObjects[jss::result].isMember(jss::error_message));
725 aliceObjects[jss::result].isMember(jss::account_objects));
727 aliceObjects[jss::result][jss::account_objects].isArray());
732 aliceObjects[jss::result][jss::account_objects].
size() ==
733 iterations + expectedNFTs);
743 R
"({"account": ")" + becky.human() +
748 !beckyObjects[jss::result].isMember(jss::error_message));
750 beckyObjects[jss::result].isMember(jss::account_objects));
752 beckyObjects[jss::result][jss::account_objects].isArray());
756 beckyObjects[jss::result][jss::account_objects].
size() ==
757 aliceObjects[jss::result][jss::account_objects].
size() - 2);
765 testcase(
"V2: account_lines");
767 using namespace test::jtx;
771 auto const lines =
env.rpc(
774 R
"("method" : "account_lines",)"
775 R"("jsonrpc" : "2.0",)"
776 R"("ripplerpc" : "2.0")"
779 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
781 lines.isMember(jss::ripplerpc) &&
782 lines[jss::ripplerpc] ==
"2.0");
786 auto const lines =
env.rpc(
789 R
"("method" : "account_lines",)"
790 R"("jsonrpc" : "2.0",)"
791 R"("ripplerpc" : "2.0",)"
795 lines[jss::error][jss::message] ==
798 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
800 lines.isMember(jss::ripplerpc) &&
801 lines[jss::ripplerpc] ==
"2.0");
802 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
806 auto const lines =
env.rpc(
809 R
"("method" : "account_lines",)"
810 R"("jsonrpc" : "2.0",)"
811 R"("ripplerpc" : "2.0",)"
815 R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"}})");
817 lines[jss::error][jss::message] ==
820 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
822 lines.isMember(jss::ripplerpc) &&
823 lines[jss::ripplerpc] ==
"2.0");
824 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
826 Account
const alice{
"alice"};
829 auto const lines =
env.rpc(
832 R
"("method" : "account_lines",)"
833 R"("jsonrpc" : "2.0",)"
834 R"("ripplerpc" : "2.0",)"
838 alice.human() + R"("}})");
840 lines[jss::error][jss::message] ==
843 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
845 lines.isMember(jss::ripplerpc) &&
846 lines[jss::ripplerpc] ==
"2.0");
847 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
849 env.fund(XRP(10000), alice);
856 auto const lines =
env.rpc(
859 R
"("method" : "account_lines",)"
860 R"("jsonrpc" : "2.0",)"
861 R"("ripplerpc" : "2.0",)"
865 alice.human() + R"("}})");
867 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 0);
869 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
871 lines.isMember(jss::ripplerpc) &&
872 lines[jss::ripplerpc] ==
"2.0");
873 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
877 auto const lines =
env.rpc(
880 R
"("method" : "account_lines",)"
881 R"("jsonrpc" : "2.0",)"
882 R"("ripplerpc" : "2.0",)"
888 R"("ledger_index": "nonsense"}})");
890 lines[jss::error][jss::message] == "ledgerIndexMalformed");
892 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
894 lines.isMember(jss::ripplerpc) &&
895 lines[jss::ripplerpc] ==
"2.0");
896 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
900 auto const lines =
env.rpc(
903 R
"("method" : "account_lines",)"
904 R"("jsonrpc" : "2.0",)"
905 R"("ripplerpc" : "2.0",)"
911 R"("ledger_index": 50000}})");
912 BEAST_EXPECT(lines[jss::error][jss::message] == "ledgerNotFound");
914 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
916 lines.isMember(jss::ripplerpc) &&
917 lines[jss::ripplerpc] ==
"2.0");
918 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
922 env.fund(XRP(10000),
gw1);
925 for (
char c = 0; c <= (
'Z' -
'A'); ++c)
933 env(trust(alice, gw1Currency(100 + c)));
934 env(pay(
gw1, alice, gw1Currency(50 + c)));
943 env.fund(XRP(10000),
gw2);
950 for (
char c = 0; c <= (
'Z' -
'A'); ++c)
958 env(trust(alice, gw2Currency(200 + c)));
961 env(pay(
gw2, alice, gw2Currency(100 + c)));
973 Account
const& account,
977 auto const linesSeq =
env.rpc(
980 R
"("method" : "account_lines",)"
981 R"("jsonrpc" : "2.0",)"
982 R"("ripplerpc" : "2.0",)"
988 R"("ledger_index": )" +
990 BEAST_EXPECT(linesSeq[jss::result][jss::lines].isArray());
991 BEAST_EXPECT(linesSeq[jss::result][jss::lines].size() == count);
993 linesSeq.isMember(jss::jsonrpc) &&
994 linesSeq[jss::jsonrpc] ==
"2.0");
996 linesSeq.isMember(jss::ripplerpc) &&
997 linesSeq[jss::ripplerpc] ==
"2.0");
998 BEAST_EXPECT(linesSeq.isMember(jss::id) && linesSeq[jss::id] == 5);
1001 auto const linesHash =
env.rpc(
1004 R
"("method" : "account_lines",)"
1005 R"("jsonrpc" : "2.0",)"
1006 R"("ripplerpc" : "2.0",)"
1009 R"({"account": ")" +
1012 R"("ledger_hash": ")" +
1014 BEAST_EXPECT(linesHash[jss::result][jss::lines].isArray());
1015 BEAST_EXPECT(linesHash[jss::result][jss::lines].size() == count);
1017 linesHash.isMember(jss::jsonrpc) &&
1018 linesHash[jss::jsonrpc] == "2.0");
1020 linesHash.isMember(jss::ripplerpc) &&
1021 linesHash[jss::ripplerpc] ==
"2.0");
1023 linesHash.isMember(jss::id) && linesHash[jss::id] == 5);
1038 auto const lines =
env.rpc(
1041 R
"("method" : "account_lines",)"
1042 R"("jsonrpc" : "2.0",)"
1043 R"("ripplerpc" : "2.0",)"
1046 R"({"account": ")" +
1049 R"("ledger_hash": ")" +
1052 R"("ledger_index": )" +
1054 BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
1055 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
1057 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
1059 lines.isMember(jss::ripplerpc) &&
1060 lines[jss::ripplerpc] ==
"2.0");
1061 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
1065 auto const lines =
env.rpc(
1068 R
"("method" : "account_lines",)"
1069 R"("jsonrpc" : "2.0",)"
1070 R"("ripplerpc" : "2.0",)"
1073 R"({"account": ")" +
1074 alice.human() + R"("}})");
1075 BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
1076 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 52);
1078 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
1080 lines.isMember(jss::ripplerpc) &&
1081 lines[jss::ripplerpc] ==
"2.0");
1082 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
1086 auto const lines =
env.rpc(
1089 R
"("method" : "account_lines",)"
1090 R"("jsonrpc" : "2.0",)"
1091 R"("ripplerpc" : "2.0",)"
1094 R"({"account": ")" +
1098 gw1.human() + R"("}})");
1099 BEAST_EXPECT(lines[jss::result][jss::lines].isArray());
1100 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
1102 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
1104 lines.isMember(jss::ripplerpc) &&
1105 lines[jss::ripplerpc] ==
"2.0");
1106 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
1113 R
"("method" : "account_lines",)"
1114 R"("jsonrpc" : "2.0",)"
1115 R"("ripplerpc" : "2.0",)"
1118 R"({"account": ")" +
1122 R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"}})");
1124 lines[jss::error][jss::message] ==
1127 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] == "2.0");
1129 lines.isMember(jss::ripplerpc) &&
1130 lines[jss::ripplerpc] ==
"2.0");
1138 R
"("method" : "account_lines",)"
1139 R"("jsonrpc" : "2.0",)"
1140 R"("ripplerpc" : "2.0",)"
1143 R"({"account": ")" +
1146 R"("limit": -1}})");
1148 lines[jss::error][jss::message] ==
1151 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
1153 lines.isMember(jss::ripplerpc) &&
1154 lines[jss::ripplerpc] ==
"2.0");
1159 auto const linesA =
env.rpc(
1162 R
"("method" : "account_lines",)"
1163 R"("jsonrpc" : "2.0",)"
1164 R"("ripplerpc" : "2.0",)"
1167 R"({"account": ")" +
1171 BEAST_EXPECT(linesA[jss::result][jss::lines].isArray());
1174 linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] == "2.0");
1176 linesA.isMember(jss::ripplerpc) &&
1177 linesA[jss::ripplerpc] ==
"2.0");
1178 BEAST_EXPECT(linesA.isMember(jss::id) && linesA[jss::id] == 5);
1181 auto marker = linesA[jss::result][jss::marker].asString();
1185 R
"("method" : "account_lines",)"
1186 R"("jsonrpc" : "2.0",)"
1187 R"("ripplerpc" : "2.0",)"
1190 R"({"account": ")" +
1198 linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0");
1200 linesB.isMember(jss::ripplerpc) &&
1201 linesB[jss::ripplerpc] ==
"2.0");
1208 R
"("method" : "account_lines",)"
1209 R"("jsonrpc" : "2.0",)"
1210 R"("ripplerpc" : "2.0",)"
1213 R"({"account": ")" +
1222 linesC.isMember(jss::jsonrpc) && linesC[jss::jsonrpc] == "2.0");
1224 linesC.isMember(jss::ripplerpc) &&
1225 linesC[jss::ripplerpc] ==
"2.0");
1233 R
"("method" : "account_lines",)"
1234 R"("jsonrpc" : "2.0",)"
1235 R"("ripplerpc" : "2.0",)"
1238 R"({"account": ")" +
1244 linesD[jss::error][jss::message] ==
1247 linesD.isMember(jss::jsonrpc) && linesD[jss::jsonrpc] == "2.0");
1249 linesD.isMember(jss::ripplerpc) &&
1250 linesD[jss::ripplerpc] ==
"2.0");
1255 auto const lines =
env.rpc(
1258 R
"("method" : "account_lines",)"
1259 R"("jsonrpc" : "2.0",)"
1260 R"("ripplerpc" : "2.0",)"
1263 R"({"account": ")" +
1266 R"("marker": true}})");
1268 lines[jss::error][jss::message] ==
1271 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
1273 lines.isMember(jss::ripplerpc) &&
1274 lines[jss::ripplerpc] ==
"2.0");
1275 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
1279 auto const lines =
env.rpc(
1282 R
"("method" : "account_lines",)"
1283 R"("jsonrpc" : "2.0",)"
1284 R"("ripplerpc" : "2.0",)"
1287 R"({"account": ")" +
1292 gw2.human() + R"("}})");
1293 auto const&
line = lines[jss::result][jss::lines][0u];
1298 lines.isMember(jss::jsonrpc) && lines[jss::jsonrpc] ==
"2.0");
1300 lines.isMember(jss::ripplerpc) &&
1301 lines[jss::ripplerpc] ==
"2.0");
1302 BEAST_EXPECT(lines.isMember(jss::id) && lines[jss::id] == 5);
1306 auto const linesA =
env.rpc(
1309 R
"("method" : "account_lines",)"
1310 R"("jsonrpc" : "2.0",)"
1311 R"("ripplerpc" : "2.0",)"
1314 R"({"account": ")" +
1319 alice.human() + R"("}})");
1320 auto const&
lineA = linesA[jss::result][jss::lines][0u];
1325 linesA.isMember(jss::jsonrpc) && linesA[jss::jsonrpc] ==
"2.0");
1327 linesA.isMember(jss::ripplerpc) &&
1328 linesA[jss::ripplerpc] ==
"2.0");
1329 BEAST_EXPECT(linesA.isMember(jss::id) && linesA[jss::id] == 5);
1332 BEAST_EXPECT(linesA[jss::result].isMember(jss::marker));
1333 auto const marker = linesA[jss::result][jss::marker].asString();
1337 R
"("method" : "account_lines",)"
1338 R"("jsonrpc" : "2.0",)"
1339 R"("ripplerpc" : "2.0",)"
1342 R"({"account": ")" +
1350 alice.human() + R"("}})");
1355 linesB.isMember(jss::jsonrpc) && linesB[jss::jsonrpc] == "2.0");
1357 linesB.isMember(jss::ripplerpc) &&
1358 linesB[jss::ripplerpc] ==
"2.0");
1367 testcase(
"V2: account_lines with removed marker");
1369 using namespace test::jtx;
1383 Account
const alice{
"alice"};
1384 Account
const becky{
"becky"};
1385 Account
const cheri{
"cheri"};
1386 Account
const gw1{
"gw1"};
1387 Account
const gw2{
"gw2"};
1388 env.fund(XRP(10000), alice, becky, cheri,
gw1,
gw2);
1391 auto const USD =
gw1[
"USD"];
1392 auto const AUD =
gw1[
"AUD"];
1393 auto const EUR =
gw2[
"EUR"];
1394 env(trust(alice, USD(200)));
1395 env(trust(alice, AUD(200)));
1396 env(trust(becky, EUR(200)));
1397 env(trust(cheri, EUR(200)));
1401 env(pay(
gw2, becky, EUR(100)));
1405 env(offer(alice, EUR(100), XRP(100)));
1409 env(offer(becky, XRP(100), EUR(100)));
1413 auto const linesBeg =
env.rpc(
1416 R
"("method" : "account_lines",)"
1417 R"("jsonrpc" : "2.0",)"
1418 R"("ripplerpc" : "2.0",)"
1421 R"({"account": ")" +
1426 linesBeg[jss::result][jss::lines][0u][jss::currency] == "USD");
1427 BEAST_EXPECT(linesBeg[jss::result].isMember(jss::marker));
1429 linesBeg.isMember(jss::jsonrpc) && linesBeg[jss::jsonrpc] ==
"2.0");
1431 linesBeg.isMember(jss::ripplerpc) &&
1432 linesBeg[jss::ripplerpc] ==
"2.0");
1433 BEAST_EXPECT(linesBeg.isMember(jss::id) && linesBeg[jss::id] == 5);
1436 env(pay(alice, cheri, EUR(100)));
1441 auto const linesEnd =
env.rpc(
1444 R
"("method" : "account_lines",)"
1445 R"("jsonrpc" : "2.0",)"
1446 R"("ripplerpc" : "2.0",)"
1449 R"({"account": ")" +
1453 linesBeg[jss::result][jss::marker].asString() + R"("}})");
1455 linesEnd[jss::error][jss::message] ==
1458 linesEnd.isMember(jss::jsonrpc) && linesEnd[jss::jsonrpc] == "2.0");
1460 linesEnd.isMember(jss::ripplerpc) &&
1461 linesEnd[jss::ripplerpc] ==
"2.0");
1462 BEAST_EXPECT(linesEnd.isMember(jss::id) && linesEnd[jss::id] == 5);
1469 testAccountLinesMarker();
1470 testAccountLineDelete();
1471 testAccountLinesWalkMarkers();