diff --git a/src/rpc/handlers/LedgerData.cpp b/src/rpc/handlers/LedgerData.cpp index 251f5e10..228f8b29 100644 --- a/src/rpc/handlers/LedgerData.cpp +++ b/src/rpc/handlers/LedgerData.cpp @@ -41,7 +41,8 @@ std::unordered_map const LedgerDataHandler {JS(state), ripple::ltRIPPLE_STATE}, {JS(ticket), ripple::ltTICKET}, {JS(nft_offer), ripple::ltNFTOKEN_OFFER}, - {JS(nft_page), ripple::ltNFTOKEN_PAGE}}; + {JS(nft_page), ripple::ltNFTOKEN_PAGE}, + {JS(amm), ripple::ltAMM}}; // TODO: should be std::views::keys when clang supports it std::unordered_set const LedgerDataHandler::TYPES_KEYS = [] { diff --git a/unittests/rpc/handlers/LedgerDataTests.cpp b/unittests/rpc/handlers/LedgerDataTests.cpp index ced5c634..b6dd08be 100644 --- a/unittests/rpc/handlers/LedgerDataTests.cpp +++ b/unittests/rpc/handlers/LedgerDataTests.cpp @@ -349,6 +349,68 @@ TEST_F(RPCLedgerDataHandlerTest, TypeFilter) }); } +TEST_F(RPCLedgerDataHandlerTest, TypeFilterAMM) +{ + static auto const ledgerExpected = R"({ + "account_hash":"0000000000000000000000000000000000000000000000000000000000000000", + "close_flags":0, + "close_time":0, + "close_time_resolution":0, + "ledger_hash":"4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652", + "ledger_index":"30", + "parent_close_time":0, + "parent_hash":"0000000000000000000000000000000000000000000000000000000000000000", + "total_coins":"0", + "transaction_hash":"0000000000000000000000000000000000000000000000000000000000000000", + "closed":true + })"; + + auto const rawBackendPtr = dynamic_cast(mockBackendPtr.get()); + ASSERT_NE(rawBackendPtr, nullptr); + mockBackendPtr->updateRange(RANGEMIN); // min + mockBackendPtr->updateRange(RANGEMAX); // max + + EXPECT_CALL(*rawBackendPtr, fetchLedgerBySequence).Times(1); + ON_CALL(*rawBackendPtr, fetchLedgerBySequence(RANGEMAX, _)) + .WillByDefault(Return(CreateLedgerInfo(LEDGERHASH, RANGEMAX))); + + auto limitLine = 5; + + std::vector bbs; + EXPECT_CALL(*rawBackendPtr, doFetchSuccessorKey).Times(limitLine + 1); + ON_CALL(*rawBackendPtr, doFetchSuccessorKey(_, RANGEMAX, _)).WillByDefault(Return(ripple::uint256{INDEX2})); + + while ((limitLine--) != 0) { + auto const line = CreateRippleStateLedgerObject("USD", ACCOUNT2, 10, ACCOUNT, 100, ACCOUNT2, 200, TXNID, 123); + bbs.push_back(line.getSerializer().peekData()); + } + + auto const amm = CreateAMMObject(ACCOUNT, "XRP", ripple::toBase58(ripple::xrpAccount()), "JPY", ACCOUNT2); + bbs.push_back(amm.getSerializer().peekData()); + + ON_CALL(*rawBackendPtr, doFetchLedgerObjects).WillByDefault(Return(bbs)); + EXPECT_CALL(*rawBackendPtr, doFetchLedgerObjects).Times(1); + + runSpawn([&, this](auto yield) { + auto const handler = AnyHandler{LedgerDataHandler{mockBackendPtr}}; + auto const req = json::parse(R"({ + "limit":6, + "type":"amm" + })"); + + auto output = handler.process(req, Context{yield}); + ASSERT_TRUE(output); + EXPECT_TRUE(output->as_object().contains("ledger")); + //"close_time_human" 's format depends on platform, might be sightly different + EXPECT_EQ(output->as_object().at("ledger").as_object().erase("close_time_human"), 1); + EXPECT_EQ(output->as_object().at("ledger"), json::parse(ledgerExpected)); + EXPECT_EQ(output->as_object().at("marker").as_string(), INDEX2); + EXPECT_EQ(output->as_object().at("state").as_array().size(), 1); + EXPECT_EQ(output->as_object().at("ledger_hash").as_string(), LEDGERHASH); + EXPECT_EQ(output->as_object().at("ledger_index").as_uint64(), RANGEMAX); + }); +} + TEST_F(RPCLedgerDataHandlerTest, OutOfOrder) { static auto const ledgerExpected = R"({