79 BEAST_EXPECT(env.
current()->header().seq == 4);
84 jvParams[jss::ledger_index] = 1;
85 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
86 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
true);
87 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"1");
92 jvParams[jss::ledger_index] =
"1";
93 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
94 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
true);
95 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"1");
100 auto const jrr = env.
rpc(
"ledger",
"current")[jss::result];
101 BEAST_EXPECT(jrr[jss::ledger][jss::closed] ==
false);
104 BEAST_EXPECT(jrr[jss::ledger_current_index] == env.
current()->header().seq);
108 auto const jrr = env.
rpc(
"json",
"ledger",
"{}")[jss::result];
109 BEAST_EXPECT(!jrr.isMember(jss::ledger));
110 BEAST_EXPECT(jrr[jss::closed][jss::ledger][jss::closed] ==
true);
112 jrr[jss::closed][jss::ledger][jss::ledger_index] ==
114 BEAST_EXPECT(jrr[jss::open][jss::ledger][jss::closed] ==
false);
116 jrr[jss::open][jss::ledger][jss::ledger_index] ==
128 auto const usd = gw[
"USD"];
133 env.
trust(usd(1000), bob);
139 jvParams[jss::ledger_index] =
"potato";
140 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
142 jrr,
"invalidParams",
"Invalid field 'ledger_index', not string or number.");
148 jvParams[jss::ledger_index] = -1;
149 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
151 jrr,
"invalidParams",
"Invalid field 'ledger_index', not string or number.");
157 jvParams[jss::ledger_index] = 10u;
158 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
164 auto const jrr = env.
rpc(
"ledger",
"arbitrary_text")[jss::result];
171 jvParams[jss::ledger_index] =
"validated";
172 jvParams[jss::queue] =
true;
173 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
179 auto const ret = env.
rpc(
"json",
"ledger",
"{ \"ledger_index\" : 2e15 }");
181 BEAST_EXPECT(ret[jss::error_message] ==
"Invalid parameters.");
186 auto const ret = env.
rpc(
"json",
"ledger",
"{ \"ledger_index\" : 1000000000000000 }");
194 jvParams[field] =
"blah";
195 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
198 testBooleanField(jss::full);
199 testBooleanField(jss::accounts);
200 testBooleanField(jss::transactions);
201 testBooleanField(jss::expand);
202 testBooleanField(jss::binary);
203 testBooleanField(jss::owner_funds);
204 testBooleanField(jss::queue);
283 testcase(
"Ledger owner_funds with MPT offer");
289 auto const usd = gw[
"USD"];
291 env.
fund(
XRP(10'000), gw, alice);
293 env.
trust(usd(1'000), alice);
294 env(
pay(gw, alice, usd(100)));
303 MPT const mptAsset = mpt;
311 env(
offer(alice,
XRP(10), usd(10)));
312 env(
offer(alice,
XRP(10), mptAsset(10)));
315 mpt.authorize({.account = gw, .holder = alice, .flags = tfMPTUnauthorize});
321 auto const getTransactions = [&](
bool includeOwnerFunds) {
324 params[jss::transactions] =
true;
325 params[jss::expand] =
true;
330 if (includeOwnerFunds)
331 params[jss::owner_funds] =
true;
333 auto const result = env.
rpc(
"json",
"ledger",
to_string(params))[jss::result];
334 BEAST_EXPECT(!result.isMember(jss::error));
335 BEAST_EXPECT(result[jss::ledger][jss::transactions].isArray());
336 return result[jss::ledger][jss::transactions];
340 for (
auto i = 0u; i < txs.
size(); ++i)
342 auto const& tx = txs[i].
isMember(jss::tx_json) ? txs[i][jss::tx_json] : txs[i];
343 if (tx[jss::TransactionType] == jss::OfferCreate &&
344 tx[jss::TakerGets].isMember(jss::mpt_issuance_id) == mpt)
353 auto const baseline = getTransactions(
false);
354 BEAST_EXPECT(baseline.size() == 5u);
355 BEAST_EXPECT(findOffer(baseline,
false) !=
nullptr);
356 BEAST_EXPECT(findOffer(baseline,
true) !=
nullptr);
359 auto const withOwnerFunds = getTransactions(
true);
362 BEAST_EXPECT(withOwnerFunds.size() == baseline.size());
365 auto const* iouOfferTx = findOffer(withOwnerFunds,
false);
366 if (BEAST_EXPECT(iouOfferTx !=
nullptr))
367 BEAST_EXPECT((*iouOfferTx)[jss::owner_funds] ==
"100");
371 auto const* mptOfferTx = findOffer(withOwnerFunds,
true);
372 if (BEAST_EXPECT(mptOfferTx !=
nullptr))
373 BEAST_EXPECT((*mptOfferTx)[jss::owner_funds] ==
"100");
389 cfg->fees.referenceFee = 10;
403 jvParams[jss::ledger] =
"closed";
404 auto jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
405 BEAST_EXPECT(jrr.isMember(jss::ledger));
406 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
407 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
409 jvParams[jss::ledger] =
"validated";
410 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
411 BEAST_EXPECT(jrr.isMember(jss::ledger));
412 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
413 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
415 jvParams[jss::ledger] =
"current";
416 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
417 BEAST_EXPECT(jrr.isMember(jss::ledger));
418 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
421 jvParams[jss::ledger] =
"invalid";
422 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
423 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
425 jrr[jss::error_message] ==
"Invalid field 'ledger', not string or number.");
428 jvParams[jss::ledger] = 4;
429 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
430 BEAST_EXPECT(jrr.isMember(jss::ledger));
431 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
432 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"4");
435 jvParams[jss::ledger] = 20;
436 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
437 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
438 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
443 "0F1A9E0C109ADEF6DA2BDE19217C12BBEC57174CBDBD212B0EBDC1CEDB8531"
447 jvParams[jss::ledger_hash] = hash3;
448 auto jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
449 BEAST_EXPECT(jrr.isMember(jss::ledger));
450 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
451 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"3");
454 jvParams[jss::ledger_hash] =
"DEADBEEF" + hash3;
455 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
456 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
457 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'ledger_hash', not hex string.");
460 jvParams[jss::ledger_hash] = 2;
461 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
462 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
463 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'ledger_hash', not hex string.");
466 jvParams[jss::ledger_hash] =
467 "2E81FC6EC0DD943197EGC7E3FBE9AE30"
468 "7F2775F2F7485BB37307984C3C0F2340";
469 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
470 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
471 BEAST_EXPECT(jrr[jss::error_message] ==
"Invalid field 'ledger_hash', not hex string.");
474 jvParams[jss::ledger_hash] =
475 "8C3EEDB3124D92E49E75D81A8826A2E6"
476 "5A75FD71FC3FD6F36FEB803C5F1D812D";
477 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
478 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
479 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
485 jvParams[jss::ledger_index] =
"closed";
486 auto jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
487 BEAST_EXPECT(jrr.isMember(jss::ledger));
488 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
489 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
490 BEAST_EXPECT(jrr.isMember(jss::ledger_index));
492 jvParams[jss::ledger_index] =
"validated";
493 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
494 BEAST_EXPECT(jrr.isMember(jss::ledger));
495 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
496 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"5");
498 jvParams[jss::ledger_index] =
"current";
499 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
500 BEAST_EXPECT(jrr.isMember(jss::ledger));
501 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
"6");
502 BEAST_EXPECT(jrr.isMember(jss::ledger_current_index));
505 jvParams[jss::ledger_index] =
"invalid";
506 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
507 BEAST_EXPECT(jrr[jss::error] ==
"invalidParams");
509 jrr[jss::error_message] ==
"Invalid field 'ledger_index', not string or number.");
512 for (
auto i : {1, 2, 3, 4, 5, 6})
514 jvParams[jss::ledger_index] = i;
515 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
516 BEAST_EXPECT(jrr.isMember(jss::ledger));
518 BEAST_EXPECT(jrr.isMember(jss::ledger_hash));
519 BEAST_EXPECT(jrr[jss::ledger][jss::ledger_index] ==
std::to_string(i));
523 jvParams[jss::ledger_index] = 7;
524 jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
525 BEAST_EXPECT(jrr[jss::error] ==
"lgrNotFound");
526 BEAST_EXPECT(jrr[jss::error_message] ==
"ledgerNotFound");
549 testcase(
"Ledger with Queued Transactions");
558 cfg->fees.referenceFee = 10;
559 Env env(*
this, std::move(cfg));
562 jv[jss::ledger_index] =
"current";
563 jv[jss::queue] =
true;
564 jv[jss::expand] =
true;
568 Account const charlie{
"charlie"};
577 auto jrr = env.
rpc(
"json",
"ledger",
to_string(jv))[jss::result];
578 BEAST_EXPECT(!jrr.isMember(jss::queue_data));
589 BEAST_EXPECT(env.
current()->header().seq == 5);
592 auto aliceSeq = env.
seq(alice);
598 auto aSeq = env.
seq(a);
600 for (
int i = 0; i < 10; ++i)
611 jrr = env.
rpc(
"json",
"ledger",
to_string(jv))[jss::result];
612 BEAST_EXPECT(jrr[jss::queue_data].size() == 33);
618 BEAST_EXPECT(env.
current()->header().seq == 8);
620 jrr = env.
rpc(
"json",
"ledger",
to_string(jv))[jss::result];
621 BEAST_EXPECT(jrr[jss::queue_data].size() == 11);
625 jrr = env.
rpc(
"json",
"ledger",
to_string(jv))[jss::result];
627 auto const& parentHash = env.
current()->header().parentHash;
628 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
631 auto const& txj = jrr[jss::queue_data][1u];
632 BEAST_EXPECT(txj[jss::account] == alice.
human());
633 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
634 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
635 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
636 BEAST_EXPECT(txj.isMember(jss::tx));
637 auto const& tx = txj[jss::tx];
638 BEAST_EXPECT(tx[jss::Account] == alice.
human());
639 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
640 return tx[jss::hash].asString();
643 auto const& txj = jrr[jss::queue_data][0u];
644 BEAST_EXPECT(txj[jss::account] == alice.
human());
645 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
646 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
647 BEAST_EXPECT(txj[
"retries_remaining"] == 10);
648 BEAST_EXPECT(txj.isMember(jss::tx));
649 auto const& tx = txj[jss::tx];
650 BEAST_EXPECT(tx[jss::Account] == alice.
human());
651 BEAST_EXPECT(tx[jss::TransactionType] == jss::OfferCreate);
652 auto const txid0 = tx[jss::hash].asString();
656 BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash));
664 jv[jss::expand] =
false;
666 jrr = env.
rpc(
"json",
"ledger",
to_string(jv))[jss::result];
667 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
669 auto const& parentHash = env.
current()->header().parentHash;
670 auto const txid1 = [&]() {
671 auto const& txj = jrr[jss::queue_data][1u];
672 BEAST_EXPECT(txj[jss::account] == alice.
human());
673 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
674 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
675 BEAST_EXPECT(txj.isMember(jss::tx));
676 return txj[jss::tx].asString();
678 auto const& txj = jrr[jss::queue_data][0u];
679 BEAST_EXPECT(txj[jss::account] == alice.
human());
680 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
681 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
682 BEAST_EXPECT(txj[
"retries_remaining"] == 9);
683 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
684 BEAST_EXPECT(txj.isMember(jss::tx));
685 BEAST_EXPECT(txj[jss::tx] == txid0);
689 BEAST_EXPECT((tx0 ^ parentHash) < (tx1 ^ parentHash));
694 jv[jss::expand] =
true;
695 jv[jss::binary] =
true;
697 jrr = env.
rpc(
"json",
"ledger",
to_string(jv))[jss::result];
698 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 2))
700 auto const& txj = jrr[jss::queue_data][1u];
701 BEAST_EXPECT(txj[jss::account] == alice.
human());
702 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
703 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
704 BEAST_EXPECT(txj[
"retries_remaining"] == 8);
705 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
706 BEAST_EXPECT(txj.isMember(jss::tx));
707 BEAST_EXPECT(txj[jss::tx].isMember(jss::tx_blob));
709 auto const& txj2 = jrr[jss::queue_data][0u];
710 BEAST_EXPECT(txj2[jss::account] == alice.
human());
711 BEAST_EXPECT(txj2[jss::fee_level] ==
"256");
712 BEAST_EXPECT(txj2[
"preflight_result"] ==
"tesSUCCESS");
713 BEAST_EXPECT(txj2[
"retries_remaining"] == 10);
714 BEAST_EXPECT(!txj2.isMember(
"last_result"));
715 BEAST_EXPECT(txj2.isMember(jss::tx));
716 BEAST_EXPECT(txj2[jss::tx].isMember(jss::tx_blob));
719 for (
int i = 0; i != 9; ++i)
724 jv[jss::expand] =
false;
725 jv[jss::binary] =
false;
727 jrr = env.
rpc(
"json",
"ledger",
to_string(jv))[jss::result];
729 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
731 auto const& txj = jrr[jss::queue_data][0u];
732 BEAST_EXPECT(txj[jss::account] == alice.
human());
733 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
734 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
735 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
736 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
737 BEAST_EXPECT(txj.isMember(jss::tx));
738 BEAST_EXPECT(txj[jss::tx] != txid0);
739 return txj[jss::tx].asString();
744 jv[jss::full] =
true;
746 jrr = env.
rpc(
"json",
"ledger",
to_string(jv))[jss::result];
747 if (BEAST_EXPECT(jrr[jss::queue_data].size() == 1))
749 auto const& txj = jrr[jss::queue_data][0u];
750 BEAST_EXPECT(txj[jss::account] == alice.
human());
751 BEAST_EXPECT(txj[jss::fee_level] ==
"256");
752 BEAST_EXPECT(txj[
"preflight_result"] ==
"tesSUCCESS");
753 BEAST_EXPECT(txj[
"retries_remaining"] == 1);
754 BEAST_EXPECT(txj[
"last_result"] ==
"terPRE_SEQ");
755 BEAST_EXPECT(txj.isMember(jss::tx));
756 auto const& tx = txj[jss::tx];
757 BEAST_EXPECT(tx[jss::Account] == alice.
human());
758 BEAST_EXPECT(tx[jss::TransactionType] == jss::AccountSet);
759 BEAST_EXPECT(tx[jss::hash] == txid2);
766 testcase(
"Ledger Request, Accounts Hashes");
774 int hashesLedgerEntryIndex = -1;
777 jvParams[jss::ledger_index] = 3u;
778 jvParams[jss::accounts] =
true;
779 jvParams[jss::expand] =
true;
780 jvParams[jss::type] =
"hashes";
781 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
782 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
783 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
785 for (
auto i = 0; i < jrr[jss::ledger][jss::accountState].size(); i++)
787 if (jrr[jss::ledger][jss::accountState][i][
"LedgerEntryType"] == jss::LedgerHashes)
789 index = jrr[jss::ledger][jss::accountState][i][
"index"].asString();
790 hashesLedgerEntryIndex = i;
794 for (
auto const&
object : jrr[jss::ledger][jss::accountState])
796 if (
object[
"LedgerEntryType"] == jss::LedgerHashes)
797 index =
object[
"index"].asString();
802 jrr.isMember(jss::warnings) && jrr[jss::warnings].isArray() &&
803 jrr[jss::warnings].size() == 1 &&
808 jvParams[jss::ledger_index] = 3u;
809 jvParams[jss::accounts] =
true;
810 jvParams[jss::expand] =
false;
811 jvParams[jss::type] =
"hashes";
812 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
813 BEAST_EXPECT(jrr[jss::ledger].isMember(jss::accountState));
814 BEAST_EXPECT(jrr[jss::ledger][jss::accountState].isArray());
816 hashesLedgerEntryIndex > 0 &&
817 jrr[jss::ledger][jss::accountState][hashesLedgerEntryIndex] == index);
821 jrr.isMember(jss::warnings) && jrr[jss::warnings].isArray() &&
822 jrr[jss::warnings].size() == 1 &&
830 testcase(
"Expanded Transactions CTID");
843 jvParams[jss::ledger_index] =
"validated";
844 jvParams[jss::transactions] =
true;
845 jvParams[jss::expand] =
true;
846 jvParams[jss::api_version] = 2;
847 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
848 BEAST_EXPECT(jrr[jss::status] ==
"success");
849 auto const& txns = jrr[jss::ledger][jss::transactions];
850 BEAST_EXPECT(txns.isArray() && txns.size() > 0);
851 for (
auto const& txn : txns)
853 BEAST_EXPECT(txn.isMember(jss::ctid));
855 jrr[jss::ledger][jss::ledger_index].asUInt(),
856 txn[jss::meta][sfTransactionIndex.jsonName].asUInt(),
859 if (BEAST_EXPECT(expectedCtid.has_value()))
860 BEAST_EXPECT(txn[jss::ctid] == expectedCtid.value());
868 jvParams[jss::ledger_index] =
"validated";
869 jvParams[jss::transactions] =
true;
870 jvParams[jss::expand] =
true;
871 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
872 BEAST_EXPECT(jrr[jss::status] ==
"success");
873 auto const& txns = jrr[jss::ledger][jss::transactions];
874 BEAST_EXPECT(txns.isArray() && txns.size() > 0);
875 for (
auto const& txn : txns)
877 BEAST_EXPECT(txn.isMember(jss::ctid));
884 jvParams[jss::ledger_index] =
"validated";
885 jvParams[jss::transactions] =
true;
886 jvParams[jss::expand] =
true;
887 jvParams[jss::binary] =
true;
888 jvParams[jss::api_version] = 2;
889 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
890 BEAST_EXPECT(jrr[jss::status] ==
"success");
891 auto const& txns = jrr[jss::ledger][jss::transactions];
892 BEAST_EXPECT(txns.isArray() && txns.size() > 0);
893 for (
auto const& txn : txns)
895 BEAST_EXPECT(txn.isMember(jss::ctid));
902 jvParams[jss::ledger_index] =
"validated";
903 jvParams[jss::transactions] =
true;
904 jvParams[jss::api_version] = 2;
905 auto const jrr = env.
rpc(
"json",
"ledger",
to_string(jvParams))[jss::result];
906 BEAST_EXPECT(jrr[jss::status] ==
"success");
907 auto const& txns = jrr[jss::ledger][jss::transactions];
908 BEAST_EXPECT(txns.isArray() && txns.size() > 0);
909 for (
auto const& txn : txns)
911 BEAST_EXPECT(txn.isString());