mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-18 18:55:51 +00:00
fix: Support canonical names for type in account_objects (#2437)
Fix: https://github.com/XRPLF/clio/issues/2275 --------- Co-authored-by: Sergey Kuznetsov <skuznetsov@ripple.com>
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include "rpc/RPCHelpers.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
#include "util/AccountUtils.hpp"
|
||||
#include "util/LedgerUtils.hpp"
|
||||
#include "util/TimeUtils.hpp"
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
@@ -120,6 +121,18 @@ CustomValidator CustomValidators::ledgerIndexValidator =
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::ledgerTypeValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (!value.is_string())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, fmt::format("Invalid field '{}', not string.", key)}};
|
||||
|
||||
auto const type = util::LedgerTypes::getLedgerEntryTypeFromStr(boost::json::value_to<std::string>(value));
|
||||
if (type == ripple::ltANY)
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, fmt::format("Invalid field '{}'.", key)}};
|
||||
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::accountValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (!value.is_string())
|
||||
@@ -160,6 +173,19 @@ CustomValidator CustomValidators::accountMarkerValidator =
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::accountTypeValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (!value.is_string())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, fmt::format("Invalid field '{}', not string.", key)}};
|
||||
|
||||
auto const type =
|
||||
util::LedgerTypes::getAccountOwnedLedgerTypeFromStr(boost::json::value_to<std::string>(value));
|
||||
if (type == ripple::ltANY)
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, fmt::format("Invalid field '{}'.", key)}};
|
||||
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::currencyValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (!value.is_string())
|
||||
|
||||
@@ -486,6 +486,14 @@ struct CustomValidators final {
|
||||
*/
|
||||
static CustomValidator ledgerIndexValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a validator for ledger type.
|
||||
*
|
||||
* A type accepts canonical names of ledger entry types (case insensitive) or short names.
|
||||
* Used by ledger_data.
|
||||
*/
|
||||
static CustomValidator ledgerTypeValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a commonly used validator for accounts.
|
||||
*
|
||||
@@ -508,6 +516,14 @@ struct CustomValidators final {
|
||||
*/
|
||||
static CustomValidator accountMarkerValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a validator for account type.
|
||||
*
|
||||
* A type accepts canonical names of owned ledger entry types (case insensitive) or short names.
|
||||
* Used by account_objects.
|
||||
*/
|
||||
static CustomValidator accountTypeValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a commonly used validator for uint160(AccountID) hex string.
|
||||
*
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
@@ -160,7 +159,8 @@ tag_invoke(boost::json::value_to_tag<AccountObjectsHandler::Input>, boost::json:
|
||||
}
|
||||
|
||||
if (jsonObject.contains(JS(type)))
|
||||
input.type = util::LedgerTypes::getLedgerEntryTypeFromStr(boost::json::value_to<std::string>(jv.at(JS(type))));
|
||||
input.type =
|
||||
util::LedgerTypes::getAccountOwnedLedgerTypeFromStr(boost::json::value_to<std::string>(jv.at(JS(type))));
|
||||
|
||||
if (jsonObject.contains(JS(limit)))
|
||||
input.limit = jv.at(JS(limit)).as_int64();
|
||||
|
||||
@@ -25,11 +25,9 @@
|
||||
#include "rpc/common/Specs.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
#include "rpc/common/Validators.hpp"
|
||||
#include "util/LedgerUtils.hpp"
|
||||
|
||||
#include <boost/json/conversion.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
@@ -107,7 +105,6 @@ public:
|
||||
static RpcSpecConstRef
|
||||
spec([[maybe_unused]] uint32_t apiVersion)
|
||||
{
|
||||
auto const& accountOwnedTypes = util::LedgerTypes::getAccountOwnedLedgerTypeStrList();
|
||||
static auto const kRPC_SPEC = RpcSpec{
|
||||
{JS(account), validation::Required{}, validation::CustomValidators::accountValidator},
|
||||
{JS(ledger_hash), validation::CustomValidators::uint256HexStringValidator},
|
||||
@@ -116,9 +113,7 @@ public:
|
||||
validation::Type<uint32_t>{},
|
||||
validation::Min(1u),
|
||||
modifiers::Clamp<int32_t>(kLIMIT_MIN, kLIMIT_MAX)},
|
||||
{JS(type),
|
||||
validation::Type<std::string>{},
|
||||
validation::OneOf<std::string>(accountOwnedTypes.cbegin(), accountOwnedTypes.cend())},
|
||||
{JS(type), validation::CustomValidators::accountTypeValidator},
|
||||
{JS(marker), validation::CustomValidators::accountMarkerValidator},
|
||||
{JS(deletion_blockers_only), validation::Type<bool>{}},
|
||||
};
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
|
||||
@@ -20,14 +20,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/JS.hpp"
|
||||
#include "rpc/common/Checkers.hpp"
|
||||
#include "rpc/common/MetaProcessors.hpp"
|
||||
#include "rpc/common/Specs.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
#include "rpc/common/Validators.hpp"
|
||||
#include "util/LedgerUtils.hpp"
|
||||
#include "util/log/Logger.hpp"
|
||||
|
||||
#include <boost/json/array.hpp>
|
||||
@@ -36,7 +34,6 @@
|
||||
#include <boost/json/value.hpp>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/protocol/ErrorCodes.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <cstdint>
|
||||
@@ -113,7 +110,6 @@ public:
|
||||
static RpcSpecConstRef
|
||||
spec([[maybe_unused]] uint32_t apiVersion)
|
||||
{
|
||||
auto const& ledgerTypeStrs = util::LedgerTypes::getLedgerEntryTypeStrList();
|
||||
static auto const kRPC_SPEC = RpcSpec{
|
||||
{JS(binary), validation::Type<bool>{}},
|
||||
{"out_of_order", validation::Type<bool>{}},
|
||||
@@ -123,11 +119,7 @@ public:
|
||||
{JS(marker),
|
||||
validation::Type<uint32_t, std::string>{},
|
||||
meta::IfType<std::string>{validation::CustomValidators::uint256HexStringValidator}},
|
||||
{JS(type),
|
||||
meta::WithCustomError{
|
||||
validation::Type<std::string>{}, Status{ripple::rpcINVALID_PARAMS, "Invalid field 'type', not string."}
|
||||
},
|
||||
validation::OneOf<std::string>(ledgerTypeStrs.cbegin(), ledgerTypeStrs.cend())},
|
||||
{JS(type), validation::CustomValidators::ledgerTypeValidator},
|
||||
{JS(ledger), check::Deprecated{}},
|
||||
};
|
||||
return kRPC_SPEC;
|
||||
|
||||
@@ -19,9 +19,14 @@
|
||||
|
||||
#include "util/LedgerUtils.hpp"
|
||||
|
||||
#include "util/JsonUtils.hpp"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -30,16 +35,52 @@ namespace util {
|
||||
ripple::LedgerEntryType
|
||||
LedgerTypes::getLedgerEntryTypeFromStr(std::string const& entryName)
|
||||
{
|
||||
static std::unordered_map<std::string, ripple::LedgerEntryType> kTYPE_MAP = []() {
|
||||
std::unordered_map<std::string, ripple::LedgerEntryType> map;
|
||||
std::ranges::for_each(kLEDGER_TYPES, [&map](auto const& item) { map[item.name_] = item.type_; });
|
||||
return map;
|
||||
}();
|
||||
if (auto const result = getLedgerTypeAttributeFromStr(entryName); result.has_value()) {
|
||||
return result->get().type_;
|
||||
}
|
||||
return ripple::ltANY;
|
||||
}
|
||||
|
||||
if (!kTYPE_MAP.contains(entryName))
|
||||
return ripple::ltANY;
|
||||
ripple::LedgerEntryType
|
||||
LedgerTypes::getAccountOwnedLedgerTypeFromStr(std::string const& entryName)
|
||||
{
|
||||
if (auto const result = getLedgerTypeAttributeFromStr(entryName);
|
||||
result.has_value() && result->get().category_ != LedgerTypeAttribute::LedgerCategory::Chain) {
|
||||
return result->get().type_;
|
||||
}
|
||||
|
||||
return kTYPE_MAP.at(entryName);
|
||||
return ripple::ltANY;
|
||||
}
|
||||
|
||||
std::optional<std::reference_wrapper<impl::LedgerTypeAttribute const>>
|
||||
LedgerTypes::getLedgerTypeAttributeFromStr(std::string const& entryName)
|
||||
{
|
||||
static std::unordered_map<std::string, std::reference_wrapper<impl::LedgerTypeAttribute const>> const kNAME_MAP =
|
||||
[]() {
|
||||
std::unordered_map<std::string, std::reference_wrapper<impl::LedgerTypeAttribute const>> map;
|
||||
std::ranges::for_each(kLEDGER_TYPES, [&map](auto const& item) {
|
||||
map.insert({util::toLower(item.name_), item});
|
||||
});
|
||||
return map;
|
||||
}();
|
||||
|
||||
static std::unordered_map<std::string, std::reference_wrapper<impl::LedgerTypeAttribute const>> const
|
||||
kRPC_NAME_MAP = []() {
|
||||
std::unordered_map<std::string, std::reference_wrapper<impl::LedgerTypeAttribute const>> map;
|
||||
std::ranges::for_each(kLEDGER_TYPES, [&map](auto const& item) { map.insert({item.rpcName_, item}); });
|
||||
return map;
|
||||
}();
|
||||
|
||||
if (auto const it = kRPC_NAME_MAP.find(entryName); it != kRPC_NAME_MAP.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
auto const entryNameLowercase = util::toLower(entryName);
|
||||
if (auto const it = kNAME_MAP.find(entryNameLowercase); it != kNAME_MAP.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
@@ -40,6 +42,7 @@ namespace util {
|
||||
class LedgerTypes;
|
||||
|
||||
namespace impl {
|
||||
|
||||
class LedgerTypeAttribute {
|
||||
enum class LedgerCategory {
|
||||
Invalid,
|
||||
@@ -50,33 +53,40 @@ class LedgerTypeAttribute {
|
||||
|
||||
ripple::LedgerEntryType type_ = ripple::ltANY;
|
||||
char const* name_ = nullptr;
|
||||
char const* rpcName_ = nullptr;
|
||||
LedgerCategory category_ = LedgerCategory::Invalid;
|
||||
|
||||
constexpr LedgerTypeAttribute(char const* name, ripple::LedgerEntryType type, LedgerCategory category)
|
||||
: type_(type), name_(name), category_(category)
|
||||
constexpr LedgerTypeAttribute(
|
||||
char const* name,
|
||||
char const* rpcName,
|
||||
ripple::LedgerEntryType type,
|
||||
LedgerCategory category
|
||||
)
|
||||
: type_{type}, name_{name}, rpcName_{rpcName}, category_{category}
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr LedgerTypeAttribute
|
||||
chainLedgerType(char const* name, ripple::LedgerEntryType type)
|
||||
chainLedgerType(char const* name, char const* rpcName, ripple::LedgerEntryType type)
|
||||
{
|
||||
return LedgerTypeAttribute(name, type, LedgerCategory::Chain);
|
||||
return LedgerTypeAttribute(name, rpcName, type, LedgerCategory::Chain);
|
||||
}
|
||||
|
||||
static constexpr LedgerTypeAttribute
|
||||
accountOwnedLedgerType(char const* name, ripple::LedgerEntryType type)
|
||||
accountOwnedLedgerType(char const* name, char const* rpcName, ripple::LedgerEntryType type)
|
||||
{
|
||||
return LedgerTypeAttribute(name, type, LedgerCategory::AccountOwned);
|
||||
return LedgerTypeAttribute(name, rpcName, type, LedgerCategory::AccountOwned);
|
||||
}
|
||||
|
||||
static constexpr LedgerTypeAttribute
|
||||
deletionBlockerLedgerType(char const* name, ripple::LedgerEntryType type)
|
||||
deletionBlockerLedgerType(char const* name, char const* rpcName, ripple::LedgerEntryType type)
|
||||
{
|
||||
return LedgerTypeAttribute(name, type, LedgerCategory::DeletionBlocker);
|
||||
return LedgerTypeAttribute(name, rpcName, type, LedgerCategory::DeletionBlocker);
|
||||
}
|
||||
friend class util::LedgerTypes;
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
/**
|
||||
@@ -88,38 +98,51 @@ class LedgerTypes {
|
||||
using LedgerTypeAttributeList = LedgerTypeAttribute[];
|
||||
|
||||
static constexpr LedgerTypeAttributeList const kLEDGER_TYPES{
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(account), ripple::ltACCOUNT_ROOT),
|
||||
LedgerTypeAttribute::chainLedgerType(JS(amendments), ripple::ltAMENDMENTS),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(check), ripple::ltCHECK),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(AccountRoot), JS(account), ripple::ltACCOUNT_ROOT),
|
||||
LedgerTypeAttribute::chainLedgerType(JS(Amendments), JS(amendments), ripple::ltAMENDMENTS),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(Check), JS(check), ripple::ltCHECK),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(DepositPreauth), JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH),
|
||||
// dir node belongs to account, but can not be filtered from account_objects
|
||||
LedgerTypeAttribute::chainLedgerType(JS(directory), ripple::ltDIR_NODE),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(escrow), ripple::ltESCROW),
|
||||
LedgerTypeAttribute::chainLedgerType(JS(fee), ripple::ltFEE_SETTINGS),
|
||||
LedgerTypeAttribute::chainLedgerType(JS(hashes), ripple::ltLEDGER_HASHES),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(offer), ripple::ltOFFER),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(payment_channel), ripple::ltPAYCHAN),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(signer_list), ripple::ltSIGNER_LIST),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(state), ripple::ltRIPPLE_STATE),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(ticket), ripple::ltTICKET),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(nft_offer), ripple::ltNFTOKEN_OFFER),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(nft_page), ripple::ltNFTOKEN_PAGE),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(amm), ripple::ltAMM),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(bridge), ripple::ltBRIDGE),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(xchain_owned_claim_id), ripple::ltXCHAIN_OWNED_CLAIM_ID),
|
||||
LedgerTypeAttribute::chainLedgerType(JS(DirectoryNode), JS(directory), ripple::ltDIR_NODE),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(Escrow), JS(escrow), ripple::ltESCROW),
|
||||
LedgerTypeAttribute::chainLedgerType(JS(FeeSettings), JS(fee), ripple::ltFEE_SETTINGS),
|
||||
LedgerTypeAttribute::chainLedgerType(JS(LedgerHashes), JS(hashes), ripple::ltLEDGER_HASHES),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(Offer), JS(offer), ripple::ltOFFER),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(PayChannel), JS(payment_channel), ripple::ltPAYCHAN),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(SignerList), JS(signer_list), ripple::ltSIGNER_LIST),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(RippleState), JS(state), ripple::ltRIPPLE_STATE),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(Ticket), JS(ticket), ripple::ltTICKET),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(NFTokenOffer), JS(nft_offer), ripple::ltNFTOKEN_OFFER),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(NFTokenPage), JS(nft_page), ripple::ltNFTOKEN_PAGE),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(AMM), JS(amm), ripple::ltAMM),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(Bridge), JS(bridge), ripple::ltBRIDGE),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(
|
||||
JS(XChainOwnedClaimID),
|
||||
JS(xchain_owned_claim_id),
|
||||
ripple::ltXCHAIN_OWNED_CLAIM_ID
|
||||
),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(
|
||||
JS(XChainOwnedCreateAccountClaimID),
|
||||
JS(xchain_owned_create_account_claim_id),
|
||||
ripple::ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID
|
||||
),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(did), ripple::ltDID),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(oracle), ripple::ltORACLE),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(credential), ripple::ltCREDENTIAL),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(vault), ripple::ltVAULT),
|
||||
LedgerTypeAttribute::chainLedgerType(JS(nunl), ripple::ltNEGATIVE_UNL),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(mpt_issuance), ripple::ltMPTOKEN_ISSUANCE),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(mptoken), ripple::ltMPTOKEN),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(permissioned_domain), ripple::ltPERMISSIONED_DOMAIN),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(delegate), ripple::ltDELEGATE),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(DID), JS(did), ripple::ltDID),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(Oracle), JS(oracle), ripple::ltORACLE),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(Credential), JS(credential), ripple::ltCREDENTIAL),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(Vault), JS(vault), ripple::ltVAULT),
|
||||
LedgerTypeAttribute::chainLedgerType(JS(NegativeUNL), JS(nunl), ripple::ltNEGATIVE_UNL),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(
|
||||
JS(MPTokenIssuance),
|
||||
JS(mpt_issuance),
|
||||
ripple::ltMPTOKEN_ISSUANCE
|
||||
),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(JS(MPToken), JS(mptoken), ripple::ltMPTOKEN),
|
||||
LedgerTypeAttribute::deletionBlockerLedgerType(
|
||||
JS(PermissionedDomain),
|
||||
JS(permissioned_domain),
|
||||
ripple::ltPERMISSIONED_DOMAIN
|
||||
),
|
||||
LedgerTypeAttribute::accountOwnedLedgerType(JS(Delegate), JS(delegate), ripple::ltDELEGATE),
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -131,32 +154,7 @@ public:
|
||||
getLedgerEntryTypeStrList()
|
||||
{
|
||||
std::array<char const*, std::size(kLEDGER_TYPES)> res{};
|
||||
std::ranges::transform(kLEDGER_TYPES, std::begin(res), [](auto const& item) { return item.name_; });
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a list of all account owned ledger entry type as string.
|
||||
*
|
||||
* @return A list of all account owned ledger entry type as string.
|
||||
*/
|
||||
static constexpr auto
|
||||
getAccountOwnedLedgerTypeStrList()
|
||||
{
|
||||
constexpr auto kFILTER = [](auto const& item) {
|
||||
return item.category_ != LedgerTypeAttribute::LedgerCategory::Chain;
|
||||
};
|
||||
|
||||
constexpr auto kACCOUNT_OWNED_COUNT =
|
||||
std::count_if(std::begin(kLEDGER_TYPES), std::end(kLEDGER_TYPES), kFILTER);
|
||||
std::array<char const*, kACCOUNT_OWNED_COUNT> res{};
|
||||
auto it = std::begin(res);
|
||||
std::ranges::for_each(kLEDGER_TYPES, [&](auto const& item) {
|
||||
if (kFILTER(item)) {
|
||||
*it = item.name_;
|
||||
++it;
|
||||
}
|
||||
});
|
||||
std::ranges::transform(kLEDGER_TYPES, std::begin(res), [](auto const& item) { return item.rpcName_; });
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -188,11 +186,25 @@ public:
|
||||
/**
|
||||
* @brief Returns the ripple::LedgerEntryType from the given string.
|
||||
*
|
||||
* @param entryName The name of the ledger entry type
|
||||
* @param entryName The name or canonical name (case-insensitive) of the ledger entry type for all categories
|
||||
* @return The ripple::LedgerEntryType of the given string, returns ltANY if not found.
|
||||
*/
|
||||
static ripple::LedgerEntryType
|
||||
getLedgerEntryTypeFromStr(std::string const& entryName);
|
||||
|
||||
/**
|
||||
* @brief Returns the ripple::LedgerEntryType from the given string.
|
||||
*
|
||||
* @param entryName The name or canonical name (case-insensitive) of the ledger entry type for account owned
|
||||
* category
|
||||
* @return The ripple::LedgerEntryType of the given string, returns ltANY if not found.
|
||||
*/
|
||||
static ripple::LedgerEntryType
|
||||
getAccountOwnedLedgerTypeFromStr(std::string const& entryName);
|
||||
|
||||
private:
|
||||
static std::optional<std::reference_wrapper<impl::LedgerTypeAttribute const>>
|
||||
getLedgerTypeAttributeFromStr(std::string const& entryName);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -110,7 +110,7 @@ generateTestValuesForParametersTest()
|
||||
.testName = "TypeNotString",
|
||||
.testJson = R"JSON({"account": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun", "type": 1})JSON",
|
||||
.expectedError = "invalidParams",
|
||||
.expectedErrorMessage = "Invalid parameters."
|
||||
.expectedErrorMessage = "Invalid field 'type', not string."
|
||||
},
|
||||
AccountObjectsParamTestCaseBundle{
|
||||
.testName = "TypeInvalid",
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
TEST(LedgerUtilsTests, LedgerObjectTypeList)
|
||||
{
|
||||
@@ -68,46 +70,14 @@ TEST(LedgerUtilsTests, LedgerObjectTypeList)
|
||||
}));
|
||||
}
|
||||
|
||||
TEST(LedgerUtilsTests, AccountOwnedTypeList)
|
||||
{
|
||||
constexpr auto kACCOUNT_OWNED = util::LedgerTypes::getAccountOwnedLedgerTypeStrList();
|
||||
static constexpr char const* kCORRECT_TYPES[] = {
|
||||
JS(account),
|
||||
JS(check),
|
||||
JS(deposit_preauth),
|
||||
JS(escrow),
|
||||
JS(offer),
|
||||
JS(payment_channel),
|
||||
JS(signer_list),
|
||||
JS(state),
|
||||
JS(ticket),
|
||||
JS(nft_offer),
|
||||
JS(nft_page),
|
||||
JS(amm),
|
||||
JS(bridge),
|
||||
JS(xchain_owned_claim_id),
|
||||
JS(xchain_owned_create_account_claim_id),
|
||||
JS(did),
|
||||
JS(oracle),
|
||||
JS(credential),
|
||||
JS(mpt_issuance),
|
||||
JS(mptoken),
|
||||
JS(permissioned_domain),
|
||||
JS(vault),
|
||||
JS(delegate)
|
||||
};
|
||||
|
||||
static_assert(std::size(kCORRECT_TYPES) == kACCOUNT_OWNED.size());
|
||||
static_assert(std::ranges::all_of(kCORRECT_TYPES, [&kACCOUNT_OWNED](std::string_view type) {
|
||||
return std::ranges::find(kACCOUNT_OWNED, type) != std::cend(kACCOUNT_OWNED);
|
||||
}));
|
||||
}
|
||||
|
||||
TEST(LedgerUtilsTests, StrToType)
|
||||
{
|
||||
EXPECT_EQ(util::LedgerTypes::getLedgerEntryTypeFromStr("mess"), ripple::ltANY);
|
||||
EXPECT_EQ(util::LedgerTypes::getLedgerEntryTypeFromStr("tomato"), ripple::ltANY);
|
||||
EXPECT_EQ(util::LedgerTypes::getLedgerEntryTypeFromStr("account"), ripple::ltACCOUNT_ROOT);
|
||||
EXPECT_EQ(util::LedgerTypes::getLedgerEntryTypeFromStr("AccoUnt"), ripple::ltANY);
|
||||
EXPECT_EQ(util::LedgerTypes::getLedgerEntryTypeFromStr("AccountRoot"), ripple::ltACCOUNT_ROOT);
|
||||
EXPECT_EQ(util::LedgerTypes::getLedgerEntryTypeFromStr("ACCOUNTRoot"), ripple::ltACCOUNT_ROOT);
|
||||
|
||||
constexpr auto kTYPES = util::LedgerTypes::getLedgerEntryTypeStrList();
|
||||
std::ranges::for_each(kTYPES, [](auto const& typeStr) {
|
||||
@@ -139,3 +109,135 @@ TEST(LedgerUtilsTests, DeletionBlockerTypes)
|
||||
std::cend(kDELETION_BLOCKERS);
|
||||
}));
|
||||
}
|
||||
|
||||
struct LedgerEntryTypeParam {
|
||||
std::string input;
|
||||
ripple::LedgerEntryType expected;
|
||||
};
|
||||
|
||||
static LedgerEntryTypeParam const kCHAIN_TEST_CASES[] = {
|
||||
// Using RPC name with exact match
|
||||
{.input = "amendments", .expected = ripple::ltAMENDMENTS},
|
||||
{.input = "directory", .expected = ripple::ltDIR_NODE},
|
||||
{.input = "fee", .expected = ripple::ltFEE_SETTINGS},
|
||||
{.input = "hashes", .expected = ripple::ltLEDGER_HASHES},
|
||||
{.input = "nunl", .expected = ripple::ltNEGATIVE_UNL},
|
||||
|
||||
// Using canonical name with exact match
|
||||
{.input = "Amendments", .expected = ripple::ltAMENDMENTS},
|
||||
{.input = "DirectoryNode", .expected = ripple::ltDIR_NODE},
|
||||
{.input = "FeeSettings", .expected = ripple::ltFEE_SETTINGS},
|
||||
{.input = "LedgerHashes", .expected = ripple::ltLEDGER_HASHES},
|
||||
{.input = "NegativeUNL", .expected = ripple::ltNEGATIVE_UNL}
|
||||
};
|
||||
|
||||
static LedgerEntryTypeParam const kACCOUNT_OWNED_TEST_CASES[] = {
|
||||
// Using RPC name with exact match
|
||||
{.input = "account", .expected = ripple::ltACCOUNT_ROOT},
|
||||
{.input = "check", .expected = ripple::ltCHECK},
|
||||
{.input = "deposit_preauth", .expected = ripple::ltDEPOSIT_PREAUTH},
|
||||
{.input = "escrow", .expected = ripple::ltESCROW},
|
||||
{.input = "offer", .expected = ripple::ltOFFER},
|
||||
{.input = "payment_channel", .expected = ripple::ltPAYCHAN},
|
||||
{.input = "signer_list", .expected = ripple::ltSIGNER_LIST},
|
||||
{.input = "state", .expected = ripple::ltRIPPLE_STATE},
|
||||
{.input = "ticket", .expected = ripple::ltTICKET},
|
||||
{.input = "nft_offer", .expected = ripple::ltNFTOKEN_OFFER},
|
||||
{.input = "nft_page", .expected = ripple::ltNFTOKEN_PAGE},
|
||||
{.input = "amm", .expected = ripple::ltAMM},
|
||||
{.input = "bridge", .expected = ripple::ltBRIDGE},
|
||||
{.input = "xchain_owned_claim_id", .expected = ripple::ltXCHAIN_OWNED_CLAIM_ID},
|
||||
{.input = "xchain_owned_create_account_claim_id", .expected = ripple::ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID},
|
||||
{.input = "did", .expected = ripple::ltDID},
|
||||
{.input = "oracle", .expected = ripple::ltORACLE},
|
||||
{.input = "credential", .expected = ripple::ltCREDENTIAL},
|
||||
{.input = "mpt_issuance", .expected = ripple::ltMPTOKEN_ISSUANCE},
|
||||
{.input = "mptoken", .expected = ripple::ltMPTOKEN},
|
||||
{.input = "permissioned_domain", .expected = ripple::ltPERMISSIONED_DOMAIN},
|
||||
{.input = "vault", .expected = ripple::ltVAULT},
|
||||
{.input = "delegate", .expected = ripple::ltDELEGATE},
|
||||
|
||||
// Using canonical name with exact match
|
||||
{.input = "AccountRoot", .expected = ripple::ltACCOUNT_ROOT},
|
||||
{.input = "Check", .expected = ripple::ltCHECK},
|
||||
{.input = "DepositPreauth", .expected = ripple::ltDEPOSIT_PREAUTH},
|
||||
{.input = "Escrow", .expected = ripple::ltESCROW},
|
||||
{.input = "Offer", .expected = ripple::ltOFFER},
|
||||
{.input = "PayChannel", .expected = ripple::ltPAYCHAN},
|
||||
{.input = "SignerList", .expected = ripple::ltSIGNER_LIST},
|
||||
{.input = "RippleState", .expected = ripple::ltRIPPLE_STATE},
|
||||
{.input = "Ticket", .expected = ripple::ltTICKET},
|
||||
{.input = "NFTokenOffer", .expected = ripple::ltNFTOKEN_OFFER},
|
||||
{.input = "NFTokenPage", .expected = ripple::ltNFTOKEN_PAGE},
|
||||
{.input = "AMM", .expected = ripple::ltAMM},
|
||||
{.input = "Bridge", .expected = ripple::ltBRIDGE},
|
||||
{.input = "XChainOwnedClaimID", .expected = ripple::ltXCHAIN_OWNED_CLAIM_ID},
|
||||
{.input = "XChainOwnedCreateAccountClaimID", .expected = ripple::ltXCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID},
|
||||
{.input = "DID", .expected = ripple::ltDID},
|
||||
{.input = "Oracle", .expected = ripple::ltORACLE},
|
||||
{.input = "Credential", .expected = ripple::ltCREDENTIAL},
|
||||
{.input = "MPTokenIssuance", .expected = ripple::ltMPTOKEN_ISSUANCE},
|
||||
{.input = "MPToken", .expected = ripple::ltMPTOKEN},
|
||||
{.input = "PermissionedDomain", .expected = ripple::ltPERMISSIONED_DOMAIN},
|
||||
{.input = "Vault", .expected = ripple::ltVAULT},
|
||||
{.input = "Delegate", .expected = ripple::ltDELEGATE}
|
||||
};
|
||||
|
||||
static LedgerEntryTypeParam const kCASE_INSENSITIVE_TEST_CASES[] = {
|
||||
// With canonical name in mixedcase
|
||||
{.input = "mPtOKenIssuance", .expected = ripple::ltMPTOKEN_ISSUANCE},
|
||||
// With canonical name in lowercase
|
||||
{.input = "mptokenissuance", .expected = ripple::ltMPTOKEN_ISSUANCE},
|
||||
};
|
||||
|
||||
static LedgerEntryTypeParam const kINVALID_TEST_CASES[] = {
|
||||
{.input = "", .expected = ripple::ltANY},
|
||||
{.input = "1234", .expected = ripple::ltANY},
|
||||
{.input = "unknown", .expected = ripple::ltANY},
|
||||
// With RPC name with inexact match
|
||||
{.input = "MPT_Issuance", .expected = ripple::ltANY}
|
||||
};
|
||||
|
||||
class LedgerEntryTypeFromStrTest : public ::testing::TestWithParam<LedgerEntryTypeParam> {};
|
||||
|
||||
TEST_P(LedgerEntryTypeFromStrTest, GetLedgerEntryTypeFromStr)
|
||||
{
|
||||
auto const& param = GetParam();
|
||||
auto const result = util::LedgerTypes::getLedgerEntryTypeFromStr(param.input);
|
||||
EXPECT_EQ(result, param.expected) << param.input;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
LedgerUtilsTests,
|
||||
LedgerEntryTypeFromStrTest,
|
||||
::testing::ValuesIn([]() {
|
||||
std::vector<LedgerEntryTypeParam> v;
|
||||
v.insert(v.end(), std::begin(kCHAIN_TEST_CASES), std::end(kCHAIN_TEST_CASES));
|
||||
v.insert(v.end(), std::begin(kACCOUNT_OWNED_TEST_CASES), std::end(kACCOUNT_OWNED_TEST_CASES));
|
||||
v.insert(v.end(), std::begin(kCASE_INSENSITIVE_TEST_CASES), std::end(kCASE_INSENSITIVE_TEST_CASES));
|
||||
v.insert(v.end(), std::begin(kINVALID_TEST_CASES), std::end(kINVALID_TEST_CASES));
|
||||
return v;
|
||||
}())
|
||||
);
|
||||
|
||||
class AccountOwnedLedgerTypeFromStrTest : public ::testing::TestWithParam<LedgerEntryTypeParam> {};
|
||||
|
||||
TEST_P(AccountOwnedLedgerTypeFromStrTest, GetAccountOwnedLedgerTypeFromStr)
|
||||
{
|
||||
auto const& param = GetParam();
|
||||
auto const result = util::LedgerTypes::getAccountOwnedLedgerTypeFromStr(param.input);
|
||||
EXPECT_EQ(result, param.expected);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
LedgerUtilsTests,
|
||||
AccountOwnedLedgerTypeFromStrTest,
|
||||
::testing::ValuesIn([]() {
|
||||
std::vector<LedgerEntryTypeParam> v;
|
||||
v.insert(v.end(), std::begin(kACCOUNT_OWNED_TEST_CASES), std::end(kACCOUNT_OWNED_TEST_CASES));
|
||||
v.insert(v.end(), std::begin(kCASE_INSENSITIVE_TEST_CASES), std::end(kCASE_INSENSITIVE_TEST_CASES));
|
||||
v.insert(v.end(), std::begin(kINVALID_TEST_CASES), std::end(kINVALID_TEST_CASES));
|
||||
v.push_back({"amendments", ripple::ltANY}); // chain type should return ltANY
|
||||
return v;
|
||||
}())
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user