mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-27 23:25:53 +00:00
@@ -66,7 +66,7 @@
|
||||
// Max number of requests to queue up before rejecting further requests.
|
||||
// Defaults to 0, which disables the limit.
|
||||
"max_queue_size": 500,
|
||||
// If request contains header with authorization, Clio will check if it matches this value's hash
|
||||
// If request contains header with authorization, Clio will check if it matches this value's sha256 hash
|
||||
// If matches, the request will be considered as admin request
|
||||
"admin_password": "xrp",
|
||||
// If local_admin is true, Clio will consider requests come from 127.0.0.1 as admin requests
|
||||
|
||||
@@ -22,19 +22,28 @@
|
||||
namespace rpc {
|
||||
|
||||
// found here : https://xrpl.org/ledger_entry.html#:~:text=valid%20fields%20are%3A-,index,-account_root
|
||||
std::unordered_map<std::string, ripple::LedgerEntryType> const AccountObjectsHandler::TYPESMAP{
|
||||
{"state", ripple::ltRIPPLE_STATE},
|
||||
{"ticket", ripple::ltTICKET},
|
||||
{"signer_list", ripple::ltSIGNER_LIST},
|
||||
{"payment_channel", ripple::ltPAYCHAN},
|
||||
{"offer", ripple::ltOFFER},
|
||||
{"escrow", ripple::ltESCROW},
|
||||
{"deposit_preauth", ripple::ltDEPOSIT_PREAUTH},
|
||||
{"check", ripple::ltCHECK},
|
||||
{"nft_page", ripple::ltNFTOKEN_PAGE},
|
||||
{"nft_offer", ripple::ltNFTOKEN_OFFER},
|
||||
std::unordered_map<std::string, ripple::LedgerEntryType> const AccountObjectsHandler::TYPES_MAP{
|
||||
{JS(state), ripple::ltRIPPLE_STATE},
|
||||
{JS(ticket), ripple::ltTICKET},
|
||||
{JS(signer_list), ripple::ltSIGNER_LIST},
|
||||
{JS(payment_channel), ripple::ltPAYCHAN},
|
||||
{JS(offer), ripple::ltOFFER},
|
||||
{JS(escrow), ripple::ltESCROW},
|
||||
{JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH},
|
||||
{JS(check), ripple::ltCHECK},
|
||||
{JS(nft_page), ripple::ltNFTOKEN_PAGE},
|
||||
{JS(nft_offer), ripple::ltNFTOKEN_OFFER},
|
||||
{JS(did), ripple::ltDID},
|
||||
};
|
||||
|
||||
std::unordered_set<std::string> const AccountObjectsHandler::TYPES_KEYS = [] {
|
||||
std::unordered_set<std::string> keys;
|
||||
std::transform(TYPES_MAP.begin(), TYPES_MAP.end(), std::inserter(keys, keys.begin()), [](auto const& pair) {
|
||||
return pair.first;
|
||||
});
|
||||
return keys;
|
||||
}();
|
||||
|
||||
AccountObjectsHandler::Result
|
||||
AccountObjectsHandler::process(AccountObjectsHandler::Input input, Context const& ctx) const
|
||||
{
|
||||
@@ -153,7 +162,7 @@ tag_invoke(boost::json::value_to_tag<AccountObjectsHandler::Input>, boost::json:
|
||||
}
|
||||
|
||||
if (jsonObject.contains(JS(type)))
|
||||
input.type = AccountObjectsHandler::TYPESMAP.at(jv.at(JS(type)).as_string().c_str());
|
||||
input.type = AccountObjectsHandler::TYPES_MAP.at(jv.at(JS(type)).as_string().c_str());
|
||||
|
||||
if (jsonObject.contains(JS(limit)))
|
||||
input.limit = jv.at(JS(limit)).as_int64();
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace rpc {
|
||||
* @brief The account_objects command returns the raw ledger format for all objects owned by an account.
|
||||
* The results can be filtered by the type.
|
||||
* The valid types are: check, deposit_preauth, escrow, nft_offer, offer, payment_channel, signer_list, state (trust
|
||||
* line), and ticket.
|
||||
* line), did and ticket.
|
||||
*
|
||||
* For more details see: https://xrpl.org/account_objects.html
|
||||
*/
|
||||
@@ -42,7 +42,8 @@ class AccountObjectsHandler {
|
||||
std::shared_ptr<BackendInterface> sharedPtrBackend_;
|
||||
|
||||
// constants
|
||||
static std::unordered_map<std::string, ripple::LedgerEntryType> const TYPESMAP;
|
||||
static std::unordered_map<std::string, ripple::LedgerEntryType> const TYPES_MAP;
|
||||
static std::unordered_set<std::string> const TYPES_KEYS;
|
||||
|
||||
public:
|
||||
static auto constexpr LIMIT_MIN = 10;
|
||||
@@ -89,18 +90,7 @@ public:
|
||||
modifiers::Clamp<int32_t>(LIMIT_MIN, LIMIT_MAX)},
|
||||
{JS(type),
|
||||
validation::Type<std::string>{},
|
||||
validation::OneOf<std::string>{
|
||||
"state",
|
||||
"ticket",
|
||||
"signer_list",
|
||||
"payment_channel",
|
||||
"offer",
|
||||
"escrow",
|
||||
"deposit_preauth",
|
||||
"check",
|
||||
"nft_page",
|
||||
"nft_offer",
|
||||
}},
|
||||
validation::OneOf<std::string>(TYPES_KEYS.cbegin(), TYPES_KEYS.cend())},
|
||||
{JS(marker), validation::AccountMarkerValidator},
|
||||
{JS(deletion_blockers_only), validation::Type<bool>{}},
|
||||
};
|
||||
|
||||
@@ -56,6 +56,8 @@ std::unordered_map<std::string, ripple::TxType> const AccountTxHandler::TYPESMAP
|
||||
{JSL(SignerListSet), ripple::ttSIGNER_LIST_SET},
|
||||
{JSL(TicketCreate), ripple::ttTICKET_CREATE},
|
||||
{JSL(TrustSet), ripple::ttTRUST_SET},
|
||||
{JSL(DIDSet), ripple::ttDID_SET},
|
||||
{JSL(DIDDelete), ripple::ttDID_DELETE},
|
||||
};
|
||||
|
||||
// TODO: should be std::views::keys when clang supports it
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace rpc {
|
||||
|
||||
std::unordered_map<std::string, ripple::LedgerEntryType> const LedgerDataHandler::TYPES_MAP{
|
||||
{JS(account), ripple::ltACCOUNT_ROOT},
|
||||
{JS(did), ripple::ltDID},
|
||||
{JS(amendments), ripple::ltAMENDMENTS},
|
||||
{JS(check), ripple::ltCHECK},
|
||||
{JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH},
|
||||
|
||||
@@ -41,9 +41,9 @@ class LedgerDataHandler {
|
||||
std::shared_ptr<BackendInterface> sharedPtrBackend_;
|
||||
util::Logger log_{"RPC"};
|
||||
|
||||
static const std::unordered_map<std::string, ripple::LedgerEntryType> TYPES_MAP;
|
||||
static std::unordered_map<std::string, ripple::LedgerEntryType> const TYPES_MAP;
|
||||
|
||||
static const std::unordered_set<std::string> TYPES_KEYS;
|
||||
static std::unordered_set<std::string> const TYPES_KEYS;
|
||||
|
||||
public:
|
||||
// constants
|
||||
|
||||
@@ -32,6 +32,8 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
key = ripple::uint256{std::string_view(*(input.index))};
|
||||
} else if (input.accountRoot) {
|
||||
key = ripple::keylet::account(*ripple::parseBase58<ripple::AccountID>(*(input.accountRoot))).key;
|
||||
} else if (input.did) {
|
||||
key = ripple::keylet::did(*ripple::parseBase58<ripple::AccountID>(*(input.did))).key;
|
||||
} else if (input.directory) {
|
||||
auto const keyOrStatus = composeKeyFromDirectory(*input.directory);
|
||||
if (auto const status = std::get_if<Status>(&keyOrStatus))
|
||||
@@ -209,6 +211,8 @@ tag_invoke(boost::json::value_to_tag<LedgerEntryHandler::Input>, boost::json::va
|
||||
// check if request for account root
|
||||
else if (jsonObject.contains(JS(account_root))) {
|
||||
input.accountRoot = jv.at(JS(account_root)).as_string().c_str();
|
||||
} else if (jsonObject.contains(JS(did))) {
|
||||
input.did = jv.at(JS(did)).as_string().c_str();
|
||||
}
|
||||
// no need to check if_object again, validator only allows string or object
|
||||
else if (jsonObject.contains(JS(directory))) {
|
||||
|
||||
@@ -56,6 +56,8 @@ public:
|
||||
ripple::LedgerEntryType expectedType = ripple::ltANY;
|
||||
// account id to address account root object
|
||||
std::optional<std::string> accountRoot;
|
||||
// account id to address did object
|
||||
std::optional<std::string> did;
|
||||
// TODO: extract into custom objects, remove json from Input
|
||||
std::optional<boost::json::object> directory;
|
||||
std::optional<boost::json::object> offer;
|
||||
@@ -128,6 +130,7 @@ public:
|
||||
{JS(ledger_index), validation::LedgerIndexValidator},
|
||||
{JS(index), malformedRequestHexStringValidator},
|
||||
{JS(account_root), validation::AccountBase58Validator},
|
||||
{JS(did), validation::AccountBase58Validator},
|
||||
{JS(check), malformedRequestHexStringValidator},
|
||||
{JS(deposit_preauth),
|
||||
validation::Type<std::string, boost::json::object>{},
|
||||
|
||||
@@ -1486,6 +1486,22 @@ static auto
|
||||
generateTransactionTypeTestValues()
|
||||
{
|
||||
return std::vector<AccountTxTransactionBundle>{
|
||||
AccountTxTransactionBundle{
|
||||
"DIDSet",
|
||||
R"({
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated",
|
||||
"tx_type": "DIDSet"
|
||||
})",
|
||||
"[]"},
|
||||
AccountTxTransactionBundle{
|
||||
"DIDDelete",
|
||||
R"({
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated",
|
||||
"tx_type": "DIDDelete"
|
||||
})",
|
||||
"[]"},
|
||||
AccountTxTransactionBundle{
|
||||
"AccountSet",
|
||||
R"({
|
||||
|
||||
@@ -82,6 +82,14 @@ generateTestValuesForParametersTest()
|
||||
"malformedAddress",
|
||||
"Malformed address."},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"InvalidDidFormat",
|
||||
R"({
|
||||
"did": "invalid"
|
||||
})",
|
||||
"malformedAddress",
|
||||
"Malformed address."},
|
||||
|
||||
ParamTestCaseBundle{
|
||||
"InvalidAccountRootNotString",
|
||||
R"({
|
||||
@@ -1041,6 +1049,17 @@ generateTestValuesForNormalPathTest()
|
||||
),
|
||||
ripple::keylet::account(GetAccountIDWithString(ACCOUNT)).key,
|
||||
CreateAccountRootObject(ACCOUNT, 0, 1, 1, 1, INDEX1, 1)},
|
||||
NormalPathTestBundle{
|
||||
"DID",
|
||||
fmt::format(
|
||||
R"({{
|
||||
"binary": true,
|
||||
"did": "{}"
|
||||
}})",
|
||||
ACCOUNT
|
||||
),
|
||||
ripple::keylet::did(GetAccountIDWithString(ACCOUNT)).key,
|
||||
CreateDidObject(ACCOUNT, "mydocument", "myURI", "mydata")},
|
||||
NormalPathTestBundle{
|
||||
"DirectoryViaDirRoot",
|
||||
fmt::format(
|
||||
|
||||
@@ -136,6 +136,25 @@ CreatePaymentTransactionMetaObject(
|
||||
return metaObj;
|
||||
}
|
||||
|
||||
ripple::STObject
|
||||
CreateDidObject(std::string_view accountId, std::string_view didDoc, std::string_view uri, std::string_view data)
|
||||
{
|
||||
ripple::STObject did(ripple::sfLedgerEntry);
|
||||
did.setAccountID(ripple::sfAccount, GetAccountIDWithString(accountId));
|
||||
did.setFieldU16(ripple::sfLedgerEntryType, ripple::ltDID);
|
||||
did.setFieldU32(ripple::sfFlags, 0);
|
||||
did.setFieldU64(ripple::sfOwnerNode, 0);
|
||||
did.setFieldH256(ripple::sfPreviousTxnID, ripple::uint256{});
|
||||
did.setFieldU32(ripple::sfPreviousTxnLgrSeq, 0);
|
||||
ripple::Slice const sliceDoc(didDoc.data(), didDoc.size());
|
||||
did.setFieldVL(ripple::sfDIDDocument, sliceDoc);
|
||||
ripple::Slice const sliceUri(uri.data(), uri.size());
|
||||
did.setFieldVL(ripple::sfURI, sliceUri);
|
||||
ripple::Slice const sliceData(data.data(), data.size());
|
||||
did.setFieldVL(ripple::sfData, sliceData);
|
||||
return did;
|
||||
}
|
||||
|
||||
ripple::STObject
|
||||
CreateAccountRootObject(
|
||||
std::string_view accountId,
|
||||
|
||||
@@ -286,3 +286,6 @@ CreateAMMObject(
|
||||
std::string_view asset2Currency,
|
||||
std::string_view asset2Issuer
|
||||
);
|
||||
|
||||
[[nodiscard]] ripple::STObject
|
||||
CreateDidObject(std::string_view accountId, std::string_view didDoc, std::string_view uri, std::string_view data);
|
||||
|
||||
Reference in New Issue
Block a user