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.
|
// Max number of requests to queue up before rejecting further requests.
|
||||||
// Defaults to 0, which disables the limit.
|
// Defaults to 0, which disables the limit.
|
||||||
"max_queue_size": 500,
|
"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
|
// If matches, the request will be considered as admin request
|
||||||
"admin_password": "xrp",
|
"admin_password": "xrp",
|
||||||
// If local_admin is true, Clio will consider requests come from 127.0.0.1 as admin requests
|
// If local_admin is true, Clio will consider requests come from 127.0.0.1 as admin requests
|
||||||
|
|||||||
@@ -22,19 +22,28 @@
|
|||||||
namespace rpc {
|
namespace rpc {
|
||||||
|
|
||||||
// found here : https://xrpl.org/ledger_entry.html#:~:text=valid%20fields%20are%3A-,index,-account_root
|
// 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{
|
std::unordered_map<std::string, ripple::LedgerEntryType> const AccountObjectsHandler::TYPES_MAP{
|
||||||
{"state", ripple::ltRIPPLE_STATE},
|
{JS(state), ripple::ltRIPPLE_STATE},
|
||||||
{"ticket", ripple::ltTICKET},
|
{JS(ticket), ripple::ltTICKET},
|
||||||
{"signer_list", ripple::ltSIGNER_LIST},
|
{JS(signer_list), ripple::ltSIGNER_LIST},
|
||||||
{"payment_channel", ripple::ltPAYCHAN},
|
{JS(payment_channel), ripple::ltPAYCHAN},
|
||||||
{"offer", ripple::ltOFFER},
|
{JS(offer), ripple::ltOFFER},
|
||||||
{"escrow", ripple::ltESCROW},
|
{JS(escrow), ripple::ltESCROW},
|
||||||
{"deposit_preauth", ripple::ltDEPOSIT_PREAUTH},
|
{JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH},
|
||||||
{"check", ripple::ltCHECK},
|
{JS(check), ripple::ltCHECK},
|
||||||
{"nft_page", ripple::ltNFTOKEN_PAGE},
|
{JS(nft_page), ripple::ltNFTOKEN_PAGE},
|
||||||
{"nft_offer", ripple::ltNFTOKEN_OFFER},
|
{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::Result
|
||||||
AccountObjectsHandler::process(AccountObjectsHandler::Input input, Context const& ctx) const
|
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)))
|
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)))
|
if (jsonObject.contains(JS(limit)))
|
||||||
input.limit = jv.at(JS(limit)).as_int64();
|
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.
|
* @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 results can be filtered by the type.
|
||||||
* The valid types are: check, deposit_preauth, escrow, nft_offer, offer, payment_channel, signer_list, state (trust
|
* 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
|
* For more details see: https://xrpl.org/account_objects.html
|
||||||
*/
|
*/
|
||||||
@@ -42,7 +42,8 @@ class AccountObjectsHandler {
|
|||||||
std::shared_ptr<BackendInterface> sharedPtrBackend_;
|
std::shared_ptr<BackendInterface> sharedPtrBackend_;
|
||||||
|
|
||||||
// constants
|
// 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:
|
public:
|
||||||
static auto constexpr LIMIT_MIN = 10;
|
static auto constexpr LIMIT_MIN = 10;
|
||||||
@@ -89,18 +90,7 @@ public:
|
|||||||
modifiers::Clamp<int32_t>(LIMIT_MIN, LIMIT_MAX)},
|
modifiers::Clamp<int32_t>(LIMIT_MIN, LIMIT_MAX)},
|
||||||
{JS(type),
|
{JS(type),
|
||||||
validation::Type<std::string>{},
|
validation::Type<std::string>{},
|
||||||
validation::OneOf<std::string>{
|
validation::OneOf<std::string>(TYPES_KEYS.cbegin(), TYPES_KEYS.cend())},
|
||||||
"state",
|
|
||||||
"ticket",
|
|
||||||
"signer_list",
|
|
||||||
"payment_channel",
|
|
||||||
"offer",
|
|
||||||
"escrow",
|
|
||||||
"deposit_preauth",
|
|
||||||
"check",
|
|
||||||
"nft_page",
|
|
||||||
"nft_offer",
|
|
||||||
}},
|
|
||||||
{JS(marker), validation::AccountMarkerValidator},
|
{JS(marker), validation::AccountMarkerValidator},
|
||||||
{JS(deletion_blockers_only), validation::Type<bool>{}},
|
{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(SignerListSet), ripple::ttSIGNER_LIST_SET},
|
||||||
{JSL(TicketCreate), ripple::ttTICKET_CREATE},
|
{JSL(TicketCreate), ripple::ttTICKET_CREATE},
|
||||||
{JSL(TrustSet), ripple::ttTRUST_SET},
|
{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
|
// 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{
|
std::unordered_map<std::string, ripple::LedgerEntryType> const LedgerDataHandler::TYPES_MAP{
|
||||||
{JS(account), ripple::ltACCOUNT_ROOT},
|
{JS(account), ripple::ltACCOUNT_ROOT},
|
||||||
|
{JS(did), ripple::ltDID},
|
||||||
{JS(amendments), ripple::ltAMENDMENTS},
|
{JS(amendments), ripple::ltAMENDMENTS},
|
||||||
{JS(check), ripple::ltCHECK},
|
{JS(check), ripple::ltCHECK},
|
||||||
{JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH},
|
{JS(deposit_preauth), ripple::ltDEPOSIT_PREAUTH},
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ class LedgerDataHandler {
|
|||||||
std::shared_ptr<BackendInterface> sharedPtrBackend_;
|
std::shared_ptr<BackendInterface> sharedPtrBackend_;
|
||||||
util::Logger log_{"RPC"};
|
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:
|
public:
|
||||||
// constants
|
// constants
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
|||||||
key = ripple::uint256{std::string_view(*(input.index))};
|
key = ripple::uint256{std::string_view(*(input.index))};
|
||||||
} else if (input.accountRoot) {
|
} else if (input.accountRoot) {
|
||||||
key = ripple::keylet::account(*ripple::parseBase58<ripple::AccountID>(*(input.accountRoot))).key;
|
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) {
|
} else if (input.directory) {
|
||||||
auto const keyOrStatus = composeKeyFromDirectory(*input.directory);
|
auto const keyOrStatus = composeKeyFromDirectory(*input.directory);
|
||||||
if (auto const status = std::get_if<Status>(&keyOrStatus))
|
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
|
// check if request for account root
|
||||||
else if (jsonObject.contains(JS(account_root))) {
|
else if (jsonObject.contains(JS(account_root))) {
|
||||||
input.accountRoot = jv.at(JS(account_root)).as_string().c_str();
|
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
|
// no need to check if_object again, validator only allows string or object
|
||||||
else if (jsonObject.contains(JS(directory))) {
|
else if (jsonObject.contains(JS(directory))) {
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ public:
|
|||||||
ripple::LedgerEntryType expectedType = ripple::ltANY;
|
ripple::LedgerEntryType expectedType = ripple::ltANY;
|
||||||
// account id to address account root object
|
// account id to address account root object
|
||||||
std::optional<std::string> accountRoot;
|
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
|
// TODO: extract into custom objects, remove json from Input
|
||||||
std::optional<boost::json::object> directory;
|
std::optional<boost::json::object> directory;
|
||||||
std::optional<boost::json::object> offer;
|
std::optional<boost::json::object> offer;
|
||||||
@@ -128,6 +130,7 @@ public:
|
|||||||
{JS(ledger_index), validation::LedgerIndexValidator},
|
{JS(ledger_index), validation::LedgerIndexValidator},
|
||||||
{JS(index), malformedRequestHexStringValidator},
|
{JS(index), malformedRequestHexStringValidator},
|
||||||
{JS(account_root), validation::AccountBase58Validator},
|
{JS(account_root), validation::AccountBase58Validator},
|
||||||
|
{JS(did), validation::AccountBase58Validator},
|
||||||
{JS(check), malformedRequestHexStringValidator},
|
{JS(check), malformedRequestHexStringValidator},
|
||||||
{JS(deposit_preauth),
|
{JS(deposit_preauth),
|
||||||
validation::Type<std::string, boost::json::object>{},
|
validation::Type<std::string, boost::json::object>{},
|
||||||
|
|||||||
@@ -1486,6 +1486,22 @@ static auto
|
|||||||
generateTransactionTypeTestValues()
|
generateTransactionTypeTestValues()
|
||||||
{
|
{
|
||||||
return std::vector<AccountTxTransactionBundle>{
|
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{
|
AccountTxTransactionBundle{
|
||||||
"AccountSet",
|
"AccountSet",
|
||||||
R"({
|
R"({
|
||||||
|
|||||||
@@ -82,6 +82,14 @@ generateTestValuesForParametersTest()
|
|||||||
"malformedAddress",
|
"malformedAddress",
|
||||||
"Malformed address."},
|
"Malformed address."},
|
||||||
|
|
||||||
|
ParamTestCaseBundle{
|
||||||
|
"InvalidDidFormat",
|
||||||
|
R"({
|
||||||
|
"did": "invalid"
|
||||||
|
})",
|
||||||
|
"malformedAddress",
|
||||||
|
"Malformed address."},
|
||||||
|
|
||||||
ParamTestCaseBundle{
|
ParamTestCaseBundle{
|
||||||
"InvalidAccountRootNotString",
|
"InvalidAccountRootNotString",
|
||||||
R"({
|
R"({
|
||||||
@@ -1041,6 +1049,17 @@ generateTestValuesForNormalPathTest()
|
|||||||
),
|
),
|
||||||
ripple::keylet::account(GetAccountIDWithString(ACCOUNT)).key,
|
ripple::keylet::account(GetAccountIDWithString(ACCOUNT)).key,
|
||||||
CreateAccountRootObject(ACCOUNT, 0, 1, 1, 1, INDEX1, 1)},
|
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{
|
NormalPathTestBundle{
|
||||||
"DirectoryViaDirRoot",
|
"DirectoryViaDirRoot",
|
||||||
fmt::format(
|
fmt::format(
|
||||||
|
|||||||
@@ -136,6 +136,25 @@ CreatePaymentTransactionMetaObject(
|
|||||||
return metaObj;
|
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
|
ripple::STObject
|
||||||
CreateAccountRootObject(
|
CreateAccountRootObject(
|
||||||
std::string_view accountId,
|
std::string_view accountId,
|
||||||
|
|||||||
@@ -286,3 +286,6 @@ CreateAMMObject(
|
|||||||
std::string_view asset2Currency,
|
std::string_view asset2Currency,
|
||||||
std::string_view asset2Issuer
|
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