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] ==
60 auto testInvalidAccountParam = [&](
auto const& param) {
62 params[jss::account] = param;
64 "json",
"account_lines",
to_string(params))[jss::result];
67 jrr[jss::error_message] ==
"Invalid field 'account'.");
70 testInvalidAccountParam(1);
71 testInvalidAccountParam(1.1);
72 testInvalidAccountParam(
true);
77 Account
const alice{
"alice"};
80 auto const lines =
env.rpc(
83 R
"({"account": ")" + alice.human() + R"("})");
85 lines[jss::result][jss::error_message] ==
88 env.fund(XRP(10000), alice);
95 auto const lines =
env.rpc(
98 R
"({"account": ")" + alice.human() + R"("})");
100 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 0);
104 auto const lines =
env.rpc(
107 R
"({"account": ")" + alice.human() +
109 R"("ledger_index": "nonsense"})");
111 lines[jss::result][jss::error_message] ==
112 "ledgerIndexMalformed");
116 auto const lines =
env.rpc(
119 R
"({"account": ")" + alice.human() +
121 R"("ledger_index": 50000})");
123 lines[jss::result][jss::error_message] == "ledgerNotFound");
126 Account
const gw1{
"gw1"};
127 env.fund(XRP(10000),
gw1);
130 for (
char c = 0; c <= (
'Z' -
'A'); ++c)
138 env(trust(alice, gw1Currency(100 + c)));
139 env(pay(
gw1, alice, gw1Currency(50 + c)));
147 Account
const gw2{
"gw2"};
148 env.fund(XRP(10000),
gw2);
155 for (
char c = 0; c <= (
'Z' -
'A'); ++c)
163 env(trust(alice, gw2Currency(200 + c)));
166 env(pay(
gw2, alice, gw2Currency(100 + c)));
182 Account
const& account,
186 auto const linesSeq =
env.rpc(
189 R
"({"account": ")" + account.human() +
191 R"("ledger_index": )" +
193 BEAST_EXPECT(linesSeq[jss::result][jss::lines].isArray());
194 BEAST_EXPECT(linesSeq[jss::result][jss::lines].size() == count);
197 auto const linesHash =
env.rpc(
200 R
"({"account": ")" + account.human() +
202 R"("ledger_hash": ")" +
204 BEAST_EXPECT(linesHash[jss::result][jss::lines].isArray());
205 BEAST_EXPECT(linesHash[jss::result][jss::lines].size() == count);
220 auto const lines =
env.rpc(
223 R
"({"account": ")" + alice.human() +
225 R"("ledger_hash": ")" +
228 R"("ledger_index": )" +
231 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
235 auto const lines =
env.rpc(
238 R
"({"account": ")" + alice.human() + R"("})");
240 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 52);
244 auto const lines =
env.rpc(
247 R
"({"account": ")" + alice.human() +
250 gw1.human() + R"("})");
252 BEAST_EXPECT(lines[jss::result][jss::lines].size() == 26);
255 auto const&
line = lines[jss::result][jss::lines][0u];
260 auto const lines =
env.rpc(
263 R
"({"account": ")" + alice.human() +
266 R"("n9MJkEKHDhy5eTLuHUQeAAjo382frHNbFK4C8hcwN4nwM2SrLdBj"})");
268 lines[jss::result][jss::error_message] ==
273 auto const lines =
env.rpc(
276 R
"({"account": ")" + alice.human() +
280 lines[jss::result][jss::error_message] ==
285 auto const linesA =
env.rpc(
288 R
"({"account": ")" + alice.human() +
291 BEAST_EXPECT(linesA[jss::result][jss::lines].isArray());
292 BEAST_EXPECT(linesA[jss::result][jss::lines].size() == 1);
295 auto marker = linesA[jss::result][jss::marker].asString();
299 R
"({"account": ")" + alice.human() +
310 R
"({"account": ")" + alice.human() +
323 R
"({"account": ")" + alice.human() +
328 linesD[jss::result][jss::error_message] ==
333 auto const lines =
env.rpc(
336 R
"({"account": ")" + alice.human() +
338 R"("marker": true})");
340 lines[jss::result][jss::error_message] ==
345 auto const lines =
env.rpc(
348 R
"({"account": ")" + alice.human() +
352 gw2.human() + R"("})");
353 auto const&
line = lines[jss::result][jss::lines][0u];
361 auto const linesA =
env.rpc(
364 R
"({"account": ")" + gw2.human() +
368 alice.human() + R"("})");
369 auto const&
lineA = linesA[jss::result][jss::lines][0u];
376 BEAST_EXPECT(linesA[jss::result].isMember(jss::marker));
377 auto const marker = linesA[jss::result][jss::marker].asString();
381 R
"({"account": ")" + gw2.human() +
388 alice.human() + R"("})");
396 testAccountLinesMarker()
398 testcase(
"Entry pointed to by marker is not owned by account");
399 using namespace test::jtx;
408 Account
const alice{
"alice"};
409 Account
const becky{
"becky"};
410 Account
const gw1{
"gw1"};
415 Account
const bogie{
"bogie"};
419 auto const EUR =
gw1[
"EUR"];
431 R
"({"account": ")" + alice.human() +
435 aliceObjects[jss::result][jss::account_objects][0u];
436 if (!(aliceSignerList[sfLedgerEntryType.jsonName] == jss::SignerList))
439 "alice's account objects are misordered. "
440 "Please reorder the objects so the SignerList is first.",
448 auto const aliceLines1 =
env.rpc(
451 R
"({"account": ")" + alice.human() + R"(", "limit": 1})");
452 BEAST_EXPECT(aliceLines1[jss::result].isMember(jss::marker));
456 aliceLines1[jss::result][jss::marker].asString();
459 BEAST_EXPECT(markerIndex == aliceSignerList[jss::index].asString());
462 auto const aliceLines2 =
env.rpc(
465 R
"({"account": ")" + alice.human() + R"(", "marker": ")" +
466 aliceMarker + R"("})");
468 BEAST_EXPECT(!aliceLines2[jss::result].isMember(jss::marker));
472 auto const beckyLines =
env.rpc(
475 R
"({"account": ")" + becky.human() + R"(", "marker": ")" +
476 aliceMarker + R"("})");
477 BEAST_EXPECT(beckyLines[jss::result].isMember(jss::error_message));
481 testAccountLineDelete()
483 testcase(
"Entry pointed to by marker is removed");
484 using namespace test::jtx;
498 Account
const alice{
"alice"};
499 Account
const becky{
"becky"};
500 Account
const cheri{
"cheri"};
501 Account
const gw1{
"gw1"};
502 Account
const gw2{
"gw2"};
506 auto const USD =
gw1[
"USD"];
507 auto const AUD =
gw1[
"AUD"];
508 auto const EUR =
gw2[
"EUR"];
528 auto const linesBeg =
env.rpc(
531 R
"({"account": ")" + alice.human() +
535 linesBeg[jss::result][jss::lines][0u][jss::currency] == "USD");
536 BEAST_EXPECT(linesBeg[jss::result].isMember(jss::marker));
539 env(
pay(alice, cheri, EUR(100)));
544 auto const linesEnd =
env.rpc(
547 R
"({"account": ")" + alice.human() +
550 linesBeg[jss::result][jss::marker].asString() + R"("})");
552 linesEnd[jss::result][jss::error_message] ==
557 testAccountLinesWalkMarkers()
559 testcase(
"Marker can point to any appropriate ledger entry type");
560 using namespace test::jtx;
561 using namespace std::chrono_literals;
570 Account
const alice{
"alice"};
571 Account
const becky{
"becky"};
572 Account
const gw1{
"gw1"};
576 auto payChan = [](Account
const& account,
578 STAmount
const& amount,
580 PublicKey
const& pk) {
582 jv[jss::TransactionType] = jss::PaymentChannelCreate;
583 jv[jss::Account] = account.human();
584 jv[jss::Destination] = to.human();
586 jv[
"SettleDelay"] = settleDelay.count();
587 jv[
"PublicKey"] =
strHex(pk.slice());
596 Account
const bogie{
"bogie"};
605 auto const EUR =
gw1[
"EUR"];
611 env(escrow::create(alice, becky,
XRP(1000)),
612 escrow::finish_time(
env.now() + 1s));
613 env(escrow::create(becky, alice,
XRP(1000)),
614 escrow::finish_time(
env.now() + 1s));
630 env(token::createOffer(alice, beckyNFtokenID,
drops(1)),
631 token::owner(becky));
632 env(token::createOffer(becky, aliceNFtokenID,
drops(1)),
633 token::owner(alice));
635 env(token::createOffer(becky, beckyNFtokenID,
drops(1)),
637 token::destination(alice));
638 env(token::createOffer(alice, aliceNFtokenID,
drops(1)),
640 token::destination(becky));
642 env(token::createOffer(
gw1, beckyNFtokenID,
drops(1)),
644 token::destination(alice));
645 env(token::createOffer(
gw1, aliceNFtokenID,
drops(1)),
647 token::destination(becky));
649 env(token::createOffer(becky, beckyNFtokenID,
drops(1)),
651 env(token::createOffer(alice, aliceNFtokenID,
drops(1)),
655 env(check::create(alice, becky,
XRP(50)));
656 env(check::create(becky, alice,
XRP(50)));
659 env(deposit::auth(alice, becky));
660 env(deposit::auth(becky, alice));
664 auto const USDalice = alice[
"USD"];
669 env(ticket::create(alice, 2));
672 auto const BTCbecky = becky[
"BTC"];
681 auto getNextLine = [](Env&
env,
682 Account
const& alice,
685 params[jss::account] = alice.human();
686 params[jss::limit] = 1;
688 params[jss::marker] = *
marker;
690 return env.rpc(
"json",
"account_lines",
to_string(params));
699 auto hasMarker = [](
auto const& aliceLines) {
700 return aliceLines[jss::result].isMember(jss::marker);
702 auto marker = [](
auto const& aliceLines) {
703 return aliceLines[jss::result][jss::marker].asString();
705 auto checkLines = [](
auto const& aliceLines) {
706 return aliceLines.isMember(jss::result) &&
707 !aliceLines[jss::result].isMember(jss::error_message) &&
708 aliceLines[jss::result].isMember(jss::lines) &&
709 aliceLines[jss::result][jss::lines].isArray() &&
710 aliceLines[jss::result][jss::lines].size() <= 1;
719 while (hasMarker(aliceLines))
722 aliceLines = getNextLine(
env, alice,
marker(aliceLines));
724 foundLines += aliceLines[jss::result][jss::lines].size();
732 R
"({"account": ")" + alice.human() +
737 !aliceObjects[jss::result].isMember(jss::error_message));
739 aliceObjects[jss::result].isMember(jss::account_objects));
741 aliceObjects[jss::result][jss::account_objects].isArray());
746 aliceObjects[jss::result][jss::account_objects].
size() ==
747 iterations + expectedNFTs);
757 R
"({"account": ")" + becky.human() +
762 !beckyObjects[jss::result].isMember(jss::error_message));
764 beckyObjects[jss::result].isMember(jss::account_objects));
766 beckyObjects[jss::result][jss::account_objects].isArray());
770 beckyObjects[jss::result][jss::account_objects].
size() ==
771 aliceObjects[jss::result][jss::account_objects].
size() - 2);
1387 testcase(
"V2: account_lines with removed marker");
1389 using namespace test::jtx;
1403 Account
const alice{
"alice"};
1404 Account
const becky{
"becky"};
1405 Account
const cheri{
"cheri"};
1406 Account
const gw1{
"gw1"};
1407 Account
const gw2{
"gw2"};
1408 env.fund(XRP(10000), alice, becky, cheri,
gw1,
gw2);
1411 auto const USD =
gw1[
"USD"];
1412 auto const AUD =
gw1[
"AUD"];
1413 auto const EUR =
gw2[
"EUR"];
1414 env(trust(alice, USD(200)));
1415 env(trust(alice, AUD(200)));
1416 env(trust(becky, EUR(200)));
1417 env(trust(cheri, EUR(200)));
1421 env(pay(
gw2, becky, EUR(100)));
1425 env(offer(alice, EUR(100), XRP(100)));
1429 env(offer(becky, XRP(100), EUR(100)));
1433 auto const linesBeg =
env.rpc(
1436 R
"("method" : "account_lines",)"
1437 R"("jsonrpc" : "2.0",)"
1438 R"("ripplerpc" : "2.0",)"
1441 R"({"account": ")" +
1446 linesBeg[jss::result][jss::lines][0u][jss::currency] == "USD");
1447 BEAST_EXPECT(linesBeg[jss::result].isMember(jss::marker));
1449 linesBeg.isMember(jss::jsonrpc) && linesBeg[jss::jsonrpc] ==
"2.0");
1451 linesBeg.isMember(jss::ripplerpc) &&
1452 linesBeg[jss::ripplerpc] ==
"2.0");
1453 BEAST_EXPECT(linesBeg.isMember(jss::id) && linesBeg[jss::id] == 5);
1456 env(pay(alice, cheri, EUR(100)));
1461 auto const linesEnd =
env.rpc(
1464 R
"("method" : "account_lines",)"
1465 R"("jsonrpc" : "2.0",)"
1466 R"("ripplerpc" : "2.0",)"
1469 R"({"account": ")" +
1473 linesBeg[jss::result][jss::marker].asString() + R"("}})");