fix: Serialize MPToken UInt64 amounts as base-10 strings (#3139)

This commit is contained in:
Chenna Keshava B S
2026-07-22 05:31:21 -07:00
committed by GitHub
parent c073c4dfd3
commit 30f8a227b1
4 changed files with 233 additions and 41 deletions

View File

@@ -17,6 +17,7 @@
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/LedgerHeader.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STInteger.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/jss.h>
@@ -236,11 +237,23 @@ tag_invoke(
}
};
// UInt64 amount fields must be serialized as base-10 strings (matching rippled's
// STUInt64::getJson) so that JSON parsers using IEEE-754 doubles do not silently lose
// precision for values greater than 2^53.
auto const setUint64IfPresent =
[&](boost::json::string_view field, xrpl::SField const& sField, auto const& value) {
if (value.has_value()) {
obj[field] = toBoostJson(
xrpl::STUInt64{sField, *value}.getJson(xrpl::JsonOptions::Values::None)
);
}
};
setIfPresent("transfer_fee", issuance.transferFee);
setIfPresent("asset_scale", issuance.assetScale);
setIfPresent("maximum_amount", issuance.maximumAmount);
setIfPresent("outstanding_amount", issuance.outstandingAmount);
setIfPresent("locked_amount", issuance.lockedAmount);
setUint64IfPresent("maximum_amount", xrpl::sfMaximumAmount, issuance.maximumAmount);
setUint64IfPresent("outstanding_amount", xrpl::sfOutstandingAmount, issuance.outstandingAmount);
setUint64IfPresent("locked_amount", xrpl::sfLockedAmount, issuance.lockedAmount);
setIfPresent("mptoken_metadata", issuance.mptokenMetadata);
setIfPresent("domain_id", issuance.domainID);

View File

@@ -18,6 +18,7 @@
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/LedgerHeader.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STInteger.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/jss.h>
@@ -176,20 +177,29 @@ tag_invoke(
AccountMPTokensHandler::MPTokenResponse const& mptoken
)
{
// UInt64 amount fields must be serialized as base-10 strings (matching rippled's
// STUInt64::getJson) so that JSON parsers using IEEE-754 doubles do not silently lose
// precision for values greater than 2^53.
auto const uint64ToString = [](xrpl::SField const& field, std::uint64_t value) {
return toBoostJson(xrpl::STUInt64{field, value}.getJson(xrpl::JsonOptions::Values::None));
};
auto obj = boost::json::object{
{"mpt_id", mptoken.mpTokenId},
{JS(account), mptoken.account},
{JS(mpt_issuance_id), mptoken.mpTokenIssuanceId},
{JS(mpt_amount), mptoken.mptAmount},
{JS(mpt_amount), uint64ToString(xrpl::sfMPTAmount, mptoken.mptAmount)},
};
if (mptoken.lockedAmount.has_value())
obj["locked_amount"] = uint64ToString(xrpl::sfLockedAmount, *mptoken.lockedAmount);
auto const setIfPresent = [&](boost::json::string_view field, auto const& value) {
if (value.has_value()) {
obj[field] = *value;
}
};
setIfPresent("locked_amount", mptoken.lockedAmount);
setIfPresent("mpt_locked", mptoken.mptLocked);
setIfPresent("mpt_authorized", mptoken.mptAuthorized);