352 testcase(
"unsteppedThenSteppedWithNFTs");
361 auto const USD1 = gw1[
"USD"];
362 auto const USD2 = gw2[
"USD"];
364 env.
fund(
XRP(1000), gw1, gw2, bob);
371 params[jss::account] = bob.human();
372 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
373 BEAST_EXPECT(!resp.isMember(jss::marker));
374 BEAST_EXPECT(resp[jss::result][jss::account_objects].size() == 0);
377 params[jss::limit] = 1;
378 resp = env.
rpc(
"json",
"account_objects",
to_string(params));
379 BEAST_EXPECT(!resp.isMember(jss::marker));
380 BEAST_EXPECT(resp[jss::result][jss::account_objects].size() == 0);
392 params[jss::account] = bob.human();
393 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
394 BEAST_EXPECT(!resp.isMember(jss::marker));
396 unpaged = resp[jss::result][jss::account_objects];
397 BEAST_EXPECT(unpaged.
size() == 1);
402 params[jss::account] = bob.human();
403 params[jss::type] = jss::nft_page;
404 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
405 BEAST_EXPECT(!resp.isMember(jss::marker));
406 Json::Value& aobjs = resp[jss::result][jss::account_objects];
407 BEAST_EXPECT(aobjs.
size() == 1);
409 aobjs[0u][sfLedgerEntryType.jsonName] == jss::NFTokenPage);
410 BEAST_EXPECT(aobjs[0u][sfNFTokens.jsonName].
size() == 1);
415 params[jss::account] = bob.human();
416 params[jss::limit] = 1;
420 Json::Value& aobjs = resp[jss::result][jss::account_objects];
421 BEAST_EXPECT(aobjs.
size() == 1);
422 auto& aobj = aobjs[0U];
423 BEAST_EXPECT(!resp[jss::result].isMember(jss::limit));
424 BEAST_EXPECT(!resp[jss::result].isMember(jss::marker));
426 BEAST_EXPECT(aobj == unpaged[0u]);
430 env.
trust(USD1(1000), bob);
431 env.
trust(USD2(1000), bob);
433 env(
pay(gw1, bob, USD1(1000)));
434 env(
pay(gw2, bob, USD2(1000)));
443 params[jss::account] = bob.human();
444 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
445 BEAST_EXPECT(!resp.isMember(jss::marker));
447 unpaged = resp[jss::result][jss::account_objects];
448 BEAST_EXPECT(unpaged.
size() == 5);
453 params[jss::account] = bob.human();
454 params[jss::type] = jss::nft_page;
455 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
456 BEAST_EXPECT(!resp.isMember(jss::marker));
457 Json::Value& aobjs = resp[jss::result][jss::account_objects];
458 BEAST_EXPECT(aobjs.
size() == 1);
460 aobjs[0u][sfLedgerEntryType.jsonName] == jss::NFTokenPage);
461 BEAST_EXPECT(aobjs[0u][sfNFTokens.jsonName].
size() == 1);
466 params[jss::account] = bob.human();
467 params[jss::limit] = 1;
468 for (
int i = 0; i < 5; ++i)
472 Json::Value& aobjs = resp[jss::result][jss::account_objects];
473 BEAST_EXPECT(aobjs.
size() == 1);
474 auto& aobj = aobjs[0U];
477 BEAST_EXPECT(resp[jss::result][jss::limit] == 1);
478 BEAST_EXPECT(resp[jss::result].isMember(jss::marker));
482 BEAST_EXPECT(!resp[jss::result].isMember(jss::limit));
483 BEAST_EXPECT(!resp[jss::result].isMember(jss::marker));
486 BEAST_EXPECT(aobj == unpaged[i]);
488 params[jss::marker] = resp[jss::result][jss::marker];
493 for (
int i = 0; i < 32; ++i)
501 params[jss::account] = bob.human();
502 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
503 BEAST_EXPECT(!resp.isMember(jss::marker));
505 unpaged = resp[jss::result][jss::account_objects];
506 BEAST_EXPECT(unpaged.
size() == 6);
511 params[jss::account] = bob.human();
512 params[jss::type] = jss::nft_page;
513 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
514 BEAST_EXPECT(!resp.isMember(jss::marker));
515 Json::Value& aobjs = resp[jss::result][jss::account_objects];
516 BEAST_EXPECT(aobjs.
size() == 2);
521 params[jss::account] = bob.human();
522 params[jss::limit] = 1;
523 for (
int i = 0; i < 6; ++i)
527 Json::Value& aobjs = resp[jss::result][jss::account_objects];
528 BEAST_EXPECT(aobjs.
size() == 1);
529 auto& aobj = aobjs[0U];
532 BEAST_EXPECT(resp[jss::result][jss::limit] == 1);
533 BEAST_EXPECT(resp[jss::result].isMember(jss::marker));
537 BEAST_EXPECT(!resp[jss::result].isMember(jss::limit));
538 BEAST_EXPECT(!resp[jss::result].isMember(jss::marker));
541 BEAST_EXPECT(aobj == unpaged[i]);
543 params[jss::marker] = resp[jss::result][jss::marker];
559 auto const USD = gw[
"USD"];
562 featurePermissionedDomains;
563 Env env(*
this, features);
566 auto acctObjs = [&env](
574 params[jss::type] = *type;
576 params[jss::limit] = *limit;
578 params[jss::marker] = *marker;
579 params[jss::ledger_index] =
"validated";
580 return env.
rpc(
"json",
"account_objects",
to_string(params));
584 auto acctObjsIsSize = [](
Json::Value const& resp,
unsigned size) {
585 return resp[jss::result][jss::account_objects].
isArray() &&
586 (resp[jss::result][jss::account_objects].
size() == size);
590 auto acctObjsTypeIsInvalid = [](
Json::Value const& resp) {
591 return resp[jss::result].
isMember(jss::error) &&
592 resp[jss::result][jss::error_message] ==
593 "Invalid field \'type\'.";
596 env.
fund(
XRP(10000), gw, alice);
601 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::account), 0));
602 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::check), 0));
603 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::deposit_preauth), 0));
604 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::escrow), 0));
605 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::nft_page), 0));
606 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::offer), 0));
607 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::payment_channel), 0));
608 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::signer_list), 0));
609 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::state), 0));
610 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::ticket), 0));
611 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::amm), 0));
612 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::did), 0));
613 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::permissioned_domain), 0));
616 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::amendments)));
617 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::directory)));
618 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::fee)));
619 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::hashes)));
620 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::NegativeUNL)));
628 Json::Value const resp = acctObjs(gw, jss::nft_page);
629 BEAST_EXPECT(acctObjsIsSize(resp, 1));
631 auto const& nftPage = resp[jss::result][jss::account_objects][0u];
632 BEAST_EXPECT(nftPage[sfNFTokens.jsonName].size() == 1);
634 nftPage[sfNFTokens.jsonName][0u][sfNFToken.jsonName]
635 [sfNFTokenID.jsonName] ==
to_string(nftID));
639 env.
trust(USD(1000), alice);
641 env(
pay(gw, alice, USD(5)));
646 BEAST_EXPECT(acctObjsIsSize(resp, 1));
648 auto const& state = resp[jss::result][jss::account_objects][0u];
649 BEAST_EXPECT(state[sfBalance.jsonName][jss::value].asInt() == -5);
651 state[sfHighLimit.jsonName][jss::value].asUInt() == 1000);
659 BEAST_EXPECT(acctObjsIsSize(resp, 1));
661 auto const& check = resp[jss::result][jss::account_objects][0u];
662 BEAST_EXPECT(check[sfAccount.jsonName] == gw.human());
663 BEAST_EXPECT(check[sfDestination.jsonName] == alice.human());
664 BEAST_EXPECT(check[sfSendMax.jsonName][jss::value].asUInt() == 10);
671 Json::Value const resp = acctObjs(gw, jss::deposit_preauth);
672 BEAST_EXPECT(acctObjsIsSize(resp, 1));
674 auto const& preauth = resp[jss::result][jss::account_objects][0u];
675 BEAST_EXPECT(preauth[sfAccount.jsonName] == gw.human());
676 BEAST_EXPECT(preauth[sfAuthorize.jsonName] == alice.human());
681 jvEscrow[jss::TransactionType] = jss::EscrowCreate;
682 jvEscrow[jss::Account] = gw.human();
683 jvEscrow[jss::Destination] = gw.human();
685 jvEscrow[sfFinishAfter.jsonName] =
692 Json::Value const resp = acctObjs(gw, jss::escrow);
693 BEAST_EXPECT(acctObjsIsSize(resp, 1));
695 auto const& escrow = resp[jss::result][jss::account_objects][0u];
696 BEAST_EXPECT(escrow[sfAccount.jsonName] == gw.human());
697 BEAST_EXPECT(escrow[sfDestination.jsonName] == gw.human());
698 BEAST_EXPECT(escrow[sfAmount.jsonName].asUInt() == 100'000'000);
711 Json::Value const resp = acctObjs(gw, jss::permissioned_domain);
712 BEAST_EXPECT(acctObjsIsSize(resp, 1));
714 auto const& permissionedDomain =
715 resp[jss::result][jss::account_objects][0u];
717 permissionedDomain.isMember(jss::Owner) &&
718 (permissionedDomain[jss::Owner] == gw.human()));
719 bool const check1 = BEAST_EXPECT(
720 permissionedDomain.isMember(jss::AcceptedCredentials) &&
721 permissionedDomain[jss::AcceptedCredentials].isArray() &&
722 (permissionedDomain[jss::AcceptedCredentials].size() == 1) &&
723 (permissionedDomain[jss::AcceptedCredentials][0u].isMember(
729 permissionedDomain[jss::AcceptedCredentials][0u]
735 credential.isMember(sfCredentialType.jsonName) &&
737 strHex(credentialType1)));
747 auto scEnvAcctObjs = [&](
Account const& acct,
char const* type) {
749 params[jss::account] = acct.
human();
750 params[jss::type] = type;
751 params[jss::ledger_index] =
"validated";
752 return scEnv.
rpc(
"json",
"account_objects",
to_string(params));
758 BEAST_EXPECT(acctObjsIsSize(resp, 1));
759 auto const& acct_bridge =
760 resp[jss::result][jss::account_objects][0u];
764 acct_bridge[sfLedgerEntryType.getJsonName()] ==
"Bridge");
766 acct_bridge[sfXChainClaimID.getJsonName()].asUInt() == 0);
768 acct_bridge[sfXChainAccountClaimCount.getJsonName()].asUInt() ==
771 acct_bridge[sfXChainAccountCreateCount.getJsonName()]
774 acct_bridge[sfMinAccountCreateAmount.getJsonName()].asUInt() ==
777 acct_bridge[sfSignatureReward.getJsonName()].asUInt() ==
779 BEAST_EXPECT(acct_bridge[sfXChainBridge.getJsonName()] == x.
jvb);
794 auto scEnvAcctObjs = [&](
Account const& acct,
char const* type) {
796 params[jss::account] = acct.
human();
797 params[jss::type] = type;
798 params[jss::ledger_index] =
"validated";
799 return scEnv.
rpc(
"json",
"account_objects",
to_string(params));
805 scEnvAcctObjs(x.
scAlice, jss::xchain_owned_claim_id);
806 BEAST_EXPECT(acctObjsIsSize(resp, 1));
808 auto const& xchain_seq =
809 resp[jss::result][jss::account_objects][0u];
813 xchain_seq[sfXChainClaimID.getJsonName()].asUInt() == 1);
818 scEnvAcctObjs(x.
scBob, jss::xchain_owned_claim_id);
819 BEAST_EXPECT(acctObjsIsSize(resp, 1));
821 auto const& xchain_seq =
822 resp[jss::result][jss::account_objects][0u];
823 BEAST_EXPECT(xchain_seq[sfAccount.jsonName] == x.
scBob.
human());
825 xchain_seq[sfXChainClaimID.getJsonName()].asUInt() == 2);
832 auto const amt =
XRP(1000);
851 auto scEnvAcctObjs = [&](
Account const& acct,
char const* type) {
853 params[jss::account] = acct.
human();
854 params[jss::type] = type;
855 params[jss::ledger_index] =
"validated";
856 return scEnv.
rpc(
"json",
"account_objects",
to_string(params));
863 BEAST_EXPECT(acctObjsIsSize(resp, 1));
865 auto const& xchain_create_account_claim_id =
866 resp[jss::result][jss::account_objects][0u];
868 xchain_create_account_claim_id[sfAccount.jsonName] ==
871 xchain_create_account_claim_id[sfXChainAccountCreateCount
883 BEAST_EXPECT(acctObjsIsSize(resp, 1));
885 auto const&
offer = resp[jss::result][jss::account_objects][0u];
886 BEAST_EXPECT(
offer[sfAccount.jsonName] == gw.human());
887 BEAST_EXPECT(
offer[sfTakerGets.jsonName].
asUInt() == 14'000'000);
888 BEAST_EXPECT(
offer[sfTakerPays.jsonName][jss::value].
asUInt() == 7);
894 jvPayChan[jss::TransactionType] = jss::PaymentChannelCreate;
895 jvPayChan[jss::Account] = gw.human();
896 jvPayChan[jss::Destination] = alice.human();
897 jvPayChan[jss::Amount] =
899 jvPayChan[sfSettleDelay.jsonName] = 24 * 60 * 60;
900 jvPayChan[sfPublicKey.jsonName] =
strHex(gw.pk().slice());
906 Json::Value const resp = acctObjs(gw, jss::payment_channel);
907 BEAST_EXPECT(acctObjsIsSize(resp, 1));
909 auto const& payChan = resp[jss::result][jss::account_objects][0u];
910 BEAST_EXPECT(payChan[sfAccount.jsonName] == gw.human());
911 BEAST_EXPECT(payChan[sfAmount.jsonName].asUInt() == 300'000'000);
913 payChan[sfSettleDelay.jsonName].asUInt() == 24 * 60 * 60);
919 jvDID[jss::TransactionType] = jss::DIDSet;
920 jvDID[jss::Account] = gw.human();
928 BEAST_EXPECT(acctObjsIsSize(resp, 1));
930 auto const& did = resp[jss::result][jss::account_objects][0u];
931 BEAST_EXPECT(did[sfAccount.jsonName] == gw.human());
939 Json::Value const resp = acctObjs(gw, jss::signer_list);
940 BEAST_EXPECT(acctObjsIsSize(resp, 1));
942 auto const& signerList =
943 resp[jss::result][jss::account_objects][0u];
944 BEAST_EXPECT(signerList[sfSignerQuorum.jsonName] == 6);
945 auto const& entry = signerList[sfSignerEntries.jsonName][0u]
946 [sfSignerEntry.jsonName];
947 BEAST_EXPECT(entry[sfAccount.jsonName] == alice.human());
948 BEAST_EXPECT(entry[sfSignerWeight.jsonName].
asUInt() == 7);
952 auto const seq = env.
seq(gw);
958 Json::Value const resp = acctObjs(gw, jss::ticket);
959 BEAST_EXPECT(acctObjsIsSize(resp, 1));
961 auto const& ticket = resp[jss::result][jss::account_objects][0u];
962 BEAST_EXPECT(ticket[sfAccount.jsonName] == gw.human());
963 BEAST_EXPECT(ticket[sfLedgerEntryType.jsonName] == jss::Ticket);
964 BEAST_EXPECT(ticket[sfTicketSequence.jsonName].asUInt() ==
seq + 1);
970 params[jss::account] = gw.human();
971 params[jss::deletion_blockers_only] =
true;
972 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
978 jss::NFTokenPage.c_str(),
979 jss::RippleState.c_str(),
980 jss::PayChannel.c_str(),
981 jss::PermissionedDomain.c_str()};
989 if (BEAST_EXPECT(acctObjsIsSize(resp, expectedAccountObjects)))
991 auto const& aobjs = resp[jss::result][jss::account_objects];
993 gotLedgerTypes.
reserve(expectedAccountObjects);
997 aobjs[i][
"LedgerEntryType"].asString());
1000 BEAST_EXPECT(gotLedgerTypes == expectedLedgerTypes);
1007 params[jss::account] = gw.human();
1008 params[jss::deletion_blockers_only] =
true;
1009 params[jss::type] = jss::escrow;
1010 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1012 if (BEAST_EXPECT(acctObjsIsSize(resp, 1u)))
1014 auto const& aobjs = resp[jss::result][jss::account_objects];
1015 BEAST_EXPECT(aobjs[0u][
"LedgerEntryType"] == jss::Escrow);
1022 auto const objs = resp[jss::result][jss::account_objects];
1023 for (
auto const& obj : resp[jss::result][jss::account_objects])
1025 obj[sfLedgerEntryType.fieldName].asString());
1026 std::sort(typesOut.begin(), typesOut.end());
1030 auto expectObjects =
1033 if (!acctObjsIsSize(resp, types.
size()))
1036 getTypes(resp, typesOut);
1037 return types == typesOut;
1040 AMM amm(env, gw,
XRP(1'000), USD(1'000));
1041 amm.deposit(alice, USD(1));
1044 BEAST_EXPECT(
lines[jss::lines].size() == 3);
1047 acctObjsIsSize(acctObjs(amm.ammAccount(), jss::amm), 1));
1049 auto resp = acctObjs(amm.ammAccount(),
std::nullopt, 2);
1051 getTypes(resp, typesOut);
1057 resp[jss::result][jss::marker].
asString());
1058 getTypes(resp, typesOut);
1063 jss::RippleState.c_str(),
1064 jss::RippleState.c_str(),
1065 jss::RippleState.c_str()}));
1067 resp = acctObjs(amm.ammAccount(), jss::state, 10);
1068 BEAST_EXPECT(expectObjects(
1070 {jss::RippleState.c_str(),
1071 jss::RippleState.c_str(),
1072 jss::RippleState.c_str()}));
1075 acctObjsIsSize(acctObjs(amm.ammAccount(), jss::offer), 0));
1077 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::amm), 0));
1081 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::amendments)));
1082 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::directory)));
1083 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::fee)));
1084 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::hashes)));
1085 BEAST_EXPECT(acctObjsTypeIsInvalid(acctObjs(gw, jss::NegativeUNL)));
1089 for (
int d = 1'000'032; d >= 1'000'000; --d)
1096 BEAST_EXPECT(acctObjsIsSize(acctObjs(gw, jss::account), 0));
1255 using namespace jtx;
1261 env.
fund(
XRP(10000), alice, bob, carol);
1263 unsigned const accountObjectSize = 30;
1264 for (
unsigned i = 0; i < accountObjectSize; i++)
1267 for (
unsigned i = 0; i < 10; i++)
1272 unsigned const limit = 11;
1278 params[jss::account] = bob.human();
1279 params[jss::limit] = limit;
1280 params[jss::ledger_index] =
"validated";
1281 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1282 auto& accountObjects = resp[jss::result][jss::account_objects];
1283 marker = resp[jss::result][jss::marker];
1284 BEAST_EXPECT(!resp[jss::result].isMember(jss::error));
1285 BEAST_EXPECT(accountObjects.size() == limit);
1291 params[jss::account] = bob.human();
1292 params[jss::limit] = limit;
1293 params[jss::marker] = marker;
1294 params[jss::ledger_index] =
"validated";
1295 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1296 auto& accountObjects = resp[jss::result][jss::account_objects];
1297 marker = resp[jss::result][jss::marker];
1298 BEAST_EXPECT(!resp[jss::result].isMember(jss::error));
1299 BEAST_EXPECT(accountObjects.size() == limit);
1303 auto testInvalidMarker = [&](
std::string& marker) {
1305 params[jss::account] = bob.human();
1306 params[jss::limit] = limit;
1307 params[jss::ledger_index] = jss::validated;
1308 params[jss::marker] = marker;
1311 return resp[jss::result][jss::error_message] ==
1312 "Invalid field \'marker\'.";
1315 auto const markerStr = marker.
asString();
1316 auto const& idx = markerStr.
find(
',');
1317 auto const dirIndex = markerStr.substr(0, idx);
1318 auto const entryIndex = markerStr.substr(idx + 1);
1323 BEAST_EXPECT(testInvalidMarker(s));
1330 BEAST_EXPECT(testInvalidMarker(s));
1338 BEAST_EXPECT(testInvalidMarker(s));
1346 s = dirIndex +
',' + s;
1347 BEAST_EXPECT(testInvalidMarker(s));
1354 BEAST_EXPECT(testInvalidMarker(s));
1363 params[jss::account] = bob.human();
1364 params[jss::limit] = limit;
1365 params[jss::marker] = s;
1366 params[jss::ledger_index] =
"validated";
1367 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1368 auto& accountObjects = resp[jss::result][jss::account_objects];
1369 BEAST_EXPECT(!resp[jss::result].isMember(jss::error));
1370 BEAST_EXPECT(accountObjects.size() == limit);
1377 BEAST_EXPECT(testInvalidMarker(s));
1384 BEAST_EXPECT(testInvalidMarker(s));
1391 params[jss::account] = bob.human();
1392 params[jss::limit] = limit;
1393 params[jss::marker] = marker;
1394 params[jss::ledger_index] =
"validated";
1395 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1396 auto& accountObjects = resp[jss::result][jss::account_objects];
1397 BEAST_EXPECT(!resp[jss::result].isMember(jss::error));
1399 accountObjects.size() == accountObjectSize - limit * 2);
1400 BEAST_EXPECT(!resp[jss::result].isMember(jss::marker));
1407 params[jss::account] = carol.human();
1408 params[jss::limit] = 10;
1409 params[jss::marker] =
"0," + entryIndex;
1410 params[jss::ledger_index] =
"validated";
1411 auto resp = env.
rpc(
"json",
"account_objects",
to_string(params));
1412 auto& accountObjects = resp[jss::result][jss::account_objects];
1413 BEAST_EXPECT(accountObjects.size() == 0);