371 testcase(
"unsteppedThenSteppedWithNFTs");
380 auto const USD1 = gw1[
"USD"];
381 auto const USD2 = gw2[
"USD"];
383 env.
fund(
XRP(1000), gw1, gw2, bob);
390 params[jss::account] = bob.human();
391 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
392 BEAST_EXPECT(!resp.isMember(jss::marker));
393 BEAST_EXPECT(resp[jss::result][jss::account_objects].size() == 0);
396 params[jss::limit] = 1;
397 resp = env.
rpc(
"json",
"account_objects",
to_string(params));
398 BEAST_EXPECT(!resp.isMember(jss::marker));
399 BEAST_EXPECT(resp[jss::result][jss::account_objects].size() == 0);
411 params[jss::account] = bob.human();
412 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
413 BEAST_EXPECT(!resp.isMember(jss::marker));
415 unpaged = resp[jss::result][jss::account_objects];
416 BEAST_EXPECT(unpaged.
size() == 1);
421 params[jss::account] = bob.human();
422 params[jss::type] = jss::nft_page;
423 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
424 BEAST_EXPECT(!resp.isMember(jss::marker));
425 Json::Value& aobjs = resp[jss::result][jss::account_objects];
426 BEAST_EXPECT(aobjs.
size() == 1);
428 aobjs[0u][sfLedgerEntryType.jsonName] == jss::NFTokenPage);
429 BEAST_EXPECT(aobjs[0u][sfNFTokens.jsonName].
size() == 1);
434 params[jss::account] = bob.human();
435 params[jss::limit] = 1;
439 Json::Value& aobjs = resp[jss::result][jss::account_objects];
440 BEAST_EXPECT(aobjs.
size() == 1);
441 auto& aobj = aobjs[0U];
442 BEAST_EXPECT(!resp[jss::result].isMember(jss::limit));
443 BEAST_EXPECT(!resp[jss::result].isMember(jss::marker));
445 BEAST_EXPECT(aobj == unpaged[0u]);
449 env.
trust(USD1(1000), bob);
450 env.
trust(USD2(1000), bob);
452 env(
pay(gw1, bob, USD1(1000)));
453 env(
pay(gw2, bob, USD2(1000)));
462 params[jss::account] = bob.human();
463 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
464 BEAST_EXPECT(!resp.isMember(jss::marker));
466 unpaged = resp[jss::result][jss::account_objects];
467 BEAST_EXPECT(unpaged.
size() == 5);
472 params[jss::account] = bob.human();
473 params[jss::type] = jss::nft_page;
474 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
475 BEAST_EXPECT(!resp.isMember(jss::marker));
476 Json::Value& aobjs = resp[jss::result][jss::account_objects];
477 BEAST_EXPECT(aobjs.
size() == 1);
479 aobjs[0u][sfLedgerEntryType.jsonName] == jss::NFTokenPage);
480 BEAST_EXPECT(aobjs[0u][sfNFTokens.jsonName].
size() == 1);
485 params[jss::account] = bob.human();
486 params[jss::limit] = 1;
487 for (
int i = 0; i < 5; ++i)
491 Json::Value& aobjs = resp[jss::result][jss::account_objects];
492 BEAST_EXPECT(aobjs.
size() == 1);
493 auto& aobj = aobjs[0U];
496 BEAST_EXPECT(resp[jss::result][jss::limit] == 1);
497 BEAST_EXPECT(resp[jss::result].isMember(jss::marker));
501 BEAST_EXPECT(!resp[jss::result].isMember(jss::limit));
502 BEAST_EXPECT(!resp[jss::result].isMember(jss::marker));
505 BEAST_EXPECT(aobj == unpaged[i]);
507 params[jss::marker] = resp[jss::result][jss::marker];
512 for (
int i = 0; i < 32; ++i)
520 params[jss::account] = bob.human();
521 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
522 BEAST_EXPECT(!resp.isMember(jss::marker));
524 unpaged = resp[jss::result][jss::account_objects];
525 BEAST_EXPECT(unpaged.
size() == 6);
530 params[jss::account] = bob.human();
531 params[jss::type] = jss::nft_page;
532 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
533 BEAST_EXPECT(!resp.isMember(jss::marker));
534 Json::Value& aobjs = resp[jss::result][jss::account_objects];
535 BEAST_EXPECT(aobjs.
size() == 2);
540 params[jss::account] = bob.human();
541 params[jss::limit] = 1;
542 for (
int i = 0; i < 6; ++i)
546 Json::Value& aobjs = resp[jss::result][jss::account_objects];
547 BEAST_EXPECT(aobjs.
size() == 1);
548 auto& aobj = aobjs[0U];
551 BEAST_EXPECT(resp[jss::result][jss::limit] == 1);
552 BEAST_EXPECT(resp[jss::result].isMember(jss::marker));
556 BEAST_EXPECT(!resp[jss::result].isMember(jss::limit));
557 BEAST_EXPECT(!resp[jss::result].isMember(jss::marker));
560 BEAST_EXPECT(aobj == unpaged[i]);
562 params[jss::marker] = resp[jss::result][jss::marker];
578 auto const USD = gw[
"USD"];
581 featurePermissionedDomains;
582 Env env(*
this, features);
585 auto acctObjs = [&env](
593 params[jss::type] = *type;
595 params[jss::limit] = *limit;
597 params[jss::marker] = *marker;
598 params[jss::ledger_index] =
"validated";
599 return env.
rpc(
"json",
"account_objects",
to_string(params));
603 auto acctObjsIsSize = [](
Json::Value const& resp,
unsigned size) {
604 return resp[jss::result][jss::account_objects].
isArray() &&
605 (resp[jss::result][jss::account_objects].
size() == size);
609 auto acctObjsTypeIsInvalid = [](
Json::Value const& resp) {
610 return resp[jss::result].
isMember(jss::error) &&
611 resp[jss::result][jss::error_message] ==
612 "Invalid field \'type\'.";
615 env.
fund(
XRP(10000), gw, alice);
620 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::account), 0));
621 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::check), 0));
622 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::deposit_preauth), 0));
623 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::escrow), 0));
624 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::nft_page), 0));
625 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::offer), 0));
626 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::payment_channel), 0));
627 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::signer_list), 0));
628 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::state), 0));
629 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::ticket), 0));
630 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::amm), 0));
631 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::did), 0));
632 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::permissioned_domain), 0));
635 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::amendments)));
636 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::directory)));
637 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::fee)));
638 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::hashes)));
639 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::NegativeUNL)));
647 Json::Value const resp = acctObjs(gw, jss::nft_page);
648 BEAST_EXPECT(acctObjsIsSize(resp, 1));
650 auto const& nftPage = resp[jss::result][jss::account_objects][0u];
651 BEAST_EXPECT(nftPage[sfNFTokens.jsonName].size() == 1);
653 nftPage[sfNFTokens.jsonName][0u][sfNFToken.jsonName]
654 [sfNFTokenID.jsonName] ==
to_string(nftID));
658 env.
trust(USD(1000), alice);
660 env(
pay(gw, alice, USD(5)));
665 BEAST_EXPECT(acctObjsIsSize(resp, 1));
667 auto const& state = resp[jss::result][jss::account_objects][0u];
668 BEAST_EXPECT(state[sfBalance.jsonName][jss::value].asInt() == -5);
670 state[sfHighLimit.jsonName][jss::value].asUInt() == 1000);
678 BEAST_EXPECT(acctObjsIsSize(resp, 1));
680 auto const& check = resp[jss::result][jss::account_objects][0u];
681 BEAST_EXPECT(check[sfAccount.jsonName] == gw.human());
682 BEAST_EXPECT(check[sfDestination.jsonName] == alice.human());
683 BEAST_EXPECT(check[sfSendMax.jsonName][jss::value].asUInt() == 10);
690 Json::Value const resp = acctObjs(gw, jss::deposit_preauth);
691 BEAST_EXPECT(acctObjsIsSize(resp, 1));
693 auto const& preauth = resp[jss::result][jss::account_objects][0u];
694 BEAST_EXPECT(preauth[sfAccount.jsonName] == gw.human());
695 BEAST_EXPECT(preauth[sfAuthorize.jsonName] == alice.human());
700 jvEscrow[jss::TransactionType] = jss::EscrowCreate;
701 jvEscrow[jss::Account] = gw.human();
702 jvEscrow[jss::Destination] = gw.human();
704 jvEscrow[sfFinishAfter.jsonName] =
711 Json::Value const resp = acctObjs(gw, jss::escrow);
712 BEAST_EXPECT(acctObjsIsSize(resp, 1));
714 auto const& escrow = resp[jss::result][jss::account_objects][0u];
715 BEAST_EXPECT(escrow[sfAccount.jsonName] == gw.human());
716 BEAST_EXPECT(escrow[sfDestination.jsonName] == gw.human());
717 BEAST_EXPECT(escrow[sfAmount.jsonName].asUInt() == 100'000'000);
730 Json::Value const resp = acctObjs(gw, jss::permissioned_domain);
731 BEAST_EXPECT(acctObjsIsSize(resp, 1));
733 auto const& permissionedDomain =
734 resp[jss::result][jss::account_objects][0u];
736 permissionedDomain.isMember(jss::Owner) &&
737 (permissionedDomain[jss::Owner] == gw.human()));
738 bool const check1 = BEAST_EXPECT(
739 permissionedDomain.isMember(jss::AcceptedCredentials) &&
740 permissionedDomain[jss::AcceptedCredentials].isArray() &&
741 (permissionedDomain[jss::AcceptedCredentials].size() == 1) &&
742 (permissionedDomain[jss::AcceptedCredentials][0u].isMember(
748 permissionedDomain[jss::AcceptedCredentials][0u]
754 credential.isMember(sfCredentialType.jsonName) &&
756 strHex(credentialType1)));
766 auto scEnvAcctObjs = [&](
Account const& acct,
char const* type) {
768 params[jss::account] = acct.
human();
769 params[jss::type] = type;
770 params[jss::ledger_index] =
"validated";
771 return scEnv.
rpc(
"json",
"account_objects",
to_string(params));
777 BEAST_EXPECT(acctObjsIsSize(resp, 1));
778 auto const& acct_bridge =
779 resp[jss::result][jss::account_objects][0u];
783 acct_bridge[sfLedgerEntryType.getJsonName()] ==
"Bridge");
785 acct_bridge[sfXChainClaimID.getJsonName()].asUInt() == 0);
787 acct_bridge[sfXChainAccountClaimCount.getJsonName()].asUInt() ==
790 acct_bridge[sfXChainAccountCreateCount.getJsonName()]
793 acct_bridge[sfMinAccountCreateAmount.getJsonName()].asUInt() ==
796 acct_bridge[sfSignatureReward.getJsonName()].asUInt() ==
798 BEAST_EXPECT(acct_bridge[sfXChainBridge.getJsonName()] == x.
jvb);
813 auto scEnvAcctObjs = [&](
Account const& acct,
char const* type) {
815 params[jss::account] = acct.
human();
816 params[jss::type] = type;
817 params[jss::ledger_index] =
"validated";
818 return scEnv.
rpc(
"json",
"account_objects",
to_string(params));
824 scEnvAcctObjs(x.
scAlice, jss::xchain_owned_claim_id);
825 BEAST_EXPECT(acctObjsIsSize(resp, 1));
827 auto const& xchain_seq =
828 resp[jss::result][jss::account_objects][0u];
832 xchain_seq[sfXChainClaimID.getJsonName()].asUInt() == 1);
837 scEnvAcctObjs(x.
scBob, jss::xchain_owned_claim_id);
838 BEAST_EXPECT(acctObjsIsSize(resp, 1));
840 auto const& xchain_seq =
841 resp[jss::result][jss::account_objects][0u];
842 BEAST_EXPECT(xchain_seq[sfAccount.jsonName] == x.
scBob.
human());
844 xchain_seq[sfXChainClaimID.getJsonName()].asUInt() == 2);
851 auto const amt =
XRP(1000);
870 auto scEnvAcctObjs = [&](
Account const& acct,
char const* type) {
872 params[jss::account] = acct.
human();
873 params[jss::type] = type;
874 params[jss::ledger_index] =
"validated";
875 return scEnv.
rpc(
"json",
"account_objects",
to_string(params));
882 BEAST_EXPECT(acctObjsIsSize(resp, 1));
884 auto const& xchain_create_account_claim_id =
885 resp[jss::result][jss::account_objects][0u];
887 xchain_create_account_claim_id[sfAccount.jsonName] ==
890 xchain_create_account_claim_id[sfXChainAccountCreateCount
902 BEAST_EXPECT(acctObjsIsSize(resp, 1));
904 auto const&
offer = resp[jss::result][jss::account_objects][0u];
905 BEAST_EXPECT(
offer[sfAccount.jsonName] == gw.human());
906 BEAST_EXPECT(
offer[sfTakerGets.jsonName].
asUInt() == 14'000'000);
907 BEAST_EXPECT(
offer[sfTakerPays.jsonName][jss::value].
asUInt() == 7);
913 jvPayChan[jss::TransactionType] = jss::PaymentChannelCreate;
914 jvPayChan[jss::Account] = gw.human();
915 jvPayChan[jss::Destination] = alice.human();
916 jvPayChan[jss::Amount] =
918 jvPayChan[sfSettleDelay.jsonName] = 24 * 60 * 60;
919 jvPayChan[sfPublicKey.jsonName] =
strHex(gw.pk().slice());
925 Json::Value const resp = acctObjs(gw, jss::payment_channel);
926 BEAST_EXPECT(acctObjsIsSize(resp, 1));
928 auto const& payChan = resp[jss::result][jss::account_objects][0u];
929 BEAST_EXPECT(payChan[sfAccount.jsonName] == gw.human());
930 BEAST_EXPECT(payChan[sfAmount.jsonName].asUInt() == 300'000'000);
932 payChan[sfSettleDelay.jsonName].asUInt() == 24 * 60 * 60);
938 jvDID[jss::TransactionType] = jss::DIDSet;
939 jvDID[jss::Account] = gw.human();
947 BEAST_EXPECT(acctObjsIsSize(resp, 1));
949 auto const& did = resp[jss::result][jss::account_objects][0u];
950 BEAST_EXPECT(did[sfAccount.jsonName] == gw.human());
958 Json::Value const resp = acctObjs(gw, jss::signer_list);
959 BEAST_EXPECT(acctObjsIsSize(resp, 1));
961 auto const& signerList =
962 resp[jss::result][jss::account_objects][0u];
963 BEAST_EXPECT(signerList[sfSignerQuorum.jsonName] == 6);
964 auto const& entry = signerList[sfSignerEntries.jsonName][0u]
965 [sfSignerEntry.jsonName];
966 BEAST_EXPECT(entry[sfAccount.jsonName] == alice.human());
967 BEAST_EXPECT(entry[sfSignerWeight.jsonName].
asUInt() == 7);
971 auto const seq = env.
seq(gw);
977 Json::Value const resp = acctObjs(gw, jss::ticket);
978 BEAST_EXPECT(acctObjsIsSize(resp, 1));
980 auto const& ticket = resp[jss::result][jss::account_objects][0u];
981 BEAST_EXPECT(ticket[sfAccount.jsonName] == gw.human());
982 BEAST_EXPECT(ticket[sfLedgerEntryType.jsonName] == jss::Ticket);
983 BEAST_EXPECT(ticket[sfTicketSequence.jsonName].asUInt() ==
seq + 1);
989 params[jss::account] = gw.human();
990 params[jss::deletion_blockers_only] =
true;
991 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
997 jss::NFTokenPage.c_str(),
998 jss::RippleState.c_str(),
999 jss::PayChannel.c_str(),
1000 jss::PermissionedDomain.c_str()};
1008 if (BEAST_EXPECT(acctObjsIsSize(resp, expectedAccountObjects)))
1010 auto const& aobjs = resp[jss::result][jss::account_objects];
1012 gotLedgerTypes.
reserve(expectedAccountObjects);
1016 aobjs[i][
"LedgerEntryType"].asString());
1019 BEAST_EXPECT(gotLedgerTypes == expectedLedgerTypes);
1026 params[jss::account] = gw.human();
1027 params[jss::deletion_blockers_only] =
true;
1028 params[jss::type] = jss::escrow;
1029 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1031 if (BEAST_EXPECT(acctObjsIsSize(resp, 1u)))
1033 auto const& aobjs = resp[jss::result][jss::account_objects];
1034 BEAST_EXPECT(aobjs[0u][
"LedgerEntryType"] == jss::Escrow);
1041 auto const objs = resp[jss::result][jss::account_objects];
1042 for (
auto const& obj : resp[jss::result][jss::account_objects])
1044 obj[sfLedgerEntryType.fieldName].asString());
1045 std::sort(typesOut.begin(), typesOut.end());
1049 auto expectObjects =
1052 if (!acctObjsIsSize(resp, types.
size()))
1055 getTypes(resp, typesOut);
1056 return types == typesOut;
1059 AMM amm(env, gw,
XRP(1'000), USD(1'000));
1060 amm.deposit(alice, USD(1));
1063 BEAST_EXPECT(
lines[jss::lines].size() == 3);
1066 acctObjsIsSize(acctObjs(amm.ammAccount(), jss::amm), 1));
1068 auto resp = acctObjs(amm.ammAccount(),
std::nullopt, 2);
1070 getTypes(resp, typesOut);
1076 resp[jss::result][jss::marker].
asString());
1077 getTypes(resp, typesOut);
1082 jss::RippleState.c_str(),
1083 jss::RippleState.c_str(),
1084 jss::RippleState.c_str()}));
1086 resp = acctObjs(amm.ammAccount(), jss::state, 10);
1087 BEAST_EXPECT(expectObjects(
1089 {jss::RippleState.c_str(),
1090 jss::RippleState.c_str(),
1091 jss::RippleState.c_str()}));
1094 acctObjsIsSize(acctObjs(amm.ammAccount(), jss::offer), 0));
1096 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::amm), 0));
1100 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::amendments)));
1101 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::directory)));
1102 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::fee)));
1103 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::hashes)));
1104 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::NegativeUNL)));
1108 for (
int d = 1'000'032; d >= 1'000'000; --d)
1115 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::account), 0));
1274 using namespace jtx;
1280 env.
fund(
XRP(10000), alice, bob, carol);
1282 unsigned const accountObjectSize = 30;
1283 for (
unsigned i = 0; i < accountObjectSize; i++)
1286 for (
unsigned i = 0; i < 10; i++)
1291 unsigned const limit = 11;
1297 params[jss::account] = bob.human();
1298 params[jss::limit] = limit;
1299 params[jss::ledger_index] =
"validated";
1300 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1301 auto& accountObjects = resp[jss::result][jss::account_objects];
1302 marker = resp[jss::result][jss::marker];
1303 BEAST_EXPECT(!resp[jss::result].isMember(jss::error));
1304 BEAST_EXPECT(accountObjects.size() == limit);
1310 params[jss::account] = bob.human();
1311 params[jss::limit] = limit;
1312 params[jss::marker] = marker;
1313 params[jss::ledger_index] =
"validated";
1314 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1315 auto& accountObjects = resp[jss::result][jss::account_objects];
1316 marker = resp[jss::result][jss::marker];
1317 BEAST_EXPECT(!resp[jss::result].isMember(jss::error));
1318 BEAST_EXPECT(accountObjects.size() == limit);
1322 auto testInvalidMarker = [&](
std::string& marker) {
1324 params[jss::account] = bob.human();
1325 params[jss::limit] = limit;
1326 params[jss::ledger_index] = jss::validated;
1327 params[jss::marker] = marker;
1330 return resp[jss::result][jss::error_message] ==
1331 "Invalid field \'marker\'.";
1334 auto const markerStr = marker.
asString();
1335 auto const& idx = markerStr.
find(
',');
1336 auto const dirIndex = markerStr.substr(0, idx);
1337 auto const entryIndex = markerStr.substr(idx + 1);
1342 BEAST_EXPECT(testInvalidMarker(s));
1349 BEAST_EXPECT(testInvalidMarker(s));
1357 BEAST_EXPECT(testInvalidMarker(s));
1365 s = dirIndex +
',' + s;
1366 BEAST_EXPECT(testInvalidMarker(s));
1373 BEAST_EXPECT(testInvalidMarker(s));
1382 params[jss::account] = bob.human();
1383 params[jss::limit] = limit;
1384 params[jss::marker] = s;
1385 params[jss::ledger_index] =
"validated";
1386 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1387 auto& accountObjects = resp[jss::result][jss::account_objects];
1388 BEAST_EXPECT(!resp[jss::result].isMember(jss::error));
1389 BEAST_EXPECT(accountObjects.size() == limit);
1396 BEAST_EXPECT(testInvalidMarker(s));
1403 BEAST_EXPECT(testInvalidMarker(s));
1410 params[jss::account] = bob.human();
1411 params[jss::limit] = limit;
1412 params[jss::marker] = marker;
1413 params[jss::ledger_index] =
"validated";
1414 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1415 auto& accountObjects = resp[jss::result][jss::account_objects];
1416 BEAST_EXPECT(!resp[jss::result].isMember(jss::error));
1418 accountObjects.size() == accountObjectSize - limit * 2);
1419 BEAST_EXPECT(!resp[jss::result].isMember(jss::marker));
1426 params[jss::account] = carol.human();
1427 params[jss::limit] = 10;
1428 params[jss::marker] =
"0," + entryIndex;
1429 params[jss::ledger_index] =
"validated";
1430 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1431 auto& accountObjects = resp[jss::result][jss::account_objects];
1432 BEAST_EXPECT(accountObjects.size() == 0);