fix: Add domain to book_changes (#2229)

Fix: https://github.com/XRPLF/clio/issues/2221
This commit is contained in:
Ayaz Salikhov
2025-06-17 14:22:06 +01:00
committed by GitHub
parent f58c85d203
commit 7584a683dd
4 changed files with 90 additions and 39 deletions

View File

@@ -265,6 +265,9 @@ tag_invoke(boost::json::value_from_tag, boost::json::value& jv, BookChange const
{JS(open), to_string(change.openRate.iou())},
{JS(close), to_string(change.closeRate.iou())},
};
if (change.domain.has_value())
jv.as_object()[JS(domain)] = ripple::to_string(*change.domain);
}
/**

View File

@@ -328,18 +328,21 @@ createMetaDataForBookChange(
std::string_view issueId,
uint32_t transactionIndex,
int finalTakerGets,
int perviousTakerGets,
int previousTakerGets,
int finalTakerPays,
int perviousTakerPays
int previousTakerPays,
std::optional<std::string_view> domain
)
{
ripple::STObject finalFields(ripple::sfFinalFields);
ripple::Issue const issue1 = getIssue(currency, issueId);
finalFields.setFieldAmount(ripple::sfTakerPays, ripple::STAmount(issue1, finalTakerPays));
finalFields.setFieldAmount(ripple::sfTakerGets, ripple::STAmount(finalTakerGets, false));
if (domain.has_value())
finalFields.setFieldH256(ripple::sfDomainID, ripple::uint256{*domain});
ripple::STObject previousFields(ripple::sfPreviousFields);
previousFields.setFieldAmount(ripple::sfTakerPays, ripple::STAmount(issue1, perviousTakerPays));
previousFields.setFieldAmount(ripple::sfTakerGets, ripple::STAmount(perviousTakerGets, false));
previousFields.setFieldAmount(ripple::sfTakerPays, ripple::STAmount(issue1, previousTakerPays));
previousFields.setFieldAmount(ripple::sfTakerGets, ripple::STAmount(previousTakerGets, false));
ripple::STObject metaObj(ripple::sfTransactionMetaData);
ripple::STArray metaArray{1};
ripple::STObject node(ripple::sfModifiedNode);
@@ -484,7 +487,7 @@ createOfferLedgerObject(
std::string_view getsIssueId,
std::string_view paysIssueId,
std::string_view dirId,
std::optional<std::string_view> const& domain
std::optional<std::string_view> domain
)
{
ripple::STObject offer(ripple::sfLedgerEntry);

View File

@@ -182,9 +182,10 @@ createMetaDataForBookChange(
std::string_view issueId,
uint32_t transactionIndex,
int finalTakerGets,
int perviousTakerGets,
int previousTakerGets,
int finalTakerPays,
int perviousTakerPays
int previousTakerPays,
std::optional<std::string_view> domain = std::nullopt
);
/*
@@ -258,7 +259,7 @@ createOfferLedgerObject(
std::string_view getsIssueId,
std::string_view paysIssueId,
std::string_view bookDirId,
std::optional<std::string_view> const& domain = std::nullopt
std::optional<std::string_view> domain = std::nullopt
);
[[nodiscard]] ripple::STObject

View File

@@ -50,6 +50,7 @@ constexpr auto kISSUER = "rK9DrarGKnVEo2nYp5MfVRXRYf5yRX3mwD";
constexpr auto kACCOUNT1 = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn";
constexpr auto kACCOUNT2 = "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun";
constexpr auto kLEDGER_HASH = "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652";
constexpr auto kDOMAIN = "F10D0CC9A0F9A3CBF585B80BE09A186483668FDBDD39AA7E3370F3649CE134E5";
constexpr auto kMAX_SEQ = 30;
constexpr auto kMIN_SEQ = 10;
@@ -79,19 +80,19 @@ generateTestValuesForParametersTest()
return std::vector<BookChangesParamTestCaseBundle>{
BookChangesParamTestCaseBundle{
.testName = "LedgerHashInvalid",
.testJson = R"JSON({"ledger_hash":"1"})JSON",
.testJson = R"JSON({"ledger_hash": "1"})JSON",
.expectedError = "invalidParams",
.expectedErrorMessage = "ledger_hashMalformed"
},
BookChangesParamTestCaseBundle{
.testName = "LedgerHashNotString",
.testJson = R"JSON({"ledger_hash":1})JSON",
.testJson = R"JSON({"ledger_hash": 1})JSON",
.expectedError = "invalidParams",
.expectedErrorMessage = "ledger_hashNotString"
},
BookChangesParamTestCaseBundle{
.testName = "LedgerIndexInvalid",
.testJson = R"JSON({"ledger_index":"a"})JSON",
.testJson = R"JSON({"ledger_index": "a"})JSON",
.expectedError = "invalidParams",
.expectedErrorMessage = "ledgerIndexMalformed"
},
@@ -121,11 +122,11 @@ TEST_P(BookChangesParameterTest, InvalidParams)
TEST_F(RPCBookChangesHandlerTest, LedgerNonExistViaIntSequence)
{
EXPECT_CALL(*backend_, fetchLedgerBySequence).Times(1);
EXPECT_CALL(*backend_, fetchLedgerBySequence);
// return empty ledgerHeader
ON_CALL(*backend_, fetchLedgerBySequence(kMAX_SEQ, _)).WillByDefault(Return(std::optional<ripple::LedgerHeader>{}));
auto static const kINPUT = json::parse(R"JSON({"ledger_index":30})JSON");
static auto const kINPUT = json::parse(R"JSON({"ledger_index": 30})JSON");
auto const handler = AnyHandler{BookChangesHandler{backend_}};
runSpawn([&](auto yield) {
auto const output = handler.process(kINPUT, Context{yield});
@@ -138,11 +139,11 @@ TEST_F(RPCBookChangesHandlerTest, LedgerNonExistViaIntSequence)
TEST_F(RPCBookChangesHandlerTest, LedgerNonExistViaStringSequence)
{
EXPECT_CALL(*backend_, fetchLedgerBySequence).Times(1);
EXPECT_CALL(*backend_, fetchLedgerBySequence);
// return empty ledgerHeader
ON_CALL(*backend_, fetchLedgerBySequence(kMAX_SEQ, _)).WillByDefault(Return(std::nullopt));
auto static const kINPUT = json::parse(R"JSON({"ledger_index":"30"})JSON");
static auto const kINPUT = json::parse(R"JSON({"ledger_index": "30"})JSON");
auto const handler = AnyHandler{BookChangesHandler{backend_}};
runSpawn([&](auto yield) {
auto const output = handler.process(kINPUT, Context{yield});
@@ -155,14 +156,13 @@ TEST_F(RPCBookChangesHandlerTest, LedgerNonExistViaStringSequence)
TEST_F(RPCBookChangesHandlerTest, LedgerNonExistViaHash)
{
EXPECT_CALL(*backend_, fetchLedgerByHash).Times(1);
// return empty ledgerHeader
ON_CALL(*backend_, fetchLedgerByHash(ripple::uint256{kLEDGER_HASH}, _))
.WillByDefault(Return(std::optional<ripple::LedgerHeader>{}));
EXPECT_CALL(*backend_, fetchLedgerByHash(ripple::uint256{kLEDGER_HASH}, _))
.WillOnce(Return(std::optional<ripple::LedgerHeader>{}));
auto static const kINPUT = json::parse(fmt::format(
static auto const kINPUT = json::parse(fmt::format(
R"JSON({{
"ledger_hash":"{}"
"ledger_hash": "{}"
}})JSON",
kLEDGER_HASH
));
@@ -180,28 +180,27 @@ TEST_F(RPCBookChangesHandlerTest, NormalPath)
{
static constexpr auto kEXPECTED_OUT =
R"JSON({
"type":"bookChanges",
"ledger_hash":"4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652",
"ledger_index":30,
"ledger_time":0,
"validated":true,
"changes":[
"type": "bookChanges",
"ledger_hash": "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652",
"ledger_index": 30,
"ledger_time": 0,
"validated": true,
"changes": [
{
"currency_a":"XRP_drops",
"currency_b":"rK9DrarGKnVEo2nYp5MfVRXRYf5yRX3mwD/0158415500000000C1F76FF6ECB0BAC600000000",
"volume_a":"2",
"volume_b":"2",
"high":"-1",
"low":"-1",
"open":"-1",
"close":"-1"
"currency_a": "XRP_drops",
"currency_b": "rK9DrarGKnVEo2nYp5MfVRXRYf5yRX3mwD/0158415500000000C1F76FF6ECB0BAC600000000",
"volume_a": "2",
"volume_b": "2",
"high": "-1",
"low": "-1",
"open": "-1",
"close": "-1"
}
]
})JSON";
EXPECT_CALL(*backend_, fetchLedgerBySequence).Times(1);
ON_CALL(*backend_, fetchLedgerBySequence(kMAX_SEQ, _))
.WillByDefault(Return(createLedgerHeader(kLEDGER_HASH, kMAX_SEQ)));
EXPECT_CALL(*backend_, fetchLedgerBySequence(kMAX_SEQ, _))
.WillOnce(Return(createLedgerHeader(kLEDGER_HASH, kMAX_SEQ)));
auto transactions = std::vector<TransactionAndMetadata>{};
auto trans1 = TransactionAndMetadata();
@@ -212,8 +211,53 @@ TEST_F(RPCBookChangesHandlerTest, NormalPath)
trans1.metadata = metaObj.getSerializer().peekData();
transactions.push_back(trans1);
EXPECT_CALL(*backend_, fetchAllTransactionsInLedger).Times(1);
ON_CALL(*backend_, fetchAllTransactionsInLedger(kMAX_SEQ, _)).WillByDefault(Return(transactions));
EXPECT_CALL(*backend_, fetchAllTransactionsInLedger(kMAX_SEQ, _)).WillOnce(Return(transactions));
auto const handler = AnyHandler{BookChangesHandler{backend_}};
runSpawn([&](auto yield) {
auto const output = handler.process(json::parse("{}"), Context{yield});
ASSERT_TRUE(output);
EXPECT_EQ(*output.result, json::parse(kEXPECTED_OUT));
});
}
TEST_F(RPCBookChangesHandlerTest, NormalPathWithDomain)
{
static constexpr auto kEXPECTED_OUT =
R"JSON({
"type": "bookChanges",
"ledger_hash": "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A652",
"ledger_index": 30,
"ledger_time": 0,
"validated": true,
"changes": [
{
"currency_a": "XRP_drops",
"currency_b": "rK9DrarGKnVEo2nYp5MfVRXRYf5yRX3mwD/0158415500000000C1F76FF6ECB0BAC600000000",
"volume_a": "2",
"volume_b": "2",
"high": "-1",
"low": "-1",
"open": "-1",
"close": "-1",
"domain": "F10D0CC9A0F9A3CBF585B80BE09A186483668FDBDD39AA7E3370F3649CE134E5"
}
]
})JSON";
EXPECT_CALL(*backend_, fetchLedgerBySequence(kMAX_SEQ, _))
.WillOnce(Return(createLedgerHeader(kLEDGER_HASH, kMAX_SEQ)));
auto transactions = std::vector<TransactionAndMetadata>{};
auto trans1 = TransactionAndMetadata();
ripple::STObject const obj = createPaymentTransactionObject(kACCOUNT1, kACCOUNT2, 1, 1, 32);
trans1.transaction = obj.getSerializer().peekData();
trans1.ledgerSequence = 32;
ripple::STObject const metaObj = createMetaDataForBookChange(kCURRENCY, kISSUER, 22, 1, 3, 3, 1, kDOMAIN);
trans1.metadata = metaObj.getSerializer().peekData();
transactions.push_back(trans1);
EXPECT_CALL(*backend_, fetchAllTransactionsInLedger(kMAX_SEQ, _)).WillOnce(Return(transactions));
auto const handler = AnyHandler{BookChangesHandler{backend_}};
runSpawn([&](auto yield) {