diff --git a/src/rpc/handlers/AccountObjects.cpp b/src/rpc/handlers/AccountObjects.cpp index 9c21c4d41..c7e43280e 100644 --- a/src/rpc/handlers/AccountObjects.cpp +++ b/src/rpc/handlers/AccountObjects.cpp @@ -115,6 +115,9 @@ AccountObjectsHandler::process(AccountObjectsHandler::Input const& input, Contex return true; }; + auto const nftIncluded = + not typeFilter or std::ranges::contains(*typeFilter, xrpl::ltNFTOKEN_PAGE); + auto const expectedNext = traverseOwnedNodes( *sharedPtrBackend_, accountID, @@ -123,7 +126,7 @@ AccountObjectsHandler::process(AccountObjectsHandler::Input const& input, Contex input.marker, ctx.yield, addToResponse, - true + nftIncluded ); if (not expectedNext.has_value()) diff --git a/tests/unit/rpc/handlers/AccountObjectsTests.cpp b/tests/unit/rpc/handlers/AccountObjectsTests.cpp index c011efe67..3c2b9c7d1 100644 --- a/tests/unit/rpc/handlers/AccountObjectsTests.cpp +++ b/tests/unit/rpc/handlers/AccountObjectsTests.cpp @@ -564,9 +564,25 @@ TEST_F(RPCAccountObjectsHandlerTest, TypeFilter) EXPECT_CALL(*backend_, doFetchLedgerObject(ownerDirKk, 30, _)) .WillOnce(Return(ownerDir.getSerializer().peekData())); - // nft null auto const nftMaxKK = xrpl::keylet::nftokenPageMax(account).key; - EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).WillOnce(Return(std::nullopt)); + auto current = nftMaxKK; + std::string first{kIndex1}; + std::ranges::sort(first); + for (auto i = 0; i < 10; i++) { + std::ranges::next_permutation(first); + auto const previous = + xrpl::keylet::nftokenPage( + xrpl::keylet::nftokenPageMin(account), xrpl::uint256{first.c_str()} + ) + .key; + auto const nftPage = createNftTokenPage( + std::vector{std::make_pair(kTokenId, "www.ok.com")}, previous + ); + ON_CALL(*backend_, doFetchLedgerObject(current, 30, _)) + .WillByDefault(Return(nftPage.getSerializer().peekData())); + current = previous; + } + EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).Times(0); std::vector bbs; // put 1 state and 1 offer @@ -592,7 +608,8 @@ TEST_F(RPCAccountObjectsHandlerTest, TypeFilter) fmt::format( R"JSON({{ "account": "{}", - "type": "offer" + "type": "offer", + "limit": 10 }})JSON", kAccount ) @@ -602,7 +619,11 @@ TEST_F(RPCAccountObjectsHandlerTest, TypeFilter) runSpawn([&](auto yield) { auto const output = handler.process(kInput, Context{yield}); ASSERT_TRUE(output); - EXPECT_EQ(output.result->as_object().at("account_objects").as_array().size(), 1); + auto const& result = output.result->as_object(); + auto const& objects = result.at("account_objects").as_array(); + ASSERT_EQ(objects.size(), 1); + EXPECT_EQ(objects.at(0).as_object().at("LedgerEntryType").as_string(), "Offer"); + EXPECT_FALSE(result.contains("marker")); }); } @@ -622,9 +643,8 @@ TEST_F(RPCAccountObjectsHandlerTest, TypeFilterAmmType) EXPECT_CALL(*backend_, doFetchLedgerObject(ownerDirKk, 30, _)) .WillOnce(Return(ownerDir.getSerializer().peekData())); - // nft null auto const nftMaxKK = xrpl::keylet::nftokenPageMax(account).key; - EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).WillOnce(Return(std::nullopt)); + EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).Times(0); std::vector bbs; // put 1 state and 1 amm @@ -675,9 +695,8 @@ TEST_F(RPCAccountObjectsHandlerTest, TypeFilterReturnEmpty) EXPECT_CALL(*backend_, doFetchLedgerObject(ownerDirKk, 30, _)) .WillOnce(Return(ownerDir.getSerializer().peekData())); - // nft null auto const nftMaxKK = xrpl::keylet::nftokenPageMax(account).key; - EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).WillOnce(Return(std::nullopt)); + EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).Times(0); std::vector bbs; auto const line1 = createRippleStateLedgerObject( @@ -794,9 +813,8 @@ TEST_F(RPCAccountObjectsHandlerTest, DeletionBlockersOnlyFilterWithTypeFilter) EXPECT_CALL(*backend_, doFetchLedgerObject(ownerDirKk, 30, _)) .WillOnce(Return(ownerDir.getSerializer().peekData())); - // nft null auto const nftMaxKK = xrpl::keylet::nftokenPageMax(account).key; - EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).WillOnce(Return(std::nullopt)); + EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).Times(0); auto const line = createRippleStateLedgerObject( "USD", kIssuer, 100, kAccount, 10, kAccount2, 20, kTxnId, 123, 0 @@ -912,9 +930,8 @@ TEST_F( auto const ownerDirKk = xrpl::keylet::ownerDir(account).key; EXPECT_CALL(*backend_, doFetchLedgerObject(ownerDirKk, 30, _)) .WillOnce(Return(ownerDir.getSerializer().peekData())); - // nft null auto const nftMaxKK = xrpl::keylet::nftokenPageMax(account).key; - EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).WillOnce(Return(std::nullopt)); + EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).Times(0); auto const offer1 = createOfferLedgerObject( kAccount, @@ -2018,9 +2035,8 @@ TEST_F(RPCAccountObjectsHandlerTest, TypeFilterMPTIssuanceType) EXPECT_CALL(*backend_, doFetchLedgerObject(ownerDirKk, 30, _)) .WillOnce(Return(ownerDir.getSerializer().peekData())); - // nft null auto const nftMaxKK = xrpl::keylet::nftokenPageMax(account).key; - EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).WillOnce(Return(std::nullopt)); + EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).Times(0); std::vector bbs; // put 1 mpt issuance @@ -2070,9 +2086,8 @@ TEST_F(RPCAccountObjectsHandlerTest, TypeFilterMPTokenType) EXPECT_CALL(*backend_, doFetchLedgerObject(ownerDirKk, 30, _)) .WillOnce(Return(ownerDir.getSerializer().peekData())); - // nft null auto const nftMaxKK = xrpl::keylet::nftokenPageMax(account).key; - EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).WillOnce(Return(std::nullopt)); + EXPECT_CALL(*backend_, doFetchLedgerObject(nftMaxKK, 30, _)).Times(0); std::vector bbs; // put 1 mpt issuance