mirror of
https://github.com/XRPLF/clio.git
synced 2026-04-29 15:37:53 +00:00
feat: Support single asset vault (#1979)
fixes #1921 --------- Co-authored-by: Sergey Kuznetsov <skuznetsov@ripple.com> Co-authored-by: Ayaz Salikhov <mathbunnyru@users.noreply.github.com>
This commit is contained in:
@@ -51,6 +51,7 @@ target_sources(
|
||||
handlers/Subscribe.cpp
|
||||
handlers/TransactionEntry.cpp
|
||||
handlers/Unsubscribe.cpp
|
||||
handlers/VaultInfo.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(clio_rpc PRIVATE clio_util)
|
||||
|
||||
@@ -89,7 +89,7 @@ getErrorInfo(ClioError code)
|
||||
{.code = ClioError::RpcMalformedAuthorizedCredentials,
|
||||
.error = "malformedAuthorizedCredentials",
|
||||
.message = "Malformed authorized credentials."},
|
||||
|
||||
{.code = ClioError::RpcEntryNotFound, .error = "entryNotFound", .message = "Entry Not Found."},
|
||||
// special system errors
|
||||
{.code = ClioError::RpcInvalidApiVersion, .error = JS(invalid_API_version), .message = "Invalid API version."},
|
||||
{.code = ClioError::RpcCommandIsMissing,
|
||||
|
||||
@@ -43,6 +43,7 @@ enum class ClioError {
|
||||
RpcFieldNotFoundTransaction = 5006,
|
||||
RpcMalformedOracleDocumentId = 5007,
|
||||
RpcMalformedAuthorizedCredentials = 5008,
|
||||
RpcEntryNotFound = 5009,
|
||||
|
||||
// special system errors start with 6000
|
||||
RpcInvalidApiVersion = 6000,
|
||||
|
||||
@@ -30,6 +30,7 @@ std::unordered_set<std::string_view> const&
|
||||
handledRpcs()
|
||||
{
|
||||
static std::unordered_set<std::string_view> const kHANDLED_RPCS = {
|
||||
// clang-format off
|
||||
"account_channels",
|
||||
"account_currencies",
|
||||
"account_info",
|
||||
@@ -64,7 +65,9 @@ handledRpcs()
|
||||
"tx",
|
||||
"subscribe",
|
||||
"unsubscribe",
|
||||
"vault_info",
|
||||
"version",
|
||||
// clang-format on
|
||||
};
|
||||
return kHANDLED_RPCS;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "data/Types.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/JS.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
#include "util/JsonUtils.hpp"
|
||||
#include "util/Taggable.hpp"
|
||||
@@ -42,6 +43,7 @@
|
||||
#include <boost/regex/v5/regex_fwd.hpp>
|
||||
#include <boost/regex/v5/regex_match.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/json/json_value.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
@@ -50,9 +52,12 @@
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Issue.h>
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/LedgerFormats.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
#include <xrpl/protocol/MPTIssue.h>
|
||||
#include <xrpl/protocol/PublicKey.h>
|
||||
#include <xrpl/protocol/Rate.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STAmount.h>
|
||||
#include <xrpl/protocol/STBase.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
@@ -60,9 +65,11 @@
|
||||
#include <xrpl/protocol/STTx.h>
|
||||
#include <xrpl/protocol/SecretKey.h>
|
||||
#include <xrpl/protocol/Seed.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/TxMeta.h>
|
||||
#include <xrpl/protocol/UintTypes.h>
|
||||
#include <xrpl/protocol/XRPAmount.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "rpc/handlers/TransactionEntry.hpp"
|
||||
#include "rpc/handlers/Tx.hpp"
|
||||
#include "rpc/handlers/Unsubscribe.hpp"
|
||||
#include "rpc/handlers/VaultInfo.hpp"
|
||||
#include "rpc/handlers/VersionHandler.hpp"
|
||||
#include "util/config/ConfigDefinition.hpp"
|
||||
|
||||
@@ -114,6 +115,7 @@ ProductionHandlerProvider::ProductionHandlerProvider(
|
||||
{"tx", {.handler = TxHandler{backend, etl}}},
|
||||
{"subscribe", {.handler = SubscribeHandler{backend, amendmentCenter, subscriptionManager}}},
|
||||
{"unsubscribe", {.handler = UnsubscribeHandler{subscriptionManager}}},
|
||||
{"vault_info", {.handler = VaultInfoHandler{backend}}},
|
||||
{"version", {.handler = VersionHandler{config}}},
|
||||
}
|
||||
{
|
||||
|
||||
@@ -184,6 +184,11 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
);
|
||||
auto const seq = input.permissionedDomain->at(JS(seq)).as_int64();
|
||||
key = ripple::keylet::permissionedDomain(*account, seq).key;
|
||||
} else if (input.vault) {
|
||||
auto const account =
|
||||
ripple::parseBase58<ripple::AccountID>(boost::json::value_to<std::string>(input.vault->at(JS(owner))));
|
||||
auto const seq = input.vault->at(JS(seq)).as_int64();
|
||||
key = ripple::keylet::vault(*account, seq).key;
|
||||
} else if (input.delegate) {
|
||||
auto const account =
|
||||
ripple::parseBase58<ripple::AccountID>(boost::json::value_to<std::string>(input.delegate->at(JS(account))));
|
||||
@@ -214,13 +219,13 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
|
||||
|
||||
if (!ledgerObject || ledgerObject->empty()) {
|
||||
if (not input.includeDeleted)
|
||||
return Error{Status{"entryNotFound"}};
|
||||
return Error{Status{ClioError::RpcEntryNotFound}};
|
||||
auto const deletedSeq = sharedPtrBackend_->fetchLedgerObjectSeq(key, lgrInfo.seq, ctx.yield);
|
||||
if (!deletedSeq)
|
||||
return Error{Status{"entryNotFound"}};
|
||||
return Error{Status{ClioError::RpcEntryNotFound}};
|
||||
ledgerObject = sharedPtrBackend_->fetchLedgerObject(key, deletedSeq.value() - 1, ctx.yield);
|
||||
if (!ledgerObject || ledgerObject->empty())
|
||||
return Error{Status{"entryNotFound"}};
|
||||
return Error{Status{ClioError::RpcEntryNotFound}};
|
||||
output.deletedLedgerIndex = deletedSeq;
|
||||
}
|
||||
|
||||
@@ -326,6 +331,7 @@ tag_invoke(boost::json::value_to_tag<LedgerEntryHandler::Input>, boost::json::va
|
||||
{JS(credential), ripple::ltCREDENTIAL},
|
||||
{JS(mptoken), ripple::ltMPTOKEN},
|
||||
{JS(permissioned_domain), ripple::ltPERMISSIONED_DOMAIN},
|
||||
{JS(vault), ripple::ltVAULT},
|
||||
{JS(delegate), ripple::ltDELEGATE}
|
||||
};
|
||||
|
||||
@@ -415,6 +421,8 @@ tag_invoke(boost::json::value_to_tag<LedgerEntryHandler::Input>, boost::json::va
|
||||
input.mptoken = jv.at(JS(mptoken)).as_object();
|
||||
} else if (jsonObject.contains(JS(permissioned_domain))) {
|
||||
input.permissionedDomain = jv.at(JS(permissioned_domain)).as_object();
|
||||
} else if (jsonObject.contains(JS(vault))) {
|
||||
input.vault = jv.at(JS(vault)).as_object();
|
||||
} else if (jsonObject.contains(JS(delegate))) {
|
||||
input.delegate = jv.at(JS(delegate)).as_object();
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ public:
|
||||
std::optional<boost::json::object> amm;
|
||||
std::optional<boost::json::object> mptoken;
|
||||
std::optional<boost::json::object> permissionedDomain;
|
||||
std::optional<boost::json::object> vault;
|
||||
std::optional<ripple::STXChainBridge> bridge;
|
||||
std::optional<std::string> bridgeAccount;
|
||||
std::optional<uint32_t> chainClaimId;
|
||||
@@ -393,6 +394,23 @@ public:
|
||||
},
|
||||
},
|
||||
}}},
|
||||
{JS(vault),
|
||||
meta::WithCustomError{
|
||||
validation::Type<std::string, boost::json::object>{}, Status(ClioError::RpcMalformedRequest)
|
||||
},
|
||||
meta::IfType<std::string>{kMALFORMED_REQUEST_HEX_STRING_VALIDATOR},
|
||||
meta::IfType<boost::json::object>{meta::Section{
|
||||
{JS(seq),
|
||||
meta::WithCustomError{validation::Required{}, Status(ClioError::RpcMalformedRequest)},
|
||||
meta::WithCustomError{validation::Type<uint32_t>{}, Status(ClioError::RpcMalformedRequest)}},
|
||||
{
|
||||
JS(owner),
|
||||
meta::WithCustomError{validation::Required{}, Status(ClioError::RpcMalformedRequest)},
|
||||
meta::WithCustomError{
|
||||
validation::CustomValidators::accountBase58Validator, Status(ClioError::RpcMalformedOwner)
|
||||
},
|
||||
},
|
||||
}}},
|
||||
{JS(delegate),
|
||||
meta::WithCustomError{
|
||||
validation::Type<std::string, boost::json::object>{}, Status(ClioError::RpcMalformedRequest)
|
||||
|
||||
191
src/rpc/handlers/VaultInfo.cpp
Normal file
191
src/rpc/handlers/VaultInfo.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2025, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "rpc/handlers/VaultInfo.hpp"
|
||||
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/JS.hpp"
|
||||
#include "rpc/RPCHelpers.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
#include "util/Assert.hpp"
|
||||
|
||||
#include <boost/json/conversion.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/Indexes.h>
|
||||
#include <xrpl/protocol/Keylet.h>
|
||||
#include <xrpl/protocol/LedgerHeader.h>
|
||||
#include <xrpl/protocol/SField.h>
|
||||
#include <xrpl/protocol/STBase.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/Serializer.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace rpc {
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* @brief Ensures that the input contains either a `vaultID` alone, or both `owner` and `tnxSequence`.
|
||||
* Any other combination is considered malformed.
|
||||
*
|
||||
* @param input The input object containing optional fields for the vault request.
|
||||
* @return Returns true if the input is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
validate(VaultInfoHandler::Input const& input)
|
||||
{
|
||||
bool const hasVaultId = input.vaultID.has_value();
|
||||
bool const hasOwner = input.owner.has_value();
|
||||
bool const hasSeq = input.tnxSequence.has_value();
|
||||
|
||||
// Only valid combinations: (vaultID) or (owner + ledgerIndex)
|
||||
// NOLINTNEXTLINE(readability-simplify-boolean-expr)
|
||||
return (hasVaultId && !hasOwner && !hasSeq) || (!hasVaultId && hasOwner && hasSeq);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
VaultInfoHandler::VaultInfoHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
|
||||
: sharedPtrBackend_{sharedPtrBackend}
|
||||
{
|
||||
}
|
||||
|
||||
VaultInfoHandler::Result
|
||||
VaultInfoHandler::process(VaultInfoHandler::Input input, Context const& ctx) const
|
||||
{
|
||||
// vault info input must either have owner and sequence, or vault_id only.
|
||||
if (not validate(input))
|
||||
return Error{ClioError::RpcMalformedRequest};
|
||||
|
||||
auto const range = sharedPtrBackend_->fetchLedgerRange();
|
||||
ASSERT(range.has_value(), "VaultInfo's ledger range must be available");
|
||||
|
||||
auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
|
||||
*sharedPtrBackend_, ctx.yield, std::nullopt, input.ledgerIndex, range->maxSequence
|
||||
);
|
||||
|
||||
if (not expectedLgrInfo.has_value())
|
||||
return Error{expectedLgrInfo.error()};
|
||||
|
||||
auto const& lgrInfo = *expectedLgrInfo;
|
||||
|
||||
// Extract the vault keylet based on input
|
||||
auto const vaultKeylet = [&]() -> std::expected<ripple::Keylet, Status> {
|
||||
if (input.owner && input.tnxSequence) {
|
||||
auto const accountStr = *input.owner;
|
||||
auto const accountID = accountFromStringStrict(accountStr);
|
||||
|
||||
// checks that account exists
|
||||
{
|
||||
auto const accountKeylet = ripple::keylet::account(*accountID);
|
||||
auto const accountLedgerObject =
|
||||
sharedPtrBackend_->fetchLedgerObject(accountKeylet.key, lgrInfo.seq, ctx.yield);
|
||||
|
||||
if (!accountLedgerObject)
|
||||
return std::unexpected{Status{ClioError::RpcEntryNotFound}};
|
||||
}
|
||||
|
||||
return ripple::keylet::vault(*accountID, *input.tnxSequence);
|
||||
}
|
||||
ripple::uint256 nodeIndex;
|
||||
if (nodeIndex.parseHex(*input.vaultID))
|
||||
return ripple::keylet::vault(nodeIndex);
|
||||
|
||||
return std::unexpected{Status{ClioError::RpcEntryNotFound}};
|
||||
}();
|
||||
|
||||
if (not vaultKeylet.has_value())
|
||||
return Error{vaultKeylet.error()};
|
||||
|
||||
// Fetch the vault object and it's associated issuance ID
|
||||
auto const vaultLedgerObject =
|
||||
sharedPtrBackend_->fetchLedgerObject(vaultKeylet.value().key, lgrInfo.seq, ctx.yield);
|
||||
|
||||
if (not vaultLedgerObject)
|
||||
return Error{Status{ClioError::RpcEntryNotFound, "vault object not found."}};
|
||||
|
||||
ripple::STLedgerEntry const vaultSle{
|
||||
ripple::SerialIter{vaultLedgerObject->data(), vaultLedgerObject->size()}, vaultKeylet.value().key
|
||||
};
|
||||
|
||||
auto const issuanceKeylet = ripple::keylet::mptIssuance(vaultSle[ripple::sfShareMPTID]).key;
|
||||
auto const issuanceObject = sharedPtrBackend_->fetchLedgerObject(issuanceKeylet, lgrInfo.seq, ctx.yield);
|
||||
|
||||
if (not issuanceObject)
|
||||
return Error{Status{ClioError::RpcEntryNotFound, "issuance object not found."}};
|
||||
|
||||
ripple::STLedgerEntry const issuanceSle{
|
||||
ripple::SerialIter{issuanceObject->data(), issuanceObject->size()}, issuanceKeylet
|
||||
};
|
||||
|
||||
// put issuance object into "shares" field of vault object
|
||||
// follows same logic as rippled:
|
||||
// https://github.com/XRPLF/rippled/pull/5224/files#diff-6cb544622c7942261f097d628f61f1c1fcf34a1bcfd954aedbada4238fc28f69R107
|
||||
Output response;
|
||||
response.vault = toBoostJson(vaultSle.getJson(ripple::JsonOptions::none));
|
||||
response.vault.as_object()[JS(shares)] = toBoostJson(issuanceSle.getJson(ripple::JsonOptions::none));
|
||||
response.ledgerIndex = lgrInfo.seq;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void
|
||||
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, VaultInfoHandler::Output const& output)
|
||||
{
|
||||
jv = boost::json::object{
|
||||
{JS(ledger_index), output.ledgerIndex}, {JS(validated), output.validated}, {JS(vault), output.vault}
|
||||
};
|
||||
}
|
||||
|
||||
VaultInfoHandler::Input
|
||||
tag_invoke(boost::json::value_to_tag<VaultInfoHandler::Input>, boost::json::value const& jv)
|
||||
{
|
||||
auto input = VaultInfoHandler::Input{};
|
||||
auto const& jsonObject = jv.as_object();
|
||||
|
||||
if (jsonObject.contains(JS(owner)))
|
||||
input.owner = jsonObject.at(JS(owner)).as_string();
|
||||
|
||||
if (jsonObject.contains(JS(seq)))
|
||||
input.tnxSequence = static_cast<uint32_t>(jsonObject.at(JS(seq)).as_int64());
|
||||
|
||||
if (jsonObject.contains(JS(vault_id)))
|
||||
input.vaultID = jsonObject.at(JS(vault_id)).as_string();
|
||||
|
||||
if (jsonObject.contains(JS(ledger_index))) {
|
||||
if (not jsonObject.at(JS(ledger_index)).is_string()) {
|
||||
input.ledgerIndex = jsonObject.at(JS(ledger_index)).as_int64();
|
||||
} else if (jsonObject.at(JS(ledger_index)).as_string() != "validated") {
|
||||
input.ledgerIndex = std::stoi(jsonObject.at(JS(ledger_index)).as_string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
} // namespace rpc
|
||||
134
src/rpc/handlers/VaultInfo.hpp
Normal file
134
src/rpc/handlers/VaultInfo.hpp
Normal file
@@ -0,0 +1,134 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2025, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/JS.hpp"
|
||||
#include "rpc/common/MetaProcessors.hpp"
|
||||
#include "rpc/common/Specs.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
#include "rpc/common/Validators.hpp"
|
||||
|
||||
#include <boost/json/conversion.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace rpc {
|
||||
|
||||
/**
|
||||
* @brief The vault_info command retrieves information about a vault, currency, shares etc.
|
||||
*/
|
||||
class VaultInfoHandler {
|
||||
std::shared_ptr<BackendInterface> sharedPtrBackend_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new VaultInfo object
|
||||
*
|
||||
* @param sharedPtrBackend The backend to use
|
||||
*/
|
||||
VaultInfoHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend);
|
||||
|
||||
/**
|
||||
* @brief A struct to hold the input data for the command
|
||||
*/
|
||||
struct Input {
|
||||
std::optional<std::string> vaultID;
|
||||
std::optional<std::string> owner;
|
||||
std::optional<uint32_t> tnxSequence;
|
||||
std::optional<uint32_t> ledgerIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A struct to hold the output data for the command
|
||||
*/
|
||||
struct Output {
|
||||
boost::json::value vault;
|
||||
uint32_t ledgerIndex{};
|
||||
bool validated = true;
|
||||
};
|
||||
|
||||
using Result = HandlerReturnType<Output>;
|
||||
|
||||
/**
|
||||
* @brief Returns the API specification for the command
|
||||
*
|
||||
* @param apiVersion The api version to return the spec for
|
||||
* @return The spec for the given apiVersion
|
||||
*/
|
||||
static RpcSpecConstRef
|
||||
spec([[maybe_unused]] uint32_t apiVersion)
|
||||
{
|
||||
static auto const kRPC_SPEC = RpcSpec{
|
||||
{JS(vault_id),
|
||||
meta::WithCustomError{
|
||||
validation::CustomValidators::uint256HexStringValidator, Status(ClioError::RpcMalformedRequest)
|
||||
}},
|
||||
{JS(owner),
|
||||
meta::WithCustomError{
|
||||
validation::CustomValidators::accountBase58Validator,
|
||||
Status(ClioError::RpcMalformedRequest, "OwnerNotHexString")
|
||||
}},
|
||||
{JS(seq), meta::WithCustomError{validation::Type<uint32_t>{}, Status(ClioError::RpcMalformedRequest)}},
|
||||
{JS(ledger_index), validation::CustomValidators::ledgerIndexValidator},
|
||||
};
|
||||
|
||||
return kRPC_SPEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process the VaultInfo command
|
||||
*
|
||||
* @param input The input data for the command
|
||||
* @param ctx The context of the request
|
||||
* @return The result of the operation
|
||||
*/
|
||||
Result
|
||||
process(Input input, Context const& ctx) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Convert the Output to a JSON object
|
||||
*
|
||||
* @param jv The JSON object to convert to
|
||||
* @param output The output to convert
|
||||
*/
|
||||
friend void
|
||||
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output);
|
||||
|
||||
/**
|
||||
* @brief Convert a JSON object to Input type
|
||||
*
|
||||
* @param jv The JSON object to convert
|
||||
* @return Input parsed from the JSON object
|
||||
*/
|
||||
friend Input
|
||||
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
|
||||
};
|
||||
|
||||
} // namespace rpc
|
||||
@@ -114,6 +114,7 @@ class LedgerTypes {
|
||||
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),
|
||||
|
||||
@@ -91,6 +91,7 @@ public:
|
||||
case rpc::ClioError::RpcFieldNotFoundTransaction:
|
||||
case rpc::ClioError::RpcMalformedOracleDocumentId:
|
||||
case rpc::ClioError::RpcMalformedAuthorizedCredentials:
|
||||
case rpc::ClioError::RpcEntryNotFound:
|
||||
case rpc::ClioError::EtlConnectionError:
|
||||
case rpc::ClioError::EtlRequestError:
|
||||
case rpc::ClioError::EtlRequestTimeout:
|
||||
|
||||
@@ -105,6 +105,7 @@ ErrorHelper::makeError(rpc::Status const& err) const
|
||||
case rpc::ClioError::RpcFieldNotFoundTransaction:
|
||||
case rpc::ClioError::RpcMalformedOracleDocumentId:
|
||||
case rpc::ClioError::RpcMalformedAuthorizedCredentials:
|
||||
case rpc::ClioError::RpcEntryNotFound:
|
||||
case rpc::ClioError::EtlConnectionError:
|
||||
case rpc::ClioError::EtlRequestError:
|
||||
case rpc::ClioError::EtlRequestTimeout:
|
||||
|
||||
Reference in New Issue
Block a user