2#include <test/jtx/Oracle.h>
3#include <test/jtx/attester.h>
4#include <test/jtx/delegate.h>
5#include <test/jtx/multisign.h>
6#include <test/jtx/xchain_bridge.h>
8#include <xrpl/beast/unit_test.h>
9#include <xrpl/json/json_value.h>
10#include <xrpl/protocol/AccountID.h>
11#include <xrpl/protocol/ErrorCodes.h>
12#include <xrpl/protocol/STXChainBridge.h>
13#include <xrpl/protocol/jss.h>
15#include <source_location>
58 mappings, [&fieldName](
auto const& pair) {
return pair.first == fieldName; });
64 Throw<std::runtime_error>(
"`mappings` is missing field " +
std::string(fieldName.
c_str()));
84 return "hex string or object";
88 return "length-2 array of Accounts";
94 Throw<std::runtime_error>(
108 if (BEAST_EXPECT(jv.
isMember(jss::status)))
109 BEAST_EXPECTS(jv[jss::status] ==
"error",
std::to_string(location.line()));
110 if (BEAST_EXPECT(jv.
isMember(jss::error)))
113 jv[jss::error] == err,
114 "Expected error " + err +
", received " + jv[jss::error].asString() +
", at line " +
120 jv[jss::error_message] ==
Json::nullValue || jv[jss::error_message] ==
"",
121 "Expected no error message, received \"" + jv[jss::error_message].asString() +
124 else if (BEAST_EXPECT(jv.
isMember(jss::error_message)))
127 jv[jss::error_message] == msg,
128 "Expected error message \"" + msg +
"\", received \"" +
129 jv[jss::error_message].asString() +
"\", at line " +
139 obj[jss::account] =
"rhigTLJJyXXSRUyRCQtqi1NoAZZzZnS4KU";
140 obj[jss::ledger_index] =
"validated";
145 arr[0u] =
"rhigTLJJyXXSRUyRCQtqi1NoAZZzZnS4KU";
146 arr[1u] =
"validated";
160 "0123456789ABCDEFGH",
161 "rJxKV9e9p6wiPw!!!!xrJ4X1n98LosPL1sgcJW",
162 "rPSTrR5yEr11uMkfsz1kHCp9jK4aoa3Avv",
163 "n9K2isxwTxcSHJKxMkJznDoWXAUs7NNy49H9Fknz1pC7oHAH3kH9",
166 "5233D68B4D44388F98559DE42903767803EFA7C1F8D01413FC16EE6B01403D"
188 static auto const& badAccountValues = remove({12});
189 static auto const& badArrayValues = remove({17, 20});
190 static auto const& badBlobValues = remove({3, 7, 8, 16});
191 static auto const& badCurrencyValues = remove({14});
192 static auto const& badHashValues = remove({2, 3, 7, 8, 16});
193 static auto const& badFixedHashValues = remove({1, 2, 3, 4, 7, 8, 16});
194 static auto const& badIndexValues = remove({12, 16, 18, 19});
195 static auto const& badUInt32Values = remove({2, 3});
196 static auto const& badUInt64Values = remove({2, 3});
197 static auto const& badIssueValues = remove({});
202 return badAccountValues;
205 return badArrayValues;
207 return badBlobValues;
209 return badCurrencyValues;
211 return badHashValues;
213 return badIndexValues;
215 return badFixedHashValues;
217 return badIssueValues;
219 return badUInt32Values;
221 return badUInt64Values;
223 Throw<std::runtime_error>(
224 "unknown type " +
std::to_string(
static_cast<uint8_t
>(fieldType)));
233 arr[0u] =
"rhigTLJJyXXSRUyRCQtqi1NoAZZzZnS4KU";
234 arr[1u] =
"r4MrUGTdB57duTnRs6KbsRGQXgkseGb1b5";
239 arr[jss::currency] =
"XRP";
247 return "r4MrUGTdB57duTnRs6KbsRGQXgkseGb1b5";
255 return "5233D68B4D44388F98559DE42903767803EFA7C1F8D01413FC16EE6"
260 return "5233D68B4D44388F98559DE42903767803EFA7C1F8D01413FC16EE6"
263 return twoAccountArray;
269 Throw<std::runtime_error>(
289 apiVersion,
"json",
"ledger_entry",
to_string(correctRequest))[jss::result];
297 jrr,
"invalidParams",
"No ledger_entry params provided.", location);
300 auto tryField = [&](
Json::Value fieldValue) ->
void {
301 correctRequest[fieldName] = fieldValue;
303 apiVersion,
"json",
"ledger_entry",
to_string(correctRequest))[jss::result];
304 auto const expectedErrMsg =
310 for (
auto const& value : badValues)
335 correctRequest[parentFieldName].
removeMember(fieldName);
337 apiVersion,
"json",
"ledger_entry",
to_string(correctRequest))[jss::result];
346 apiVersion,
"json",
"ledger_entry",
to_string(correctRequest))[jss::result];
353 auto tryField = [&](
Json::Value fieldValue) ->
void {
354 correctRequest[parentFieldName][fieldName] = fieldValue;
357 apiVersion,
"json",
"ledger_entry",
to_string(correctRequest))[jss::result];
366 for (
auto const& value : badValues)
415 for (
auto const& subfield : subfields)
417 correctOutput[parentField][subfield.fieldName] =
getCorrectValue(subfield.fieldName);
420 for (
auto const& subfield : subfields)
422 auto const fieldType =
getFieldType(subfield.fieldName);
429 subfield.malformedErrorMsg,
439 using namespace test::jtx;
447 jvParams[jss::account_root] = alice.human();
448 jvParams[jss::ledger_hash] =
449 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
451 auto const jrr = env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
457 jvParams[jss::account_root] = alice.human();
461 auto tryField = [&](
Json::Value fieldValue) ->
void {
462 jvParams[jss::ledger_hash] = fieldValue;
464 apiVersion,
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
466 jrr,
"invalidParams",
"Invalid field 'ledger_hash', not hex string.");
470 for (
auto const& value : badValues)
480 jvParams[jss::ledger_index] =
"validated";
481 jvParams[jss::index] =
482 "00000000000000000000000000000000000000000000000000000000000000"
484 auto const jrr = env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
492 jvParams[jss::features] =
493 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
495 jvParams[jss::api_version] = apiVersion;
497 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
505 checkErrorValue(jrr,
"invalidParams",
"No ledger_entry params provided.");
515 using namespace test::jtx;
518 cfg->FEES.reference_fee = 10;
519 Env env{*
this, std::move(cfg)};
529 BEAST_EXPECT(jrr[jss::ledger_hash] ==
ledgerHash);
530 BEAST_EXPECT(jrr[jss::ledger_index] == 3);
537 jvParams[jss::account_root] = alice.human();
540 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
541 BEAST_EXPECT(jrr.
isMember(jss::node));
542 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
543 BEAST_EXPECT(jrr[jss::node][sfBalance.jsonName] ==
"10000000000");
544 accountRootIndex = jrr[jss::index].
asString();
547 constexpr char aliceAcctRootBinary[]{
548 "1100612200800000240000000425000000032D00000000559CE54C3B934E4"
549 "73A995B477E92EC229F99CED5B62BF4D2ACE4DC42719103AE2F6240000002"
550 "540BE4008114AE123A8556F3CF91154711376AFB0F894F832B3D"};
554 jvParams[jss::account_root] = alice.human();
555 jvParams[jss::binary] = 1;
558 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
559 BEAST_EXPECT(jrr.
isMember(jss::node_binary));
560 BEAST_EXPECT(jrr[jss::node_binary] == aliceAcctRootBinary);
565 jvParams[jss::index] = accountRootIndex;
567 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
568 BEAST_EXPECT(!jrr.
isMember(jss::node_binary));
569 BEAST_EXPECT(jrr.
isMember(jss::node));
570 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
571 BEAST_EXPECT(jrr[jss::node][sfBalance.jsonName] ==
"10000000000");
576 jvParams[jss::index] = accountRootIndex;
577 jvParams[jss::binary] = 0;
579 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
580 BEAST_EXPECT(jrr.
isMember(jss::node));
581 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
582 BEAST_EXPECT(jrr[jss::node][sfBalance.jsonName] ==
"10000000000");
587 jvParams[jss::account] = alice.human();
590 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
591 BEAST_EXPECT(jrr.
isMember(jss::node));
592 BEAST_EXPECT(jrr[jss::node][jss::Account] == alice.human());
593 BEAST_EXPECT(jrr[jss::node][sfBalance.jsonName] ==
"10000000000");
594 accountRootIndex = jrr[jss::index].
asString();
608 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
617 using namespace test::jtx;
634 "42426C4D4F1009EE67080A9B7965B44656D7"
635 "714D104A72F9B4369F97ABF044EE"));
638 "4C97EBA926031A7CF7D7B36FDE3ED66DDA54"
639 "21192D63DE53FFB46E43B9DC8373"));
642 "03BDC0099C4E14163ADA272C1B6F6FABB448"
643 "CC3E51F522F978041E4B57D9158C"));
646 "35291ADD2D79EB6991343BDA0912269C817D"
647 "0F094B02226C1C14AD2858962ED4"));
648 sle->setFieldV256(sfAmendments,
STVector256(enabledAmendments));
654 majority1.setFieldH256(
657 "7BB62DC13EC72B775091E9C71BF8CF97E122"
658 "647693B50C5E87A80DFD6FCFAC50"));
659 majority1.setFieldU32(sfCloseTime, 779561310);
660 majorities.
push_back(std::move(majority1));
663 majority2.setFieldH256(
666 "755C971C29971C9F20C6F080F2ED96F87884"
667 "E40AD19554A5EBECDCEC8A1F77FE"));
668 majority2.setFieldU32(sfCloseTime, 779561310);
669 majorities.
push_back(std::move(majority2));
671 sle->setFieldArray(sfMajorities, majorities);
682 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
683 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Amendments);
695 using namespace test::jtx;
702 AMM const amm(env, alice,
XRP(10), alice[
"USD"](1000));
707 jvParams[jss::amm] =
to_string(amm.ammID());
708 auto const result = env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
710 result.isObject() && result.isMember(jss::result) &&
711 !result[jss::result].isMember(jss::error) &&
712 result[jss::result].isMember(jss::node) &&
713 result[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) &&
714 result[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::AMM);
722 obj[jss::currency] =
"XRP";
723 ammParams[jss::asset] = obj;
727 obj[jss::currency] =
"USD";
728 obj[jss::issuer] = alice.human();
729 ammParams[jss::asset2] = obj;
731 jvParams[jss::amm] = ammParams;
732 auto const result = env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
734 result.isObject() && result.isMember(jss::result) &&
735 !result[jss::result].isMember(jss::error) &&
736 result[jss::result].isMember(jss::node) &&
737 result[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) &&
738 result[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::AMM);
746 {jss::asset,
"malformedRequest"},
747 {jss::asset2,
"malformedRequest"},
755 using namespace test::jtx;
770 jvParams[jss::check] =
to_string(checkId.key);
773 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
774 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Check);
775 BEAST_EXPECT(jrr[jss::node][sfSendMax.jsonName] ==
"100000000");
783 jvParams[jss::account_root] = alice.human();
785 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
786 accountRootIndex = jrr[jss::index].
asString();
789 jvParams[jss::check] = accountRootIndex;
792 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
793 checkErrorValue(jrr,
"unexpectedLedgerType",
"Unexpected ledger type.");
806 using namespace test::jtx;
809 Account const issuer{
"issuer"};
812 char const credType[] =
"abcde";
814 env.
fund(
XRP(5000), issuer, alice, bob);
826 !jv[jss::result].
isMember(jss::error) && jv[jss::result].
isMember(jss::node) &&
827 jv[jss::result][jss::node].
isMember(sfLedgerEntryType.jsonName) &&
828 jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::Credential);
835 !jv[jss::result].
isMember(jss::error) && jv[jss::result].
isMember(jss::node) &&
836 jv[jss::result][jss::node].
isMember(sfLedgerEntryType.jsonName) &&
837 jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::Credential);
844 "48004829F915654A81B11C4AB8218D96FED67F209B58328A72314FB6EA288B"
855 {jss::subject,
"malformedRequest"},
856 {jss::issuer,
"malformedRequest"},
857 {jss::credential_type,
"malformedRequest"},
867 using namespace test::jtx;
872 env.
fund(
XRP(10000), alice, bob);
881 jvParams[jss::delegate][jss::account] = alice.human();
882 jvParams[jss::delegate][jss::authorize] = bob.human();
885 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
886 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Delegate);
887 BEAST_EXPECT(jrr[jss::node][sfAccount.jsonName] == alice.human());
888 BEAST_EXPECT(jrr[jss::node][sfAuthorize.jsonName] == bob.human());
889 delegateIndex = jrr[jss::node][jss::index].
asString();
894 jvParams[jss::delegate] = delegateIndex;
897 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
898 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Delegate);
899 BEAST_EXPECT(jrr[jss::node][sfAccount.jsonName] == alice.human());
900 BEAST_EXPECT(jrr[jss::node][sfAuthorize.jsonName] == bob.human());
909 {jss::account,
"malformedAddress"},
910 {jss::authorize,
"malformedAddress"},
920 using namespace test::jtx;
926 env.
fund(
XRP(10000), alice, becky);
937 jvParams[jss::deposit_preauth][jss::owner] = alice.human();
938 jvParams[jss::deposit_preauth][jss::authorized] = becky.human();
941 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
943 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::DepositPreauth);
944 BEAST_EXPECT(jrr[jss::node][sfAccount.jsonName] == alice.human());
945 BEAST_EXPECT(jrr[jss::node][sfAuthorize.jsonName] == becky.human());
946 depositPreauthIndex = jrr[jss::node][jss::index].
asString();
951 jvParams[jss::deposit_preauth] = depositPreauthIndex;
954 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
956 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::DepositPreauth);
957 BEAST_EXPECT(jrr[jss::node][sfAccount.jsonName] == alice.human());
958 BEAST_EXPECT(jrr[jss::node][sfAuthorize.jsonName] == becky.human());
964 jss::deposit_preauth,
966 {jss::owner,
"malformedOwner"},
967 {jss::authorized,
"malformedAuthorized",
false},
975 testcase(
"Deposit Preauth with credentials");
977 using namespace test::jtx;
980 Account const issuer{
"issuer"};
983 char const credType[] =
"abcde";
985 env.
fund(
XRP(5000), issuer, alice, bob);
990 env(
fset(bob, asfDepositAuth));
999 jvParams[jss::ledger_index] = jss::validated;
1000 jvParams[jss::deposit_preauth][jss::owner] = bob.human();
1002 jvParams[jss::deposit_preauth][jss::authorized_credentials] =
Json::arrayValue;
1003 auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]);
1006 jo[jss::issuer] = issuer.human();
1008 arr.append(std::move(jo));
1009 auto const jrr = env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
1012 jrr.isObject() && jrr.isMember(jss::result) &&
1013 !jrr[jss::result].isMember(jss::error) && jrr[jss::result].isMember(jss::node) &&
1014 jrr[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) &&
1015 jrr[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::DepositPreauth);
1021 jvParams[jss::ledger_index] = jss::validated;
1022 jvParams[jss::deposit_preauth][jss::owner] = bob.human();
1024 auto tryField = [&](
Json::Value fieldValue) ->
void {
1027 jo[jss::issuer] = fieldValue;
1030 jvParams[jss::deposit_preauth][jss::authorized_credentials] = arr;
1033 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1034 auto const expectedErrMsg = fieldValue.
isNull()
1037 checkErrorValue(jrr,
"malformedAuthorizedCredentials", expectedErrMsg);
1041 for (
auto const& value : badValues)
1051 jvParams[jss::ledger_index] = jss::validated;
1052 jvParams[jss::deposit_preauth][jss::owner] = bob.human();
1054 jvParams[jss::deposit_preauth][jss::authorized_credentials] =
Json::arrayValue;
1055 auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]);
1058 jo[jss::issuer] = issuer.human();
1061 arr.append(std::move(jo));
1062 auto const jrr = env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
1065 "malformedAuthorizedCredentials",
1072 jvParams[jss::ledger_index] = jss::validated;
1073 jvParams[jss::deposit_preauth][jss::owner] = bob.human();
1075 auto tryField = [&](
Json::Value fieldValue) ->
void {
1078 jo[jss::issuer] = issuer.human();
1079 jo[jss::credential_type] = fieldValue;
1081 jvParams[jss::deposit_preauth][jss::authorized_credentials] = arr;
1084 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1085 auto const expectedErrMsg = fieldValue.
isNull()
1088 checkErrorValue(jrr,
"malformedAuthorizedCredentials", expectedErrMsg);
1092 for (
auto const& value : badValues)
1102 jvParams[jss::ledger_index] = jss::validated;
1103 jvParams[jss::deposit_preauth][jss::owner] = bob.human();
1104 jvParams[jss::deposit_preauth][jss::authorized] = alice.human();
1106 jvParams[jss::deposit_preauth][jss::authorized_credentials] =
Json::arrayValue;
1107 auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]);
1110 jo[jss::issuer] = issuer.human();
1112 arr.append(std::move(jo));
1114 auto const jrr = env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
1118 "Must have exactly one of `authorized` and "
1119 "`authorized_credentials`.");
1125 jvParams[jss::ledger_index] = jss::validated;
1126 jvParams[jss::deposit_preauth][jss::owner] = bob.human();
1130 jss::deposit_preauth,
1131 jss::authorized_credentials,
1133 "malformedAuthorizedCredentials",
1140 jvParams[jss::ledger_index] = jss::validated;
1141 jvParams[jss::deposit_preauth][jss::owner] = bob.human();
1142 jvParams[jss::deposit_preauth][jss::authorized_credentials] =
Json::arrayValue;
1143 auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]);
1144 arr.append(
"foobar");
1146 auto const jrr = env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
1149 "malformedAuthorizedCredentials",
1150 "Invalid field 'authorized_credentials', not array.");
1156 jvParams[jss::ledger_index] = jss::validated;
1157 jvParams[jss::deposit_preauth][jss::owner] = bob.human();
1158 jvParams[jss::deposit_preauth][jss::authorized_credentials] =
Json::arrayValue;
1159 auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]);
1162 arr.
append(std::move(payload));
1164 auto const jrr = env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
1167 "malformedAuthorizedCredentials",
1168 "Invalid field 'authorized_credentials', not array.");
1174 jvParams[jss::ledger_index] = jss::validated;
1175 jvParams[jss::deposit_preauth][jss::owner] = bob.human();
1176 jvParams[jss::deposit_preauth][jss::authorized_credentials] =
Json::arrayValue;
1178 auto const jrr = env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
1181 "malformedAuthorizedCredentials",
1182 "Invalid field 'authorized_credentials', array empty.");
1188 "cred1",
"cred2",
"cred3",
"cred4",
"cred5",
"cred6",
"cred7",
"cred8",
"cred9"};
1192 jvParams[jss::ledger_index] = jss::validated;
1193 jvParams[jss::deposit_preauth][jss::owner] = bob.human();
1194 jvParams[jss::deposit_preauth][jss::authorized_credentials] =
Json::arrayValue;
1196 auto& arr(jvParams[jss::deposit_preauth][jss::authorized_credentials]);
1198 for (
auto cred : credTypes)
1201 jo[jss::issuer] = issuer.human();
1203 arr.append(std::move(jo));
1206 auto const jrr = env.
rpc(
"json",
"ledger_entry",
to_string(jvParams));
1209 "malformedAuthorizedCredentials",
1210 "Invalid field 'authorized_credentials', array too long.");
1218 using namespace test::jtx;
1222 auto const USD = gw[
"USD"];
1223 env.
fund(
XRP(10000), alice, gw);
1226 env.
trust(USD(1000), alice);
1231 for (
int d = 1'000'032; d >= 1'000'000; --d)
1241 BEAST_EXPECT(jrr[jss::ledger_hash] ==
ledgerHash);
1242 BEAST_EXPECT(jrr[jss::ledger_index] == 5);
1246 "A33EC6BB85FB5674074C4A3A43373BB17645308F3EAE1933E3E35252162B217D";
1250 jvParams[jss::directory] = dirRootIndex;
1253 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1254 BEAST_EXPECT(jrr[jss::node][sfIndexes.jsonName].
size() == 32);
1260 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
1262 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1263 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
1269 jvParams[jss::directory][jss::owner] = alice.human();
1272 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1273 BEAST_EXPECT(jrr[jss::index] == dirRootIndex);
1279 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
1280 jvParams[jss::directory][jss::sub_index] = 1;
1282 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1283 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
1284 BEAST_EXPECT(jrr[jss::node][sfIndexes.jsonName].
size() == 2);
1290 jvParams[jss::directory][jss::owner] = alice.human();
1291 jvParams[jss::directory][jss::sub_index] = 1;
1294 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1295 BEAST_EXPECT(jrr[jss::index] != dirRootIndex);
1296 BEAST_EXPECT(jrr[jss::node][sfIndexes.jsonName].
size() == 2);
1309 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
1339 jvParams[jss::directory][jss::owner] = alice.human();
1340 jvParams[jss::directory][jss::dir_root] = dirRootIndex;
1343 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1345 jrr,
"malformedRequest",
"Must have exactly one of `owner` and `dir_root` fields.");
1351 jvParams[jss::directory][jss::sub_index] = 1;
1354 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1356 jrr,
"malformedRequest",
"Must have exactly one of `owner` and `dir_root` fields.");
1364 using namespace test::jtx;
1376 jv[jss::TransactionType] = jss::EscrowCreate;
1377 jv[jss::Account] = account.human();
1378 jv[jss::Destination] = to.human();
1380 jv[sfFinishAfter.jsonName] = cancelAfter.time_since_epoch().count() + 2;
1384 using namespace std::chrono_literals;
1385 env(escrowCreate(alice, alice,
XRP(333), env.
now() + 2s));
1394 jvParams[jss::escrow][jss::owner] = alice.human();
1395 jvParams[jss::escrow][jss::seq] = env.
seq(alice) - 1;
1397 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1398 BEAST_EXPECT(jrr[jss::node][jss::Amount] ==
XRP(333).value().getText());
1399 escrowIndex = jrr[jss::index].
asString();
1404 jvParams[jss::escrow] = escrowIndex;
1407 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1408 BEAST_EXPECT(jrr[jss::node][jss::Amount] ==
XRP(333).value().getText());
1413 env, jss::escrow, {{jss::owner,
"malformedOwner"}, {jss::seq,
"malformedSeq"}});
1421 using namespace test::jtx;
1430 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1431 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::FeeSettings);
1443 using namespace test::jtx;
1452 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1453 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::LedgerHashes);
1465 using namespace test::jtx;
1469 Account const issuer{
"issuer"};
1471 env.
fund(
XRP(1000), issuer, buyer);
1483 jvParams[jss::nft_offer] =
to_string(offerID);
1485 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1486 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::NFTokenOffer);
1487 BEAST_EXPECT(jrr[jss::node][sfOwner.jsonName] == issuer.human());
1488 BEAST_EXPECT(jrr[jss::node][sfNFTokenID.jsonName] ==
to_string(nftokenID0));
1489 BEAST_EXPECT(jrr[jss::node][sfAmount.jsonName] ==
"1");
1500 using namespace test::jtx;
1504 Account const issuer{
"issuer"};
1511 BEAST_EXPECT(env.
le(nftpage) !=
nullptr);
1517 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1518 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::NFTokenPage);
1529 using namespace test::jtx;
1546 "ED58F6770DB5DD77E59D28CB650EC3816E2FC95021BB56E720C9A1"
1548 disabledValidator.setFieldVL(sfPublicKey, *pubKeyBlob);
1549 disabledValidator.setFieldU32(sfFirstLedgerSequence, 91371264);
1550 disabledValidators.
push_back(std::move(disabledValidator));
1552 sle->setFieldArray(sfDisabledValidators, disabledValidators);
1556 "8D47FFE664BE6C335108DF689537625855A6"
1557 "A95160CC6D351341B9"
1559 sle->setFieldU32(sfPreviousTxnLgrSeq, 91442944);
1570 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1571 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::NegativeUNL);
1583 using namespace test::jtx;
1587 auto const USD = gw[
"USD"];
1588 env.
fund(
XRP(10000), alice, gw);
1591 env(
offer(alice, USD(321),
XRP(322)));
1600 jvParams[jss::offer][jss::account] = alice.human();
1601 jvParams[jss::offer][jss::seq] = env.
seq(alice) - 1;
1604 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1605 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
1606 offerIndex = jrr[jss::index].
asString();
1611 jvParams[jss::offer] = offerIndex;
1613 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1614 BEAST_EXPECT(jrr[jss::node][jss::TakerGets] ==
"322000000");
1622 {{jss::account,
"malformedAddress"}, {jss::seq,
"malformedRequest"}});
1630 using namespace test::jtx;
1645 jv[jss::TransactionType] = jss::PaymentChannelCreate;
1646 jv[jss::Account] = account.human();
1647 jv[jss::Destination] = to.human();
1649 jv[sfSettleDelay.jsonName] = settleDelay.count();
1650 jv[sfPublicKey.jsonName] =
strHex(pk.slice());
1654 env(payChanCreate(alice, env.
master,
XRP(57), 18s, alice.pk()));
1663 jvParams[jss::payment_channel] =
to_string(payChanIndex);
1666 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1667 BEAST_EXPECT(jrr[jss::node][sfAmount.jsonName] ==
"57000000");
1668 BEAST_EXPECT(jrr[jss::node][sfBalance.jsonName] ==
"0");
1669 BEAST_EXPECT(jrr[jss::node][sfSettleDelay.jsonName] == 18);
1677 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1691 using namespace test::jtx;
1695 auto const USD = gw[
"USD"];
1696 env.
fund(
XRP(10000), alice, gw);
1699 env.
trust(USD(999), alice);
1702 env(
pay(gw, alice, USD(97)));
1706 for (
auto const& fieldName : {jss::ripple_state, jss::state})
1714 jvParams[fieldName][jss::accounts][0u] = alice.human();
1715 jvParams[fieldName][jss::accounts][1u] = gw.human();
1716 jvParams[fieldName][jss::currency] =
"USD";
1719 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1720 BEAST_EXPECT(jrr[jss::node][sfBalance.jsonName][jss::value] ==
"-97");
1721 BEAST_EXPECT(jrr[jss::node][sfHighLimit.jsonName][jss::value] ==
"999");
1729 {jss::accounts,
"malformedRequest"},
1730 {jss::currency,
"malformedCurrency"},
1738 jvParams[fieldName][jss::accounts][0u] = alice.human();
1739 jvParams[fieldName][jss::currency] =
"USD";
1742 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1746 "Invalid field 'accounts', not length-2 array of "
1754 jvParams[fieldName][jss::accounts][0u] = alice.human();
1755 jvParams[fieldName][jss::accounts][1u] = gw.human();
1756 jvParams[fieldName][jss::accounts][2u] = alice.human();
1757 jvParams[fieldName][jss::currency] =
"USD";
1760 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1764 "Invalid field 'accounts', not length-2 array of "
1771 auto tryField = [&](
Json::Value badAccount) ->
void {
1775 jvParams[fieldName][jss::accounts][0u] = badAccount;
1776 jvParams[fieldName][jss::accounts][1u] = gw.human();
1777 jvParams[fieldName][jss::currency] =
"USD";
1780 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1790 jvParams[fieldName][jss::accounts][0u] = alice.human();
1791 jvParams[fieldName][jss::accounts][1u] = badAccount;
1792 jvParams[fieldName][jss::currency] =
"USD";
1795 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1804 for (
auto const& value : badValues)
1815 jvParams[fieldName][jss::accounts][0u] = alice.human();
1816 jvParams[fieldName][jss::accounts][1u] = alice.human();
1817 jvParams[fieldName][jss::currency] =
"USD";
1820 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1821 checkErrorValue(jrr,
"malformedRequest",
"Cannot have a trustline to self.");
1830 using namespace test::jtx;
1839 using namespace test::jtx;
1858 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1867 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1868 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Ticket);
1869 BEAST_EXPECT(jrr[jss::node][sfTicketSequence.jsonName] == tkt1);
1875 jvParams[jss::ticket][jss::account] = env.
master.
human();
1876 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 1;
1879 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1887 jvParams[jss::ticket][jss::account] = env.
master.
human();
1888 jvParams[jss::ticket][jss::ticket_seq] = tkt1 + 2;
1891 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1900 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1901 checkErrorValue(jrr,
"unexpectedLedgerType",
"Unexpected ledger type.");
1910 {jss::account,
"malformedAddress"},
1911 {jss::ticket_seq,
"malformedRequest"},
1920 using namespace test::jtx;
1931 jv[jss::TransactionType] = jss::DIDSet;
1932 jv[jss::Account] = account.human();
1938 env(didCreate(alice));
1946 jvParams[jss::did] = alice.human();
1949 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1950 BEAST_EXPECT(jrr[jss::node][sfDIDDocument.jsonName] ==
strHex(
std::string{
"data"}));
1959 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
1973 testcase(
"Invalid Oracle Ledger Entry");
1981 env, {.owner = owner, .fee =
static_cast<int>(env.
current()->fees().base.drops())});
1989 {jss::account,
"malformedAccount"},
1990 {jss::oracle_document_id,
"malformedDocumentID"},
2003 auto const baseFee =
static_cast<int>(env.
current()->fees().base.drops());
2006 for (
int i = 0; i < 10; ++i)
2011 Oracle const oracle(env, {.owner = owner, .documentID = i, .fee = baseFee});
2015 Oracle const oracle1(env, {.owner = owner, .documentID = i + 10, .fee = baseFee});
2017 oracles.
push_back(oracle1.documentID());
2019 for (
int i = 0; i < accounts.
size(); ++i)
2021 auto const jv = [&]() {
2024 return Oracle::ledgerEntry(env, accounts[i], oracles[i]);
2026 return Oracle::ledgerEntry(env, accounts[i],
std::to_string(oracles[i]));
2030 BEAST_EXPECT(jv[jss::node][jss::Owner] ==
to_string(accounts[i]));
2043 using namespace test::jtx;
2049 MPTTester mptAlice(env, alice, {.holders = {bob}});
2054 .flags = tfMPTCanLock | tfMPTRequireAuth | tfMPTCanEscrow | tfMPTCanTrade |
2055 tfMPTCanTransfer | tfMPTCanClawback});
2056 mptAlice.authorize({.account = bob, .holderCount = 1});
2060 std::string const badMptID =
"00000193B9DDCAF401B5B3B26875986043F82CD0D13B4315";
2064 jvParams[jss::mpt_issuance] =
strHex(mptAlice.issuanceID());
2067 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2068 BEAST_EXPECT(jrr[jss::node][sfMPTokenMetadata.jsonName] ==
strHex(
std::string{
"123"}));
2069 BEAST_EXPECT(jrr[jss::node][jss::mpt_issuance_id] ==
strHex(mptAlice.issuanceID()));
2074 jvParams[jss::mpt_issuance] = badMptID;
2077 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2084 jvParams[jss::mptoken][jss::account] = bob.
human();
2085 jvParams[jss::mptoken][jss::mpt_issuance_id] =
strHex(mptAlice.issuanceID());
2088 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2090 jrr[jss::node][sfMPTokenIssuanceID.jsonName] ==
strHex(mptAlice.issuanceID()));
2096 jvParams[jss::mptoken][jss::account] = bob.
human();
2097 jvParams[jss::mptoken][jss::mpt_issuance_id] = badMptID;
2100 env.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2116 using namespace test::jtx;
2119 Account const issuer{
"issuer"};
2123 env.
fund(
XRP(5000), issuer, alice, bob);
2126 auto const seq = env.
seq(alice);
2130 if (!BEAST_EXPECT(objects.size() == 1))
2136 params[jss::ledger_index] = jss::validated;
2137 params[jss::permissioned_domain][jss::account] = alice.human();
2138 params[jss::permissioned_domain][jss::seq] =
seq;
2139 auto jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2142 !jv[jss::result].
isMember(jss::error) && jv[jss::result].
isMember(jss::node) &&
2143 jv[jss::result][jss::node].
isMember(sfLedgerEntryType.jsonName) &&
2144 jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::PermissionedDomain);
2150 params[jss::ledger_index] = jss::validated;
2151 params[jss::permissioned_domain] = pdIdx;
2152 jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2155 !jv[jss::result].
isMember(jss::error) && jv[jss::result].
isMember(jss::node) &&
2156 jv[jss::result][jss::node].
isMember(sfLedgerEntryType.jsonName) &&
2157 jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::PermissionedDomain);
2163 params[jss::ledger_index] = jss::validated;
2164 params[jss::permissioned_domain] =
2165 "12F1F1F1F180D67377B2FAB292A31C922470326268D2B9B74CD1E582645B9A"
2167 auto const jrr = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2168 checkErrorValue(jrr[jss::result],
"entryNotFound",
"Entry not found.");
2174 jss::permissioned_domain,
2176 {jss::account,
"malformedAddress"},
2177 {jss::seq,
"malformedRequest"},
2186 using namespace test::jtx;
2208 auto checkResult = [&](
bool good,
2215 jv.isObject() && jv.isMember(jss::result) &&
2216 !jv[jss::result].isMember(jss::error) &&
2217 jv[jss::result].isMember(jss::node) &&
2218 jv[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) &&
2219 jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == expectedType,
2225 jv.isObject() && jv.isMember(jss::result) &&
2226 jv[jss::result].isMember(jss::error) &&
2227 !jv[jss::result].isMember(jss::node) &&
2228 jv[jss::result][jss::error] == expectedError.value_or(
"entryNotFound"),
2245 Keylet const& expectedKey,
2247 testcase << expectedType.c_str() << (good ?
"" :
" not") <<
" found";
2249 auto const hexKey =
strHex(expectedKey.key);
2255 params[jss::ledger_index] = jss::validated;
2257 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2258 checkResult(
false, jv, expectedType,
"malformedRequest");
2259 BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
2265 params[jss::ledger_index] = jss::validated;
2266 params[field] =
"arbitrary string";
2267 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2268 checkResult(
false, jv, expectedType,
"malformedRequest");
2269 BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
2275 params[jss::ledger_index] = jss::validated;
2276 params[field] =
false;
2277 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2278 checkResult(
false, jv, expectedType,
"invalidParams");
2279 BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
2287 params[jss::ledger_index] = jss::validated;
2288 params[field] = badKey;
2289 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2290 checkResult(
false, jv, expectedType,
"entryNotFound");
2291 BEAST_EXPECTS(jv[jss::result][jss::index] == badKey,
to_string(jv));
2297 params[jss::ledger_index] = jss::validated;
2298 params[jss::index] = field;
2299 params[jss::api_version] = 2;
2300 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2301 checkResult(
false, jv, expectedType,
"malformedRequest");
2302 BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
2310 params[jss::ledger_index] = jss::validated;
2311 params[field] =
true;
2312 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2314 std::string const pdIdx = jv[jss::result][jss::index].asString();
2315 BEAST_EXPECTS(hexKey == pdIdx,
to_string(jv));
2316 checkResult(good, jv, expectedType);
2325 params[jss::ledger_index] = jss::validated;
2326 params[field] = hexKey;
2327 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2328 checkResult(good, jv, expectedType);
2329 BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey);
2336 params[jss::ledger_index] = jss::validated;
2337 params[jss::index] = field;
2338 params[jss::api_version] = 2;
2339 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2340 checkResult(
false, jv, expectedType,
"malformedRequest");
2341 BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
2347 params[jss::ledger_index] = jss::validated;
2348 params[jss::index] = field;
2349 params[jss::api_version] = 3;
2350 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2352 BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey);
2353 checkResult(good, jv, expectedType);
2359 params[jss::ledger_index] = jss::validated;
2360 params[jss::index] = pdIdx;
2361 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2363 BEAST_EXPECT(jv[jss::result][jss::index].asString() == hexKey);
2364 checkResult(good, jv, expectedType);
2369 test(jss::fee, jss::FeeSettings,
keylet::fees(),
true);
2373 test(jss::hashes, jss::LedgerHashes,
keylet::skip(),
true);
2379 using namespace test::jtx;
2401 auto checkResult = [&](
bool good,
2408 jv.isObject() && jv.isMember(jss::result) &&
2409 !jv[jss::result].isMember(jss::error) &&
2410 jv[jss::result].isMember(jss::node) &&
2411 jv[jss::result][jss::node].isMember(sfLedgerEntryType.jsonName) &&
2412 jv[jss::result][jss::node][sfLedgerEntryType.jsonName] == jss::LedgerHashes,
2415 jv[jss::result].isMember(jss::node) &&
2416 jv[jss::result][jss::node].isMember(
"Hashes") &&
2417 jv[jss::result][jss::node][
"Hashes"].size() == expectedCount,
2418 to_string(jv[jss::result][jss::node][
"Hashes"].size()));
2423 jv.isObject() && jv.isMember(jss::result) &&
2424 jv[jss::result].isMember(jss::error) &&
2425 !jv[jss::result].isMember(jss::node) &&
2426 jv[jss::result][jss::error] == expectedError.value_or(
"entryNotFound"),
2442 [&](
Json::Value ledger,
Keylet const& expectedKey,
bool good,
int expectedCount = 0) {
2444 <<
" \"hashes\":" <<
to_string(ledger) << (good ?
"" :
" not") <<
" found";
2446 auto const hexKey =
strHex(expectedKey.key);
2452 params[jss::ledger_index] = jss::validated;
2454 auto jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2455 checkResult(
false, jv, 0,
"malformedRequest");
2456 BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
2462 params[jss::ledger_index] = jss::validated;
2463 params[jss::hashes] =
"arbitrary string";
2464 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2465 checkResult(
false, jv, 0,
"malformedRequest");
2466 BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
2472 params[jss::ledger_index] = jss::validated;
2473 params[jss::hashes] =
"10";
2474 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2475 checkResult(
false, jv, 0,
"malformedRequest");
2476 BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
2482 params[jss::ledger_index] = jss::validated;
2483 params[jss::hashes] =
false;
2484 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2485 checkResult(
false, jv, 0,
"invalidParams");
2486 BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
2492 params[jss::ledger_index] = jss::validated;
2493 params[jss::hashes] = -1;
2494 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2495 checkResult(
false, jv, 0,
"internal");
2496 BEAST_EXPECT(!jv[jss::result].isMember(jss::index));
2503 params[jss::ledger_index] = jss::validated;
2504 params[jss::hashes] = badKey;
2505 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2506 checkResult(
false, jv, 0,
"entryNotFound");
2507 BEAST_EXPECT(jv[jss::result][jss::index] == badKey);
2514 params[jss::ledger_index] = jss::validated;
2515 params[jss::hashes] = ledger;
2516 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2517 checkResult(good, jv, expectedCount);
2519 std::string const pdIdx = jv[jss::result][jss::index].asString();
2520 BEAST_EXPECTS(hexKey == pdIdx,
strHex(pdIdx));
2526 params[jss::ledger_index] = jss::validated;
2527 params[jss::hashes] = hexKey;
2528 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2529 checkResult(good, jv, expectedCount);
2532 hexKey == jv[jss::result][jss::index].asString(),
2533 strHex(jv[jss::result][jss::index].asString()));
2539 params[jss::ledger_index] = jss::validated;
2540 params[jss::index] = hexKey;
2541 auto const jv = env.
rpc(
"json",
"ledger_entry",
to_string(params));
2542 checkResult(good, jv, expectedCount);
2545 hexKey == jv[jss::result][jss::index].asString(),
2546 strHex(jv[jss::result][jss::index].asString()));
2558 for (
auto i = env.
current()->seq(); i <= 250; ++i)
2569 for (
auto i = env.
current()->seq(); i <= 260; ++i)
2584 using namespace test::jtx;
2598 BEAST_EXPECT(jrr[jss::node][sfLedgerEntryType.jsonName] == jss::Check);
2599 BEAST_EXPECT(jrr[jss::node][sfSendMax.jsonName] ==
"100000000");
2644 if (BEAST_EXPECT(jv.
isMember(jss::status)))
2645 BEAST_EXPECT(jv[jss::status] ==
"error");
2646 if (BEAST_EXPECT(jv.
isMember(jss::error)))
2647 BEAST_EXPECT(jv[jss::error] == err);
2650 BEAST_EXPECT(jv[jss::error_message] ==
Json::nullValue || jv[jss::error_message] ==
"");
2652 else if (BEAST_EXPECT(jv.
isMember(jss::error_message)))
2654 BEAST_EXPECT(jv[jss::error_message] == msg);
2662 using namespace test::jtx;
2676 jvParams[jss::bridge] =
jvb;
2678 mcEnv.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2680 BEAST_EXPECT(jrr.
isMember(jss::node));
2681 auto r = jrr[jss::node];
2683 BEAST_EXPECT(r.isMember(jss::Account));
2686 BEAST_EXPECT(r.isMember(jss::Flags));
2688 BEAST_EXPECT(r.isMember(sfLedgerEntryType.jsonName));
2689 BEAST_EXPECT(r[sfLedgerEntryType.jsonName] == jss::Bridge);
2692 BEAST_EXPECT(r.isMember(sfXChainAccountCreateCount.jsonName));
2693 BEAST_EXPECT(r[sfXChainAccountCreateCount.jsonName].asInt() == 0);
2696 BEAST_EXPECT(r.isMember(sfXChainAccountClaimCount.jsonName));
2697 BEAST_EXPECT(r[sfXChainAccountClaimCount.jsonName].asInt() == 0);
2699 BEAST_EXPECT(r.isMember(jss::index));
2700 bridge_index = r[jss::index].asString();
2706 jvParams[jss::index] = bridge_index;
2708 mcEnv.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2710 BEAST_EXPECT(jrr.
isMember(jss::node));
2711 BEAST_EXPECT(jrr[jss::node] == mcBridge);
2718 jvParams[jss::bridge] =
jvb;
2721 mcEnv.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2736 jvParams[jss::bridge] =
jvb;
2738 mcEnv.rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2740 BEAST_EXPECT(jrr.
isMember(jss::node));
2741 auto r = jrr[jss::node];
2744 BEAST_EXPECT(r.isMember(sfXChainClaimID.jsonName));
2745 BEAST_EXPECT(r[sfXChainClaimID.jsonName].asInt() == 2);
2752 testcase(
"ledger_entry: xchain_claim_id");
2753 using namespace test::jtx;
2769 jvParams[jss::xchain_owned_claim_id][jss::xchain_owned_claim_id] = 1;
2771 scEnv.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2773 BEAST_EXPECT(jrr.
isMember(jss::node));
2774 auto r = jrr[jss::node];
2776 BEAST_EXPECT(r.isMember(jss::Account));
2778 BEAST_EXPECT(r[sfLedgerEntryType.jsonName] == jss::XChainOwnedClaimID);
2779 BEAST_EXPECT(r[sfXChainClaimID.jsonName].asInt() == 1);
2780 BEAST_EXPECT(r[sfOwnerNode.jsonName].asInt() == 0);
2787 jvParams[jss::xchain_owned_claim_id][jss::xchain_owned_claim_id] = 2;
2789 scEnv.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2791 BEAST_EXPECT(jrr.
isMember(jss::node));
2792 auto r = jrr[jss::node];
2794 BEAST_EXPECT(r.isMember(jss::Account));
2795 BEAST_EXPECT(r[jss::Account] ==
scBob.
human());
2796 BEAST_EXPECT(r[sfLedgerEntryType.jsonName] == jss::XChainOwnedClaimID);
2797 BEAST_EXPECT(r[sfXChainClaimID.jsonName].asInt() == 2);
2798 BEAST_EXPECT(r[sfOwnerNode.jsonName].asInt() == 0);
2805 testcase(
"ledger_entry: xchain_create_account_claim_id");
2806 using namespace test::jtx;
2816 auto const amt =
XRP(1000);
2822 size_t constexpr num_attest = 3;
2835 for (
size_t i = 0; i < num_attest; ++i)
2837 scEnv(attestations[i]);
2844 jvParams[jss::xchain_owned_create_account_claim_id] =
jvXRPBridgeRPC;
2845 jvParams[jss::xchain_owned_create_account_claim_id]
2846 [jss::xchain_owned_create_account_claim_id] = 1;
2848 scEnv.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2850 BEAST_EXPECT(jrr.
isMember(jss::node));
2851 auto r = jrr[jss::node];
2853 BEAST_EXPECT(r.isMember(jss::Account));
2856 BEAST_EXPECT(r.isMember(sfXChainAccountCreateCount.jsonName));
2857 BEAST_EXPECT(r[sfXChainAccountCreateCount.jsonName].asInt() == 1);
2859 BEAST_EXPECT(r.isMember(sfXChainCreateAccountAttestations.jsonName));
2860 auto attest = r[sfXChainCreateAccountAttestations.jsonName];
2861 BEAST_EXPECT(attest.isArray());
2862 BEAST_EXPECT(attest.size() == 3);
2866 for (
size_t i = 0; i < num_attest; ++i)
2870 a[i].isMember(jss::Amount) && a[i][jss::Amount].asInt() == 1000 *
drop_per_xrp);
2872 a[i].isMember(jss::Destination) && a[i][jss::Destination] ==
scCarol.
human());
2874 a[i].isMember(sfAttestationSignerAccount.jsonName) &&
2876 return a[i][sfAttestationSignerAccount.jsonName] == s.account.human();
2879 a[i].isMember(sfAttestationRewardAccount.jsonName) &&
2881 return a[i][sfAttestationRewardAccount.jsonName] == account.human();
2884 a[i].isMember(sfWasLockingChainSend.jsonName) &&
2885 a[i][sfWasLockingChainSend.jsonName] == 1);
2887 a[i].isMember(sfSignatureReward.jsonName) &&
2896 scEnv(attestations[i]);
2902 jvParams[jss::xchain_owned_create_account_claim_id] =
jvXRPBridgeRPC;
2903 jvParams[jss::xchain_owned_create_account_claim_id]
2904 [jss::xchain_owned_create_account_claim_id] = 1;
2906 scEnv.
rpc(
"json",
"ledger_entry",
to_string(jvParams))[jss::result];
2922BEAST_DEFINE_TESTSUITE(LedgerEntry_XChain,
rpc,
xrpl);
Lightweight wrapper to tag static string.
constexpr char const * c_str() const
Value & append(Value const &value)
Append value to array at the end.
UInt size() const
Number of values in array or object.
std::string toStyledString() const
void clear()
Remove all object members and array elements.
Value removeMember(char const *key)
Remove and return the named member.
std::string asString() const
Returns the unquoted string value.
bool isNull() const
isNull() tests to see if this field is null.
bool isMember(char const *key) const
Return true if the object has a member named key.
A generic endpoint for log messages.
testcase_t testcase
Memberspace for declaring test cases.
void fail(String const &reason, char const *file, int line)
Record a failure.
bool modify(modify_type const &f)
Modify the open ledger.
Writable ledger view that accumulates state and tx changes.
void rawInsert(std::shared_ptr< SLE > const &sle) override
Unconditionally insert a state item.
void push_back(STObject const &object)
static STObject makeInnerObject(SField const &name)
virtual OpenLedger & getOpenLedger()=0
static base_uint fromVoid(void const *data)
void testCreateAccountClaimID()
void run() override
Runs the suite.
void checkErrorValue(Json::Value const &jv, std::string const &err, std::string const &msg)
void checkErrorValue(Json::Value const &jv, std::string const &err, std::string const &msg, std::source_location const location=std::source_location::current())
void testOracleLedgerEntry()
void testMalformedSubfield(test::jtx::Env &env, Json::Value correctRequest, Json::StaticString parentFieldName, Json::StaticString fieldName, FieldType typeID, std::string const &expectedError, bool required=true, std::source_location const location=std::source_location::current())
void run() override
Runs the suite.
void testMalformedField(test::jtx::Env &env, Json::Value correctRequest, Json::StaticString const fieldName, FieldType const typeID, std::string const &expectedError, bool required=true, std::source_location const location=std::source_location::current())
static std::vector< Json::Value > getBadValues(FieldType fieldType)
static Json::Value getCorrectValue(Json::StaticString fieldName)
void testDepositPreauth()
void runLedgerEntryTest(test::jtx::Env &env, Json::StaticString const &parentField, std::source_location const location=std::source_location::current())
void runLedgerEntryTest(test::jtx::Env &env, Json::StaticString const &parentField, std::vector< Subfield > const &subfields, std::source_location const location=std::source_location::current())
void testFixed()
Test the ledger entry types that don't take parameters.
void testPermissionedDomain()
void testDepositPreauthCred()
void testInvalidOracleLedgerEntry()
Convenience class to test AMM functionality.
Immutable cryptographic account descriptor.
std::string const & human() const
Returns the human readable public key.
static Account const master
The master account.
AccountID id() const
Returns the Account ID.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
NetClock::time_point now()
Returns the current network time.
void create(MPTCreate const &arg=MPTCreate{})
Oracle class facilitates unit-testing of the Price Oracle feature.
Set the expected result code for a JTx The test will fail if the code doesn't match.
Sets the optional Destination field on an NFTokenOffer.
@ arrayValue
array value (ordered list)
@ objectValue
object value (collection of name/value pairs).
std::string expected_field_message(std::string const &name, std::string const &type)
std::string missing_field_message(std::string const &name)
Keylet const & skip() noexcept
The index of the "short" skip list.
Keylet const & negativeUNL() noexcept
The (fixed) index of the object containing the ledger negativeUNL.
Keylet nftpage_max(AccountID const &owner)
A keylet for the owner's last possible NFT page.
Keylet nftoffer(AccountID const &owner, std::uint32_t seq)
An offer from an account to buy or sell an NFT.
Keylet const & amendments() noexcept
The index of the amendment table.
Keylet payChan(AccountID const &src, AccountID const &dst, std::uint32_t seq) noexcept
A PaymentChannel.
Keylet check(AccountID const &id, std::uint32_t seq) noexcept
A Check.
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Keylet permissionedDomain(AccountID const &account, std::uint32_t seq) noexcept
Json::Value create(A const &account, A const &dest, STAmount const &sendMax)
Create a check.
Json::Value ledgerEntry(jtx::Env &env, jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
Json::Value create(jtx::Account const &subject, jtx::Account const &issuer, std::string_view credType)
Json::Value set(jtx::Account const &account, jtx::Account const &authorize, std::vector< std::string > const &permissions)
Json::Value authCredentials(jtx::Account const &account, std::vector< AuthorizeCredentials > const &auth)
Json::Value auth(Account const &account, Account const &auth)
Preauthorize for deposit.
Json::Value setTx(AccountID const &account, Credentials const &credentials, std::optional< uint256 > domain)
std::map< uint256, Json::Value > getObjects(Account const &account, Env &env, bool withType)
Json::Value create(Account const &account, std::uint32_t count)
Create one of more tickets.
Json::Value mint(jtx::Account const &account, std::uint32_t nfTokenTaxon)
Mint an NFToken.
Json::Value createOffer(jtx::Account const &account, uint256 const &nftokenID, STAmount const &amount)
Create an NFTokenOffer.
uint256 getNextID(jtx::Env const &env, jtx::Account const &issuer, std::uint32_t nfTokenTaxon, std::uint16_t flags, std::uint16_t xferFee)
Get the next NFTokenID that will be issued.
Json::Value sidechain_xchain_account_create(Account const &acc, Json::Value const &bridge, Account const &dst, AnyAmount const &amt, AnyAmount const &reward)
constexpr std::size_t UT_XCHAIN_DEFAULT_NUM_SIGNERS
XRP_t const XRP
Converts to XRP Issue or STAmount.
require_t required(Args const &... args)
Compose many condition functors into one.
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
JValueVec create_account_attestations(jtx::Account const &submittingAccount, Json::Value const &jvBridge, jtx::Account const &sendingAccount, jtx::AnyAmount const &sendingAmount, jtx::AnyAmount const &rewardAmount, std::vector< jtx::Account > const &rewardAccounts, bool wasLockingChainSend, std::uint64_t createCount, jtx::Account const &dst, std::vector< jtx::signer > const &signers, std::size_t const numAtts, std::size_t const fromIdx)
Json::Value xchain_create_claim_id(Account const &acc, Json::Value const &bridge, STAmount const &reward, Account const &otherChainSource)
FeatureBitset testable_amendments()
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
std::vector< std::pair< Json::StaticString, FieldType > > mappings
FieldType getFieldType(Json::StaticString fieldName)
static uint256 ledgerHash(LedgerHeader const &info)
std::string getTypeName(FieldType typeID)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::string to_string(base_uint< Bits, Tag > const &a)
std::string strHex(FwdIt begin, FwdIt end)
uint256 getTicketIndex(AccountID const &account, std::uint32_t uSequence)
void forAllApiVersions(Fn const &fn, Args &&... args)
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
std::size_t constexpr maxCredentialsArraySize
The maximum number of credentials can be passed in array.
A pair of SHAMap key and LedgerEntryType.
Json::StaticString fieldName
std::string malformedErrorMsg
void createBridgeObjects(Env &mcEnv, Env &scEnv)
Json::Value const jvXRPBridgeRPC
std::vector< Account > const payee
std::vector< signer > const signers
FeatureBitset const features
static constexpr int drop_per_xrp
Set the sequence number on a JTx.
A signer in a SignerList.