Add missing doxygen comments (#1223)

Fixes #1218
This commit is contained in:
Alex Kremer
2024-03-01 15:58:18 +00:00
committed by GitHub
parent b3e63b2491
commit a74970b81e
125 changed files with 2755 additions and 365 deletions

View File

@@ -2,8 +2,18 @@ PROJECT_NAME = "Clio"
PROJECT_LOGO = ../docs/img/xrpl-logo.svg PROJECT_LOGO = ../docs/img/xrpl-logo.svg
PROJECT_NUMBER = @DOC_CLIO_VERSION@ PROJECT_NUMBER = @DOC_CLIO_VERSION@
PROJECT_BRIEF = The XRP Ledger API server. PROJECT_BRIEF = The XRP Ledger API server.
INPUT = ../src ../unittests
EXCLUDE_PATTERNS = *Test*.cpp *Test*.hpp */impl/* EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = NO
EXTRACT_ANON_NSPACES = NO
SORT_MEMBERS_CTORS_1ST = YES
INPUT = ../src
EXCLUDE_SYMBOLS = impl
RECURSIVE = YES RECURSIVE = YES
HAVE_DOT = YES HAVE_DOT = YES
@@ -12,7 +22,6 @@ WARNINGS = YES
WARN_NO_PARAMDOC = YES WARN_NO_PARAMDOC = YES
WARN_IF_INCOMPLETE_DOC = YES WARN_IF_INCOMPLETE_DOC = YES
WARN_IF_UNDOCUMENTED = YES WARN_IF_UNDOCUMENTED = YES
WARN_AS_ERROR = FAIL_ON_WARNINGS
GENERATE_LATEX = NO GENERATE_LATEX = NO
GENERATE_HTML = YES GENERATE_HTML = YES

View File

@@ -83,39 +83,92 @@ class BackendCounters {
public: public:
using PtrType = std::shared_ptr<BackendCounters>; using PtrType = std::shared_ptr<BackendCounters>;
/**
* @brief Create a new BackendCounters object
*
* @return A shared pointer to the new BackendCounters object
*/
static PtrType static PtrType
make(); make();
/**
* @brief Register that the backend was too busy to process a request
*/
void void
registerTooBusy(); registerTooBusy();
/**
* @brief Register that a write operation was started
*
* @param startTime The time the operation was started
*/
void void
registerWriteSync(std::chrono::steady_clock::time_point startTime); registerWriteSync(std::chrono::steady_clock::time_point startTime);
/**
* @brief Register that a write operation was retried
*/
void void
registerWriteSyncRetry(); registerWriteSyncRetry();
/**
* @brief Register that a write operation was started
*/
void void
registerWriteStarted(); registerWriteStarted();
/**
* @brief Register that a write operation was finished
*
* @param startTime The time the operation was started
*/
void void
registerWriteFinished(std::chrono::steady_clock::time_point startTime); registerWriteFinished(std::chrono::steady_clock::time_point startTime);
/**
* @brief Register that a write operation was retried
*/
void void
registerWriteRetry(); registerWriteRetry();
/**
* @brief Register that one or more read operations were started
*
* @param count The number of operations started
*/
void void
registerReadStarted(std::uint64_t count = 1u); registerReadStarted(std::uint64_t count = 1u);
/**
* @brief Register that one or more read operations were finished
*
* @param startTime The time the operations were started
* @param count The number of operations finished
*/
void void
registerReadFinished(std::chrono::steady_clock::time_point startTime, std::uint64_t count = 1u); registerReadFinished(std::chrono::steady_clock::time_point startTime, std::uint64_t count = 1u);
/**
* @brief Register that one or more read operations were retried
*
* @param count The number of operations retried
*/
void void
registerReadRetry(std::uint64_t count = 1u); registerReadRetry(std::uint64_t count = 1u);
/**
* @brief Register that one or more read operations had an error
*
* @param count The number of operations with an error
*/
void void
registerReadError(std::uint64_t count = 1u); registerReadError(std::uint64_t count = 1u);
/**
* @brief Get a report of the backend counters
*
* @return The report
*/
boost::json::object boost::json::object
report() const; report() const;

View File

@@ -53,6 +53,9 @@ namespace data {
*/ */
class DatabaseTimeout : public std::exception { class DatabaseTimeout : public std::exception {
public: public:
/**
* @return The error message as a C string
*/
char const* char const*
what() const throw() override what() const throw() override
{ {
@@ -67,9 +70,9 @@ static constexpr std::size_t DEFAULT_WAIT_BETWEEN_RETRY = 500;
* @tparam FnType The type of function object to execute * @tparam FnType The type of function object to execute
* @param func The function object to execute * @param func The function object to execute
* @param waitMs Delay between retry attempts * @param waitMs Delay between retry attempts
* @return auto The same as the return type of func * @return The same as the return type of func
*/ */
template <class FnType> template <typename FnType>
auto auto
retryOnTimeout(FnType func, size_t waitMs = DEFAULT_WAIT_BETWEEN_RETRY) retryOnTimeout(FnType func, size_t waitMs = DEFAULT_WAIT_BETWEEN_RETRY)
{ {
@@ -90,9 +93,9 @@ retryOnTimeout(FnType func, size_t waitMs = DEFAULT_WAIT_BETWEEN_RETRY)
* *
* @tparam FnType The type of function object to execute * @tparam FnType The type of function object to execute
* @param func The function object to execute * @param func The function object to execute
* @return auto The same as the return type of func * @return The same as the return type of func
*/ */
template <class FnType> template <typename FnType>
auto auto
synchronous(FnType&& func) synchronous(FnType&& func)
{ {
@@ -118,9 +121,9 @@ synchronous(FnType&& func)
* *
* @tparam FnType The type of function object to execute * @tparam FnType The type of function object to execute
* @param func The function object to execute * @param func The function object to execute
* @return auto The same as the return type of func * @return The same as the return type of func
*/ */
template <class FnType> template <typename FnType>
auto auto
synchronousAndRetryOnTimeout(FnType&& func) synchronousAndRetryOnTimeout(FnType&& func)
{ {
@@ -219,7 +222,7 @@ public:
* *
* @param seq The sequence to fetch for * @param seq The sequence to fetch for
* @param yield The coroutine context * @param yield The coroutine context
* @return ripple::Fees if fees are found; nullopt otherwise * @return Fees if fees are found; nullopt otherwise
*/ */
std::optional<ripple::Fees> std::optional<ripple::Fees>
fetchFees(std::uint32_t seq, boost::asio::yield_context yield) const; fetchFees(std::uint32_t seq, boost::asio::yield_context yield) const;
@@ -318,12 +321,11 @@ public:
* *
* @param issuer AccountID of issuer you wish you query. * @param issuer AccountID of issuer you wish you query.
* @param taxon Optional taxon of NFTs by which you wish to filter. * @param taxon Optional taxon of NFTs by which you wish to filter.
* @param ledgerSequence The ledger sequence to fetch for
* @param limit Paging limit. * @param limit Paging limit.
* @param cursorIn Optional cursor to allow us to pick up from where we * @param cursorIn Optional cursor to allow us to pick up from where we last left off.
* last left off.
* @param yield Currently executing coroutine. * @param yield Currently executing coroutine.
* @return std::vector<NFT> of NFTs issued by this account, or * @return NFTs issued by this account, or this issuer/taxon combination if taxon is passed and an optional marker
* this issuer/taxon combination if taxon is passed and an optional marker
*/ */
virtual NFTsAndCursor virtual NFTsAndCursor
fetchNFTsByIssuer( fetchNFTsByIssuer(
@@ -488,6 +490,7 @@ public:
/** /**
* @brief Fetches the ledger range from DB. * @brief Fetches the ledger range from DB.
* *
* @param yield The coroutine context
* @return The ledger range if available; nullopt otherwise * @return The ledger range if available; nullopt otherwise
*/ */
virtual std::optional<LedgerRange> virtual std::optional<LedgerRange>
@@ -598,15 +601,27 @@ public:
isTooBusy() const = 0; isTooBusy() const = 0;
/** /**
* @return json object containing backend usage statistics * @return A JSON object containing backend usage statistics
*/ */
virtual boost::json::object virtual boost::json::object
stats() const = 0; stats() const = 0;
private: private:
/**
* @brief Writes a ledger object to the database
*
* @param key The key of the object
* @param seq The sequence of the ledger
* @param blob The data
*/
virtual void virtual void
doWriteLedgerObject(std::string&& key, std::uint32_t seq, std::string&& blob) = 0; doWriteLedgerObject(std::string&& key, std::uint32_t seq, std::string&& blob) = 0;
/**
* @brief The implementation should wait for all pending writes to finish
*
* @return true on success; false otherwise
*/
virtual bool virtual bool
doFinishWrites() = 0; doFinishWrites() = 0;
}; };

View File

@@ -48,6 +48,12 @@ struct AccountTransactionsData {
std::uint32_t transactionIndex{}; std::uint32_t transactionIndex{};
ripple::uint256 txHash; ripple::uint256 txHash;
/**
* @brief Construct a new AccountTransactionsData object
*
* @param meta The transaction metadata
* @param txHash The transaction hash
*/
AccountTransactionsData(ripple::TxMeta& meta, ripple::uint256 const& txHash) AccountTransactionsData(ripple::TxMeta& meta, ripple::uint256 const& txHash)
: accounts(meta.getAffectedAccounts()) : accounts(meta.getAffectedAccounts())
, ledgerSequence(meta.getLgrSeq()) , ledgerSequence(meta.getLgrSeq())
@@ -70,6 +76,13 @@ struct NFTTransactionsData {
std::uint32_t transactionIndex; std::uint32_t transactionIndex;
ripple::uint256 txHash; ripple::uint256 txHash;
/**
* @brief Construct a new NFTTransactionsData object
*
* @param tokenID The token ID
* @param meta The transaction metadata
* @param txHash The transaction hash
*/
NFTTransactionsData(ripple::uint256 const& tokenID, ripple::TxMeta const& meta, ripple::uint256 const& txHash) NFTTransactionsData(ripple::uint256 const& tokenID, ripple::TxMeta const& meta, ripple::uint256 const& txHash)
: tokenID(tokenID), ledgerSequence(meta.getLgrSeq()), transactionIndex(meta.getIndex()), txHash(txHash) : tokenID(tokenID), ledgerSequence(meta.getLgrSeq()), transactionIndex(meta.getIndex()), txHash(txHash)
{ {
@@ -80,35 +93,33 @@ struct NFTTransactionsData {
* @brief Represents an NFT state at a particular ledger. * @brief Represents an NFT state at a particular ledger.
* *
* Gets written to nf_tokens table and the like. * Gets written to nf_tokens table and the like.
*
* The transaction index is only stored because we want to store only the final state of an NFT per ledger.
* Since we pull this from transactions we keep track of which tx index created this so we can de-duplicate, as it is
* possible for one ledger to have multiple txs that change the state of the same NFT.
*
* We only set the uri if this is a mint tx, or if we are loading initial state from NFTokenPage objects.
*/ */
struct NFTsData { struct NFTsData {
ripple::uint256 tokenID; ripple::uint256 tokenID;
std::uint32_t ledgerSequence; std::uint32_t ledgerSequence;
// The transaction index is only stored because we want to store only the
// final state of an NFT per ledger. Since we pull this from transactions
// we keep track of which tx index created this so we can de-duplicate, as
// it is possible for one ledger to have multiple txs that change the
// state of the same NFT. This field is not applicable when we are loading
// initial NFT state via ledger objects, since we do not have to tiebreak
// NFT state for a given ledger in that case.
std::optional<std::uint32_t> transactionIndex; std::optional<std::uint32_t> transactionIndex;
ripple::AccountID owner; ripple::AccountID owner;
// We only set the uri if this is a mint tx, or if we are
// loading initial state from NFTokenPage objects. In other words,
// uri should only be set if the etl process believes this NFT hasn't
// been seen before in our local database. We do this so that we don't
// write to the the nf_token_uris table every
// time the same NFT changes hands. We also can infer if there is a URI
// that we need to write to the issuer_nf_tokens table.
std::optional<ripple::Blob> uri; std::optional<ripple::Blob> uri;
bool isBurned = false; bool isBurned = false;
// This constructor is used when parsing an NFTokenMint tx. /**
// Unfortunately because of the extreme edge case of being able to * @brief Construct a new NFTsData object
// re-mint an NFT with the same ID, we must explicitly record a null *
// URI. For this reason, we _always_ write this field as a result of * @note This constructor is used when parsing an NFTokenMint tx
// this tx. * Unfortunately because of the extreme edge case of being able to re-mint an NFT with the same ID, we must
* explicitly record a null URI. For this reason, we _always_ write this field as a result of this tx.
*
* @param tokenID The token ID
* @param owner The owner
* @param uri The URI
* @param meta The transaction metadata
*/
NFTsData( NFTsData(
ripple::uint256 const& tokenID, ripple::uint256 const& tokenID,
ripple::AccountID const& owner, ripple::AccountID const& owner,
@@ -119,8 +130,16 @@ struct NFTsData {
{ {
} }
// This constructor is used when parsing an NFTokenBurn or /**
// NFTokenAcceptOffer tx * @brief Construct a new NFTsData object
*
* @note This constructor is used when parsing an NFTokenBurn or NFTokenAcceptOffer tx
*
* @param tokenID The token ID
* @param owner The owner
* @param meta The transaction metadata
* @param isBurned Whether the NFT is burned
*/
NFTsData(ripple::uint256 const& tokenID, ripple::AccountID const& owner, ripple::TxMeta const& meta, bool isBurned) NFTsData(ripple::uint256 const& tokenID, ripple::AccountID const& owner, ripple::TxMeta const& meta, bool isBurned)
: tokenID(tokenID) : tokenID(tokenID)
, ledgerSequence(meta.getLgrSeq()) , ledgerSequence(meta.getLgrSeq())
@@ -130,12 +149,18 @@ struct NFTsData {
{ {
} }
// This constructor is used when parsing an NFTokenPage directly from /**
// ledger state. * @brief Construct a new NFTsData object
// Unfortunately because of the extreme edge case of being able to *
// re-mint an NFT with the same ID, we must explicitly record a null * @note This constructor is used when parsing an NFTokenPage directly from ledger state.
// URI. For this reason, we _always_ write this field as a result of * Unfortunately because of the extreme edge case of being able to re-mint an NFT with the same ID, we must
// this tx. * explicitly record a null URI. For this reason, we _always_ write this field as a result of this tx.
*
* @param tokenID The token ID
* @param ledgerSequence The ledger sequence
* @param owner The owner
* @param uri The URI
*/
NFTsData( NFTsData(
ripple::uint256 const& tokenID, ripple::uint256 const& tokenID,
std::uint32_t const ledgerSequence, std::uint32_t const ledgerSequence,
@@ -153,7 +178,7 @@ struct NFTsData {
* @param object The object to check * @param object The object to check
* @return true if the object is an offer; false otherwise * @return true if the object is an offer; false otherwise
*/ */
template <class T> template <typename T>
inline bool inline bool
isOffer(T const& object) isOffer(T const& object)
{ {
@@ -170,7 +195,7 @@ isOffer(T const& object)
* @param object The object to check * @param object The object to check
* @return true if the object is an offer; false otherwise * @return true if the object is an offer; false otherwise
*/ */
template <class T> template <typename T>
inline bool inline bool
isOfferHex(T const& object) isOfferHex(T const& object)
{ {
@@ -186,7 +211,7 @@ isOfferHex(T const& object)
* @param object The object to check * @param object The object to check
* @return true if the object is a dir node; false otherwise * @return true if the object is a dir node; false otherwise
*/ */
template <class T> template <typename T>
inline bool inline bool
isDirNode(T const& object) isDirNode(T const& object)
{ {
@@ -202,7 +227,7 @@ isDirNode(T const& object)
* @param object The object to check * @param object The object to check
* @return true if the object is a book dir; false otherwise * @return true if the object is a book dir; false otherwise
*/ */
template <class T, class R> template <typename T, typename R>
inline bool inline bool
isBookDir(T const& key, R const& object) isBookDir(T const& key, R const& object)
{ {
@@ -219,7 +244,7 @@ isBookDir(T const& key, R const& object)
* @param offer The offer to get the book for * @param offer The offer to get the book for
* @return Book as ripple::uint256 * @return Book as ripple::uint256
*/ */
template <class T> template <typename T>
inline ripple::uint256 inline ripple::uint256
getBook(T const& offer) getBook(T const& offer)
{ {
@@ -236,7 +261,7 @@ getBook(T const& offer)
* @param key The key to get the book base out of * @param key The key to get the book base out of
* @return Book base as ripple::uint256 * @return Book base as ripple::uint256
*/ */
template <class T> template <typename T>
inline ripple::uint256 inline ripple::uint256
getBookBase(T const& key) getBookBase(T const& key)
{ {

View File

@@ -173,6 +173,11 @@ public:
float float
getSuccessorHitRate() const; getSuccessorHitRate() const;
/**
* @brief Waits until the cache contains a specific sequence.
*
* @param seq The sequence to wait for
*/
void void
waitUntilCacheContainsSeq(uint32_t seq); waitUntilCacheContainsSeq(uint32_t seq);
}; };

View File

@@ -41,10 +41,7 @@ struct LedgerObject {
Blob blob; Blob blob;
bool bool
operator==(LedgerObject const& other) const operator==(LedgerObject const& other) const = default;
{
return key == other.key && blob == other.blob;
}
}; };
/** /**
@@ -73,11 +70,25 @@ struct TransactionAndMetadata {
std::uint32_t date = 0; std::uint32_t date = 0;
TransactionAndMetadata() = default; TransactionAndMetadata() = default;
/**
* @brief Construct a new Transaction And Metadata object
*
* @param transaction The transaction
* @param metadata The metadata
* @param ledgerSequence The ledger sequence
* @param date The date
*/
TransactionAndMetadata(Blob transaction, Blob metadata, std::uint32_t ledgerSequence, std::uint32_t date) TransactionAndMetadata(Blob transaction, Blob metadata, std::uint32_t ledgerSequence, std::uint32_t date)
: transaction{std::move(transaction)}, metadata{std::move(metadata)}, ledgerSequence{ledgerSequence}, date{date} : transaction{std::move(transaction)}, metadata{std::move(metadata)}, ledgerSequence{ledgerSequence}, date{date}
{ {
} }
/**
* @brief Construct a new Transaction And Metadata object
*
* @param data The data to construct from
*/
TransactionAndMetadata(std::tuple<Blob, Blob, std::uint32_t, std::uint32_t> data) TransactionAndMetadata(std::tuple<Blob, Blob, std::uint32_t, std::uint32_t> data)
: transaction{std::get<0>(data)} : transaction{std::get<0>(data)}
, metadata{std::get<1>(data)} , metadata{std::get<1>(data)}
@@ -86,6 +97,12 @@ struct TransactionAndMetadata {
{ {
} }
/**
* @brief Check if the transaction and metadata are the same as another
*
* @param other The other transaction and metadata
* @return true if they are the same; false otherwise
*/
bool bool
operator==(TransactionAndMetadata const& other) const operator==(TransactionAndMetadata const& other) const
{ {
@@ -102,11 +119,23 @@ struct TransactionsCursor {
std::uint32_t transactionIndex = 0; std::uint32_t transactionIndex = 0;
TransactionsCursor() = default; TransactionsCursor() = default;
/**
* @brief Construct a new Transactions Cursor object
*
* @param ledgerSequence The ledger sequence
* @param transactionIndex The transaction index
*/
TransactionsCursor(std::uint32_t ledgerSequence, std::uint32_t transactionIndex) TransactionsCursor(std::uint32_t ledgerSequence, std::uint32_t transactionIndex)
: ledgerSequence{ledgerSequence}, transactionIndex{transactionIndex} : ledgerSequence{ledgerSequence}, transactionIndex{transactionIndex}
{ {
} }
/**
* @brief Construct a new Transactions Cursor object
*
* @param data The data to construct from
*/
TransactionsCursor(std::tuple<std::uint32_t, std::uint32_t> data) TransactionsCursor(std::tuple<std::uint32_t, std::uint32_t> data)
: ledgerSequence{std::get<0>(data)}, transactionIndex{std::get<1>(data)} : ledgerSequence{std::get<0>(data)}, transactionIndex{std::get<1>(data)}
{ {
@@ -115,6 +144,11 @@ struct TransactionsCursor {
bool bool
operator==(TransactionsCursor const& other) const = default; operator==(TransactionsCursor const& other) const = default;
/**
* @brief Convert the cursor to a tuple of seq and index
*
* @return The cursor as a tuple
*/
[[nodiscard]] std::tuple<std::uint32_t, std::uint32_t> [[nodiscard]] std::tuple<std::uint32_t, std::uint32_t>
asTuple() const asTuple() const
{ {
@@ -141,6 +175,16 @@ struct NFT {
bool isBurned{}; bool isBurned{};
NFT() = default; NFT() = default;
/**
* @brief Construct a new NFT object
*
* @param tokenID The token ID
* @param ledgerSequence The ledger sequence
* @param owner The owner
* @param uri The URI
* @param isBurned Whether the token is burned
*/
NFT(ripple::uint256 const& tokenID, NFT(ripple::uint256 const& tokenID,
std::uint32_t ledgerSequence, std::uint32_t ledgerSequence,
ripple::AccountID const& owner, ripple::AccountID const& owner,
@@ -150,13 +194,28 @@ struct NFT {
{ {
} }
/**
* @brief Construct a new NFT object
*
* @param tokenID The token ID
* @param ledgerSequence The ledger sequence
* @param owner The owner
* @param isBurned Whether the token is burned
*/
NFT(ripple::uint256 const& tokenID, std::uint32_t ledgerSequence, ripple::AccountID const& owner, bool isBurned) NFT(ripple::uint256 const& tokenID, std::uint32_t ledgerSequence, ripple::AccountID const& owner, bool isBurned)
: NFT(tokenID, ledgerSequence, owner, {}, isBurned) : NFT(tokenID, ledgerSequence, owner, {}, isBurned)
{ {
} }
// clearly two tokens are the same if they have the same ID, but this struct stores the state of a given token at a /**
// given ledger sequence, so we also need to compare with ledgerSequence. * @brief Check if the NFT is the same as another
*
* Clearly two tokens are the same if they have the same ID, but this struct stores the state of a given
* token at a given ledger sequence, so we also need to compare with ledgerSequence.
*
* @param other The other NFT
* @return true if they are the same; false otherwise
*/
bool bool
operator==(NFT const& other) const operator==(NFT const& other) const
{ {
@@ -164,6 +223,9 @@ struct NFT {
} }
}; };
/**
* @brief Represents a bundle of NFTs with a cursor to the next page
*/
struct NFTsAndCursor { struct NFTsAndCursor {
std::vector<NFT> nfts; std::vector<NFT> nfts;
std::optional<ripple::uint256> cursor; std::optional<ripple::uint256> cursor;

View File

@@ -36,11 +36,20 @@ class CassandraError {
uint32_t code_{}; uint32_t code_{};
public: public:
CassandraError() = default; // default constructible required by Expected // default constructible required by Expected
CassandraError() = default;
/**
* @brief Construct a new CassandraError object
*
* @param message The error message
* @param code The error code
*/
CassandraError(std::string message, uint32_t code) : message_{std::move(message)}, code_{code} CassandraError(std::string message, uint32_t code) : message_{std::move(message)}, code_{code}
{ {
} }
/** @cond */
template <typename T> template <typename T>
friend std::string friend std::string
operator+(T const& lhs, CassandraError const& rhs) operator+(T const& lhs, CassandraError const& rhs)
@@ -70,6 +79,7 @@ public:
os << err.message(); os << err.message();
return os; return os;
} }
/** @endcond */
/** /**
* @return The final error message as a std::string * @return The final error message as a std::string

View File

@@ -96,7 +96,7 @@ Handle::reconnect(std::string_view keyspace) const
} }
std::vector<Handle::FutureType> std::vector<Handle::FutureType>
Handle::asyncExecuteEach(std::vector<Statement> const& statements) const Handle::asyncExecuteEach(std::vector<StatementType> const& statements) const
{ {
std::vector<Handle::FutureType> futures; std::vector<Handle::FutureType> futures;
futures.reserve(statements.size()); futures.reserve(statements.size());
@@ -106,7 +106,7 @@ Handle::asyncExecuteEach(std::vector<Statement> const& statements) const
} }
Handle::MaybeErrorType Handle::MaybeErrorType
Handle::executeEach(std::vector<Statement> const& statements) const Handle::executeEach(std::vector<StatementType> const& statements) const
{ {
for (auto futures = asyncExecuteEach(statements); auto const& future : futures) { for (auto futures = asyncExecuteEach(statements); auto const& future : futures) {
if (auto rc = future.await(); not rc) if (auto rc = future.await(); not rc)
@@ -117,38 +117,37 @@ Handle::executeEach(std::vector<Statement> const& statements) const
} }
Handle::FutureType Handle::FutureType
Handle::asyncExecute(Statement const& statement) const Handle::asyncExecute(StatementType const& statement) const
{ {
return cass_session_execute(session_, statement); return cass_session_execute(session_, statement);
} }
Handle::FutureWithCallbackType Handle::FutureWithCallbackType
Handle::asyncExecute(Statement const& statement, std::function<void(Handle::ResultOrErrorType)>&& cb) const Handle::asyncExecute(StatementType const& statement, std::function<void(ResultOrErrorType)>&& cb) const
{ {
return Handle::FutureWithCallbackType{cass_session_execute(session_, statement), std::move(cb)}; return Handle::FutureWithCallbackType{cass_session_execute(session_, statement), std::move(cb)};
} }
Handle::ResultOrErrorType Handle::ResultOrErrorType
Handle::execute(Statement const& statement) const Handle::execute(StatementType const& statement) const
{ {
return asyncExecute(statement).get(); return asyncExecute(statement).get();
} }
Handle::FutureType Handle::FutureType
Handle::asyncExecute(std::vector<Statement> const& statements) const Handle::asyncExecute(std::vector<StatementType> const& statements) const
{ {
return cass_session_execute_batch(session_, Batch{statements}); return cass_session_execute_batch(session_, Batch{statements});
} }
Handle::MaybeErrorType Handle::MaybeErrorType
Handle::execute(std::vector<Statement> const& statements) const Handle::execute(std::vector<StatementType> const& statements) const
{ {
return asyncExecute(statements).await(); return asyncExecute(statements).await();
} }
Handle::FutureWithCallbackType Handle::FutureWithCallbackType
Handle::asyncExecute(std::vector<Statement> const& statements, std::function<void(Handle::ResultOrErrorType)>&& cb) Handle::asyncExecute(std::vector<StatementType> const& statements, std::function<void(ResultOrErrorType)>&& cb) const
const
{ {
return Handle::FutureWithCallbackType{cass_session_execute_batch(session_, Batch{statements}), std::move(cb)}; return Handle::FutureWithCallbackType{cass_session_execute_batch(session_, Batch{statements}), std::move(cb)};
} }

View File

@@ -35,6 +35,9 @@
#include <string_view> #include <string_view>
#include <vector> #include <vector>
/**
* @brief This namespace implements a wrapper for the Cassandra C++ driver
*/
namespace data::cassandra { namespace data::cassandra {
/** /**
@@ -54,7 +57,7 @@ public:
using ResultType = Result; using ResultType = Result;
/** /**
* @brief Construct a new handle from a @ref impl::Settings object. * @brief Construct a new handle from a Settings object.
* *
* @param clusterSettings The settings to use * @param clusterSettings The settings to use
*/ */
@@ -317,7 +320,9 @@ public:
* You can call .begin() and .end() in order to iterate as usual. * You can call .begin() and .end() in order to iterate as usual.
* This also means that you can use it in a range-based for or with some algorithms. * This also means that you can use it in a range-based for or with some algorithms.
* *
* @tparam Types The types to extract
* @param result The result to iterate * @param result The result to iterate
* @return An extractor object (iterator inside)
*/ */
template <typename... Types> template <typename... Types>
[[nodiscard]] impl::ResultExtractor<Types...> [[nodiscard]] impl::ResultExtractor<Types...>

View File

@@ -34,6 +34,14 @@
namespace data::cassandra { namespace data::cassandra {
/**
* @brief Returns the table name qualified with the keyspace and table prefix
*
* @tparam SettingsProviderType The settings provider type
* @param provider The settings provider
* @param name The name of the table
* @return The qualified table name
*/
template <SomeSettingsProvider SettingsProviderType> template <SomeSettingsProvider SettingsProviderType>
[[nodiscard]] std::string inline qualifiedTableName(SettingsProviderType const& provider, std::string_view name) [[nodiscard]] std::string inline qualifiedTableName(SettingsProviderType const& provider, std::string_view name)
{ {
@@ -49,6 +57,11 @@ class Schema {
std::reference_wrapper<SettingsProviderType const> settingsProvider_; std::reference_wrapper<SettingsProviderType const> settingsProvider_;
public: public:
/**
* @brief Construct a new Schema object
*
* @param settingsProvider The settings provider
*/
explicit Schema(SettingsProviderType const& settingsProvider) : settingsProvider_{std::cref(settingsProvider)} explicit Schema(SettingsProviderType const& settingsProvider) : settingsProvider_{std::cref(settingsProvider)}
{ {
} }
@@ -279,6 +292,12 @@ public:
std::reference_wrapper<Handle const> handle_; std::reference_wrapper<Handle const> handle_;
public: public:
/**
* @brief Construct a new Statements object
*
* @param settingsProvider The settings provider
* @param handle The handle to the DB
*/
Statements(SettingsProviderType const& settingsProvider, Handle const& handle) Statements(SettingsProviderType const& settingsProvider, Handle const& handle)
: settingsProvider_{settingsProvider}, handle_{std::cref(handle)} : settingsProvider_{settingsProvider}, handle_{std::cref(handle)}
{ {
@@ -713,6 +732,8 @@ public:
/** /**
* @brief Recreates the prepared statements. * @brief Recreates the prepared statements.
*
* @param handle The handle to the DB
*/ */
void void
prepareStatements(Handle const& handle) prepareStatements(Handle const& handle)
@@ -724,6 +745,8 @@ public:
/** /**
* @brief Provides access to statements. * @brief Provides access to statements.
*
* @return The statements
*/ */
std::unique_ptr<Statements> const& std::unique_ptr<Statements> const&
operator->() const operator->() const

View File

@@ -33,13 +33,13 @@
namespace { namespace {
constexpr auto clusterDeleter = [](CassCluster* ptr) { cass_cluster_free(ptr); }; constexpr auto clusterDeleter = [](CassCluster* ptr) { cass_cluster_free(ptr); };
template <class... Ts> template <typename... Ts>
struct overloadSet : Ts... { struct overloadSet : Ts... {
using Ts::operator()...; using Ts::operator()...;
}; };
// explicit deduction guide (not needed as of C++20, but clang be clang) // explicit deduction guide (not needed as of C++20, but clang be clang)
template <class... Ts> template <typename... Ts>
overloadSet(Ts...) -> overloadSet<Ts...>; overloadSet(Ts...) -> overloadSet<Ts...>;
}; // namespace }; // namespace

View File

@@ -29,6 +29,7 @@ namespace etl {
* @brief Settings for the cache loader * @brief Settings for the cache loader
*/ */
struct CacheLoaderSettings { struct CacheLoaderSettings {
/** @brief Ways to load the cache */
enum class LoadStyle { ASYNC, SYNC, NONE }; enum class LoadStyle { ASYNC, SYNC, NONE };
size_t numCacheDiffs = 32; /**< number of diffs to use to generate cursors */ size_t numCacheDiffs = 32; /**< number of diffs to use to generate cursors */
@@ -54,6 +55,12 @@ struct CacheLoaderSettings {
isDisabled() const; isDisabled() const;
}; };
/**
* @brief Create a CacheLoaderSettings object from a Config object
*
* @param config The configuration object
* @returns The CacheLoaderSettings object
*/
[[nodiscard]] CacheLoaderSettings [[nodiscard]] CacheLoaderSettings
make_CacheLoaderSettings(util::Config const& config); make_CacheLoaderSettings(util::Config const& config);

View File

@@ -52,7 +52,9 @@ class NetworkValidatedLedgers {
public: public:
/** /**
* @brief A factory function for NetworkValidatedLedgers. * @brief A factory function for NetworkValidatedLedgers
*
* @return A shared pointer to a new instance of NetworkValidatedLedgers
*/ */
static std::shared_ptr<NetworkValidatedLedgers> static std::shared_ptr<NetworkValidatedLedgers>
make_ValidatedLedgers() make_ValidatedLedgers()
@@ -93,6 +95,7 @@ public:
* @brief Waits for the sequence to be validated by the network. * @brief Waits for the sequence to be validated by the network.
* *
* @param sequence The sequence to wait for * @param sequence The sequence to wait for
* @param maxWaitMs Maximum time to wait for the sequence to be validated. If empty, wait indefinitely
* @return true if sequence was validated, false otherwise a return value of false means the datastructure has been * @return true if sequence was validated, false otherwise a return value of false means the datastructure has been
* stopped * stopped
*/ */
@@ -117,7 +120,7 @@ public:
* @note (original note) We can't use a lockfree queue here, since we need the ability to wait for an element to be * @note (original note) We can't use a lockfree queue here, since we need the ability to wait for an element to be
* added or removed from the queue. These waits are blocking calls. * added or removed from the queue. These waits are blocking calls.
*/ */
template <class T> template <typename T>
class ThreadSafeQueue { class ThreadSafeQueue {
std::queue<T> queue_; std::queue<T> queue_;
@@ -207,6 +210,11 @@ public:
return ret; return ret;
} }
/**
* @brief Get the size of the queue
*
* @return The size of the queue
*/
std::size_t std::size_t
size() const size() const
{ {
@@ -218,6 +226,7 @@ public:
* @brief Parititions the uint256 keyspace into numMarkers partitions, each of equal size. * @brief Parititions the uint256 keyspace into numMarkers partitions, each of equal size.
* *
* @param numMarkers Total markers to partition for * @param numMarkers Total markers to partition for
* @return The markers
*/ */
inline std::vector<ripple::uint256> inline std::vector<ripple::uint256>
getMarkers(size_t numMarkers) getMarkers(size_t numMarkers)

View File

@@ -144,6 +144,7 @@ public:
* @param subscriptions Subscription manager * @param subscriptions Subscription manager
* @param balancer Load balancer to use * @param balancer Load balancer to use
* @param ledgers The network validated ledgers datastructure * @param ledgers The network validated ledgers datastructure
* @return A shared pointer to a new instance of ETLService
*/ */
static std::shared_ptr<ETLService> static std::shared_ptr<ETLService>
make_ETLService( make_ETLService(
@@ -180,6 +181,8 @@ public:
/** /**
* @brief Get time passed since last ledger close, in seconds. * @brief Get time passed since last ledger close, in seconds.
*
* @return Time passed since last ledger close
*/ */
std::uint32_t std::uint32_t
lastCloseAgeSeconds() const lastCloseAgeSeconds() const
@@ -200,6 +203,8 @@ public:
/** /**
* @brief Get state of ETL as a JSON object * @brief Get state of ETL as a JSON object
*
* @return The state of ETL as a JSON object
*/ */
boost::json::object boost::json::object
getInfo() const getInfo() const
@@ -217,7 +222,7 @@ public:
/** /**
* @brief Get the etl nodes' state * @brief Get the etl nodes' state
* @return the etl nodes' state, nullopt if etl nodes are not connected * @return The etl nodes' state, nullopt if etl nodes are not connected
*/ */
std::optional<etl::ETLState> std::optional<etl::ETLState>
getETLState() const noexcept getETLState() const noexcept
@@ -234,7 +239,7 @@ private:
* *
* @param startSequence the first ledger to extract * @param startSequence the first ledger to extract
* @param numExtractors number of extractors to use * @param numExtractors number of extractors to use
* @return the last ledger written to the database, if any * @return The last ledger written to the database, if any
*/ */
std::optional<uint32_t> std::optional<uint32_t>
runETLPipeline(uint32_t startSequence, uint32_t numExtractors); runETLPipeline(uint32_t startSequence, uint32_t numExtractors);
@@ -255,7 +260,7 @@ private:
* @brief Monitor the network for newly validated ledgers and publish them to the ledgers stream * @brief Monitor the network for newly validated ledgers and publish them to the ledgers stream
* *
* @param nextSequence the ledger sequence to publish * @param nextSequence the ledger sequence to publish
* @return the next ledger sequence to publish * @return The next ledger sequence to publish
*/ */
uint32_t uint32_t
publishNextSequence(uint32_t nextSequence); publishNextSequence(uint32_t nextSequence);
@@ -283,7 +288,7 @@ private:
* *
* This is equivelent to the degree of parallelism during the initial ledger download. * This is equivelent to the degree of parallelism during the initial ledger download.
* *
* @return the number of markers * @return The number of markers
*/ */
std::uint32_t std::uint32_t
getNumMarkers() const getNumMarkers() const

View File

@@ -57,6 +57,12 @@ struct ETLState {
} }
}; };
/**
* @brief Parse a boost::json::value into a ETLState
*
* @param jv The json value to convert
* @return The ETLState
*/
ETLState ETLState
tag_invoke(boost::json::value_to_tag<ETLState>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<ETLState>, boost::json::value const& jv);

View File

@@ -222,7 +222,7 @@ LoadBalancer::toJson() const
return ret; return ret;
} }
template <class Func> template <typename Func>
bool bool
LoadBalancer::execute(Func f, uint32_t ledgerSequence) LoadBalancer::execute(Func f, uint32_t ledgerSequence)
{ {

View File

@@ -104,6 +104,7 @@ public:
* @param backend BackendInterface implementation * @param backend BackendInterface implementation
* @param subscriptions Subscription manager * @param subscriptions Subscription manager
* @param validatedLedgers The network validated ledgers datastructure * @param validatedLedgers The network validated ledgers datastructure
* @return A shared pointer to a new instance of LoadBalancer
*/ */
static std::shared_ptr<LoadBalancer> static std::shared_ptr<LoadBalancer>
make_LoadBalancer( make_LoadBalancer(
@@ -121,6 +122,8 @@ public:
* *
* @param sequence Sequence of ledger to download * @param sequence Sequence of ledger to download
* @param cacheOnly Whether to only write to cache and not to the DB; defaults to false * @param cacheOnly Whether to only write to cache and not to the DB; defaults to false
* @return A std::pair<std::vector<std::string>, bool> The ledger data and a bool indicating whether the download
* was successful
*/ */
std::pair<std::vector<std::string>, bool> std::pair<std::vector<std::string>, bool>
loadInitialLedger(uint32_t sequence, bool cacheOnly = false); loadInitialLedger(uint32_t sequence, bool cacheOnly = false);
@@ -134,13 +137,15 @@ public:
* @param ledgerSequence Sequence of the ledger to fetch * @param ledgerSequence Sequence of the ledger to fetch
* @param getObjects Whether to get the account state diff between this ledger and the prior one * @param getObjects Whether to get the account state diff between this ledger and the prior one
* @param getObjectNeighbors Whether to request object neighbors * @param getObjectNeighbors Whether to request object neighbors
* @return The extracted data, if extraction was successful. If the ledger was found in the database or the server * @return The extracted data, if extraction was successful. If the ledger was found
* is shutting down, the optional will be empty * in the database or the server is shutting down, the optional will be empty
*/ */
OptionalGetLedgerResponseType OptionalGetLedgerResponseType
fetchLedger(uint32_t ledgerSequence, bool getObjects, bool getObjectNeighbors); fetchLedger(uint32_t ledgerSequence, bool getObjects, bool getObjectNeighbors);
/** /**
* @brief Represent the state of this load balancer as a JSON object
*
* @return JSON representation of the state of this load balancer. * @return JSON representation of the state of this load balancer.
*/ */
boost::json::value boost::json::value
@@ -181,7 +186,7 @@ private:
* @return true if f was eventually executed successfully. false if the ledger was found in the database or the * @return true if f was eventually executed successfully. false if the ledger was found in the database or the
* server is shutting down * server is shutting down
*/ */
template <class Func> template <typename Func>
bool bool
execute(Func f, uint32_t ledgerSequence); execute(Func f, uint32_t ledgerSequence);

View File

@@ -33,6 +33,56 @@
namespace etl { namespace etl {
/**
* @brief Get the NFT Token mint data from a transaction
*
* @param txMeta Transaction metadata
* @param sttx The transaction
* @return NFT Token mint data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenMintData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
/**
* @brief Get the NFT Token burn data from a transaction
*
* @param txMeta Transaction metadata
* @param sttx The transaction
* @return NFT Token burn data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenBurnData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
/**
* @brief Get the NFT Token accept offer data from a transaction
*
* @param txMeta Transaction metadata
* @param sttx The transaction
* @return NFT Token accept offer data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenAcceptOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
/**
* @brief Get the NFT Token cancel offer data from a transaction
*
* @param txMeta Transaction metadata
* @param sttx The transaction
* @return NFT Token cancel offer data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenCancelOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
/**
* @brief Get the NFT Token create offer data from a transaction
*
* @param txMeta Transaction metadata
* @param sttx The transaction
* @return NFT Token create offer data as a pair of transactions and optional NFTsData
*/
std::pair<std::vector<NFTTransactionsData>, std::optional<NFTsData>>
getNFTokenCreateOfferData(ripple::TxMeta const& txMeta, ripple::STTx const& sttx);
/** /**
* @brief Pull NFT data from TX via ETLService. * @brief Pull NFT data from TX via ETLService.
* *

View File

@@ -45,6 +45,13 @@
namespace etl { namespace etl {
/**
* @brief Provides an implementation of a ETL source
*
* @tparam GrpcSourceType The type of the gRPC source
* @tparam SubscriptionSourceTypePtr The type of the subscription source
* @tparam ForwardingSourceType The type of the forwarding source
*/
template < template <
typename GrpcSourceType = impl::GrpcSource, typename GrpcSourceType = impl::GrpcSource,
typename SubscriptionSourceTypePtr = std::unique_ptr<impl::SubscriptionSource>, typename SubscriptionSourceTypePtr = std::unique_ptr<impl::SubscriptionSource>,
@@ -62,6 +69,16 @@ public:
using OnConnectHook = impl::SubscriptionSource::OnConnectHook; using OnConnectHook = impl::SubscriptionSource::OnConnectHook;
using OnDisconnectHook = impl::SubscriptionSource::OnDisconnectHook; using OnDisconnectHook = impl::SubscriptionSource::OnDisconnectHook;
/**
* @brief Construct a new SourceImpl object
*
* @param ip The IP of the source
* @param wsPort The web socket port of the source
* @param grpcPort The gRPC port of the source
* @param grpcSource The gRPC source
* @param subscriptionSource The subscription source
* @param forwardingSource The forwarding source
*/
template <typename SomeGrpcSourceType, typename SomeForwardingSourceType> template <typename SomeGrpcSourceType, typename SomeForwardingSourceType>
requires std::is_same_v<GrpcSourceType, SomeGrpcSourceType> && requires std::is_same_v<GrpcSourceType, SomeGrpcSourceType> &&
std::is_same_v<ForwardingSourceType, SomeForwardingSourceType> std::is_same_v<ForwardingSourceType, SomeForwardingSourceType>
@@ -91,7 +108,11 @@ public:
subscriptionSource_->run(); subscriptionSource_->run();
} }
/** @return true if source is connected; false otherwise */ /**
* @brief Check if source is connected
*
* @return true if source is connected; false otherwise
*/
bool bool
isConnected() const isConnected() const
{ {
@@ -109,7 +130,11 @@ public:
subscriptionSource_->setForwarding(isForwarding); subscriptionSource_->setForwarding(isForwarding);
} }
/** @return JSON representation of the source */ /**
* @brief Represent the source as a JSON object
*
* @return JSON representation of the source
*/
boost::json::object boost::json::object
toJson() const toJson() const
{ {
@@ -213,6 +238,9 @@ using Source = SourceImpl<>;
* @param backend BackendInterface implementation * @param backend BackendInterface implementation
* @param subscriptions Subscription manager * @param subscriptions Subscription manager
* @param validatedLedgers The network validated ledgers data structure * @param validatedLedgers The network validated ledgers data structure
* @param onDisconnect The hook to call on disconnect
* @param onConnect The hook to call on connect
* @return The created source
*/ */
Source Source
make_Source( make_Source(

View File

@@ -61,7 +61,7 @@ public:
* extraction succeeds, or the server shuts down. * extraction succeeds, or the server shuts down.
* *
* @param sequence sequence of the ledger to extract * @param sequence sequence of the ledger to extract
* @return ledger header and transaction+metadata blobs; empty optional if the server is shutting down * @return Ledger header and transaction+metadata blobs; Empty optional if the server is shutting down
*/ */
OptionalGetLedgerResponseType OptionalGetLedgerResponseType
fetchData(uint32_t sequence) fetchData(uint32_t sequence)
@@ -81,8 +81,7 @@ public:
* extraction succeeds, or the server shuts down. * extraction succeeds, or the server shuts down.
* *
* @param sequence sequence of the ledger to extract * @param sequence sequence of the ledger to extract
* @return ledger header, transaction+metadata blobs, and all ledger objects created, modified or deleted between * @return Ledger data diff between sequance and parent; Empty optional if the server is shutting down
* this ledger and the parent; Empty optional if the server is shutting down
*/ */
OptionalGetLedgerResponseType OptionalGetLedgerResponseType
fetchDataAndDiff(uint32_t sequence) fetchDataAndDiff(uint32_t sequence)

View File

@@ -102,8 +102,7 @@ public:
* *
* @param ledger ledger to insert transactions into * @param ledger ledger to insert transactions into
* @param data data extracted from an ETL source * @param data data extracted from an ETL source
* @return struct that contains the neccessary info to write to the account_transactions/account_tx and * @return The neccessary info to write the account_transactions/account_tx and nft_token_transactions tables
* nft_token_transactions tables (mostly transaction hashes, corresponding nodestore hashes and affected accounts)
*/ */
FormattedTransactionsData FormattedTransactionsData
insertTransactions(ripple::LedgerHeader const& ledger, GetLedgerResponseType& data) insertTransactions(ripple::LedgerHeader const& ledger, GetLedgerResponseType& data)

View File

@@ -106,7 +106,7 @@ public:
* *
* @param ledgerSequence the sequence of the ledger to publish * @param ledgerSequence the sequence of the ledger to publish
* @param maxAttempts the number of times to attempt to read the ledger from the database. 1 attempt per second * @param maxAttempts the number of times to attempt to read the ledger from the database. 1 attempt per second
* @return whether the ledger was found in the database and published * @return Whether the ledger was found in the database and published
*/ */
bool bool
publish(uint32_t ledgerSequence, std::optional<uint32_t> maxAttempts) publish(uint32_t ledgerSequence, std::optional<uint32_t> maxAttempts)

View File

@@ -52,6 +52,9 @@
*/ */
namespace feed { namespace feed {
/**
* @brief A subscription manager is responsible for managing the subscriptions and publishing the feeds
*/
class SubscriptionManager { class SubscriptionManager {
std::reference_wrapper<boost::asio::io_context> ioContext_; std::reference_wrapper<boost::asio::io_context> ioContext_;
std::shared_ptr<data::BackendInterface const> backend_; std::shared_ptr<data::BackendInterface const> backend_;
@@ -64,6 +67,12 @@ class SubscriptionManager {
impl::ProposedTransactionFeed proposedTransactionFeed_; impl::ProposedTransactionFeed proposedTransactionFeed_;
public: public:
/**
* @brief Construct a new Subscription Manager object
*
* @param ioContext The io context to use
* @param backend The backend to use
*/
SubscriptionManager( SubscriptionManager(
boost::asio::io_context& ioContext, boost::asio::io_context& ioContext,
std::shared_ptr<data::BackendInterface const> const& backend std::shared_ptr<data::BackendInterface const> const& backend
@@ -141,7 +150,9 @@ public:
/** /**
* @brief Subscribe to the ledger feed. * @brief Subscribe to the ledger feed.
* @param subscriber * @param yield The coroutine context
* @param subscriber The subscriber to the ledger feed
* @return The ledger feed
*/ */
boost::json::object boost::json::object
subLedger(boost::asio::yield_context yield, SubscriberSharedPtr const& subscriber); subLedger(boost::asio::yield_context yield, SubscriberSharedPtr const& subscriber);
@@ -236,7 +247,8 @@ public:
/** /**
* @brief Unsubscribe to the transactions feed for particular account. * @brief Unsubscribe to the transactions feed for particular account.
* @param subscriber * @param account The account to stop watching
* @param subscriber The subscriber to unsubscribe
*/ */
void void
unsubAccount(ripple::AccountID const& account, SubscriberSharedPtr const& subscriber); unsubAccount(ripple::AccountID const& account, SubscriberSharedPtr const& subscriber);
@@ -268,6 +280,8 @@ public:
/** /**
* @brief Get the number of subscribers. * @brief Get the number of subscribers.
*
* @return The report of the number of subscribers
*/ */
boost::json::object boost::json::object
report() const report() const
@@ -299,6 +313,12 @@ class SubscriptionManagerRunner {
std::vector<std::thread> workers_; std::vector<std::thread> workers_;
public: public:
/**
* @brief Construct a new Subscription Manager Runner object
*
* @param config The configuration
* @param backend The backend to use
*/
SubscriptionManagerRunner(util::Config const& config, std::shared_ptr<data::BackendInterface> const& backend) SubscriptionManagerRunner(util::Config const& config, std::shared_ptr<data::BackendInterface> const& backend)
: subscriptionManager_(std::make_shared<SubscriptionManager>(ioContext_, backend)) : subscriptionManager_(std::make_shared<SubscriptionManager>(ioContext_, backend))
{ {
@@ -309,6 +329,11 @@ public:
workers_.emplace_back([&] { ioContext_.run(); }); workers_.emplace_back([&] { ioContext_.run(); });
} }
/**
* @brief Get the subscription manager
*
* @return The subscription manager
*/
std::shared_ptr<SubscriptionManager> std::shared_ptr<SubscriptionManager>
getManager() getManager()
{ {

View File

@@ -70,7 +70,7 @@ namespace po = boost::program_options;
* *
* @param argc * @param argc
* @param argv * @param argv
* @return std::string Path to configuration file * @return Path to configuration file
*/ */
std::string std::string
parseCli(int argc, char* argv[]) parseCli(int argc, char* argv[])
@@ -109,7 +109,7 @@ parseCli(int argc, char* argv[])
* @brief Parse certificates from configuration file * @brief Parse certificates from configuration file
* *
* @param config The configuration * @param config The configuration
* @return std::optional<ssl::context> SSL context if certificates were parsed * @return SSL context if certificates were parsed
*/ */
std::optional<ssl::context> std::optional<ssl::context>
parseCerts(Config const& config) parseCerts(Config const& config)

View File

@@ -34,7 +34,16 @@
namespace rpc { namespace rpc {
/** /**
* @brief getAmmPoolHolds returns the balances of the amm asset pair. * @brief getAmmPoolHolds returns the balances of the amm asset pair
*
* @param backend The backend to use
* @param sequence The sequence number to use
* @param ammAccountID The amm account
* @param issue1 The first issue
* @param issue2 The second issue
* @param freezeHandling Whether to return zeroes for frozen accounts
* @param yield The coroutine context
* @return The balances of the amm asset pair
*/ */
std::pair<ripple::STAmount, ripple::STAmount> std::pair<ripple::STAmount, ripple::STAmount>
getAmmPoolHolds( getAmmPoolHolds(
@@ -48,7 +57,16 @@ getAmmPoolHolds(
); );
/** /**
* @brief getAmmLpHolds returns the lp token balance. * @brief getAmmLpHolds returns the liquidity provider token balance
*
* @param backend The backend to use
* @param sequence The sequence number to use
* @param cur1 The first currency
* @param cur2 The second currency
* @param ammAccount The amm account
* @param lpAccount The lp account
* @param yield The coroutine context
* @return The lp token balance
*/ */
ripple::STAmount ripple::STAmount
getAmmLpHolds( getAmmLpHolds(
@@ -62,7 +80,14 @@ getAmmLpHolds(
); );
/** /**
* @brief getAmmLpHolds returns the lp token balance. * @brief getAmmLpHolds returns the liquidity provider token balance
*
* @param backend The backend to use
* @param sequence The sequence number to use
* @param ammSle The amm ledger entry
* @param lpAccount The lp account
* @param yield The coroutine context
* @return The lp token balance
*/ */
ripple::STAmount ripple::STAmount
getAmmLpHolds( getAmmLpHolds(

View File

@@ -75,7 +75,7 @@ public:
* @brief Computes all book_changes for the given transactions. * @brief Computes all book_changes for the given transactions.
* *
* @param transactions The transactions to compute book changes for * @param transactions The transactions to compute book changes for
* @return std::vector<BookChange> Book changes * @return Book changes
*/ */
[[nodiscard]] static std::vector<BookChange> [[nodiscard]] static std::vector<BookChange>
compute(std::vector<data::TransactionAndMetadata> const& transactions) compute(std::vector<data::TransactionAndMetadata> const& transactions)
@@ -261,6 +261,7 @@ tag_invoke(boost::json::value_from_tag, boost::json::value& jv, BookChange const
* *
* @param lgrInfo The ledger header * @param lgrInfo The ledger header
* @param transactions The vector of transactions with heir metadata * @param transactions The vector of transactions with heir metadata
* @return The book changes
*/ */
[[nodiscard]] boost::json::object [[nodiscard]] boost::json::object
computeBookChanges(ripple::LedgerHeader const& lgrInfo, std::vector<data::TransactionAndMetadata> const& transactions); computeBookChanges(ripple::LedgerHeader const& lgrInfo, std::vector<data::TransactionAndMetadata> const& transactions);

View File

@@ -109,6 +109,7 @@ public:
* @brief Increments the completed count for a particular RPC method. * @brief Increments the completed count for a particular RPC method.
* *
* @param method The method to increment the count for * @param method The method to increment the count for
* @param rpcDuration The duration of the RPC call
*/ */
void void
rpcComplete(std::string const& method, std::chrono::microseconds const& rpcDuration); rpcComplete(std::string const& method, std::chrono::microseconds const& rpcDuration);

View File

@@ -37,13 +37,13 @@
using namespace std; using namespace std;
namespace { namespace {
template <class... Ts> template <typename... Ts>
struct overloadSet : Ts... { struct overloadSet : Ts... {
using Ts::operator()...; using Ts::operator()...;
}; };
// explicit deduction guide (not needed as of C++20, but clang be clang) // explicit deduction guide (not needed as of C++20, but clang be clang)
template <class... Ts> template <typename... Ts>
overloadSet(Ts...) -> overloadSet<Ts...>; overloadSet(Ts...) -> overloadSet<Ts...>;
} // namespace } // namespace
@@ -107,7 +107,7 @@ getErrorInfo(ClioError code)
} }
boost::json::object boost::json::object
makeError(RippledError err, optional<string_view> customError, optional<string_view> customMessage) makeError(RippledError err, std::optional<std::string_view> customError, std::optional<std::string_view> customMessage)
{ {
boost::json::object json; boost::json::object json;
auto const& info = ripple::RPC::get_error_info(err); auto const& info = ripple::RPC::get_error_info(err);
@@ -122,7 +122,7 @@ makeError(RippledError err, optional<string_view> customError, optional<string_v
} }
boost::json::object boost::json::object
makeError(ClioError err, optional<string_view> customError, optional<string_view> customMessage) makeError(ClioError err, std::optional<std::string_view> customError, std::optional<std::string_view> customMessage)
{ {
boost::json::object json; boost::json::object json;
auto const& info = getErrorInfo(err); auto const& info = getErrorInfo(err);

View File

@@ -77,25 +77,61 @@ struct Status {
std::optional<boost::json::object> extraInfo; std::optional<boost::json::object> extraInfo;
Status() = default; Status() = default;
/**
* @brief Construct a new Status object
*
* @param code The error code
*/
/* implicit */ Status(CombinedError code) : code(code){}; /* implicit */ Status(CombinedError code) : code(code){};
/**
* @brief Construct a new Status object
*
* @param code The error code
* @param extraInfo The extra info
*/
Status(CombinedError code, boost::json::object&& extraInfo) : code(code), extraInfo(std::move(extraInfo)){}; Status(CombinedError code, boost::json::object&& extraInfo) : code(code), extraInfo(std::move(extraInfo)){};
// HACK. Some rippled handlers explicitly specify errors. /**
// This means that we have to be able to duplicate this functionality. * @brief Construct a new Status object with a custom message
*
* @note HACK. Some rippled handlers explicitly specify errors. This means that we have to be able to duplicate this
* functionality.
*
* @param message The message
*/
explicit Status(std::string message) : code(ripple::rpcUNKNOWN), message(std::move(message)) explicit Status(std::string message) : code(ripple::rpcUNKNOWN), message(std::move(message))
{ {
} }
/**
* @brief Construct a new Status object
*
* @param code The error code
* @param message The message
*/
Status(CombinedError code, std::string message) : code(code), message(std::move(message)) Status(CombinedError code, std::string message) : code(code), message(std::move(message))
{ {
} }
/**
* @brief Construct a new Status object
*
* @param code The error code
* @param error The error
* @param message The message
*/
Status(CombinedError code, std::string error, std::string message) Status(CombinedError code, std::string error, std::string message)
: code(code), error(std::move(error)), message(std::move(message)) : code(code), error(std::move(error)), message(std::move(message))
{ {
} }
/** @brief Returns true if the Status is *not* OK. */ /**
* @brief Check if the status is not OK
*
* @return true if the status is not OK; false otherwise
*/
operator bool() const operator bool() const
{ {
if (auto err = std::get_if<RippledError>(&code)) if (auto err = std::get_if<RippledError>(&code))
@@ -141,6 +177,13 @@ enum WarningCode { warnUNKNOWN = -1, warnRPC_CLIO = 2001, warnRPC_OUTDATED = 200
/** @brief Holds information about a clio warning. */ /** @brief Holds information about a clio warning. */
struct WarningInfo { struct WarningInfo {
constexpr WarningInfo() = default; constexpr WarningInfo() = default;
/**
* @brief Construct a new Warning Info object
*
* @param code The warning code
* @param message The warning message
*/
constexpr WarningInfo(WarningCode code, char const* message) : code(code), message(message) constexpr WarningInfo(WarningCode code, char const* message) : code(code), message(message)
{ {
} }
@@ -154,10 +197,20 @@ class InvalidParamsError : public std::exception {
std::string msg; std::string msg;
public: public:
/**
* @brief Construct a new Invalid Params Error object
*
* @param msg The error message
*/
explicit InvalidParamsError(std::string msg) : msg(std::move(msg)) explicit InvalidParamsError(std::string msg) : msg(std::move(msg))
{ {
} }
/**
* @brief Get the error message as a C string
*
* @return The error message
*/
char const* char const*
what() const throw() override what() const throw() override
{ {
@@ -170,10 +223,20 @@ class AccountNotFoundError : public std::exception {
std::string account; std::string account;
public: public:
/**
* @brief Construct a new Account Not Found Error object
*
* @param acct The account
*/
explicit AccountNotFoundError(std::string acct) : account(std::move(acct)) explicit AccountNotFoundError(std::string acct) : account(std::move(acct))
{ {
} }
/**
* @brief Get the error message as a C string
*
* @return The error message
*/
char const* char const*
what() const throw() override what() const throw() override
{ {
@@ -224,6 +287,8 @@ makeError(Status const& status);
* @brief Generate JSON from a @ref rpc::RippledError. * @brief Generate JSON from a @ref rpc::RippledError.
* *
* @param err The rippled error * @param err The rippled error
* @param customError A custom error
* @param customMessage A custom message
* @return The JSON output * @return The JSON output
*/ */
boost::json::object boost::json::object
@@ -237,6 +302,8 @@ makeError(
* @brief Generate JSON from a @ref rpc::ClioError. * @brief Generate JSON from a @ref rpc::ClioError.
* *
* @param err The clio's custom error * @param err The clio's custom error
* @param customError A custom error
* @param customMessage A custom message
* @return The JSON output * @return The JSON output
*/ */
boost::json::object boost::json::object

View File

@@ -47,10 +47,10 @@ util::Expected<web::Context, Status>
make_WsContext( make_WsContext(
boost::asio::yield_context yc, boost::asio::yield_context yc,
boost::json::object const& request, boost::json::object const& request,
shared_ptr<web::ConnectionBase> const& session, std::shared_ptr<web::ConnectionBase> const& session,
TagDecoratorFactory const& tagFactory, util::TagDecoratorFactory const& tagFactory,
data::LedgerRange const& range, data::LedgerRange const& range,
string const& clientIp, std::string const& clientIp,
std::reference_wrapper<APIVersionParser const> apiVersionParser std::reference_wrapper<APIVersionParser const> apiVersionParser
) )
{ {
@@ -76,9 +76,9 @@ Expected<web::Context, Status>
make_HttpContext( make_HttpContext(
boost::asio::yield_context yc, boost::asio::yield_context yc,
boost::json::object const& request, boost::json::object const& request,
TagDecoratorFactory const& tagFactory, util::TagDecoratorFactory const& tagFactory,
data::LedgerRange const& range, data::LedgerRange const& range,
string const& clientIp, std::string const& clientIp,
std::reference_wrapper<APIVersionParser const> apiVersionParser, std::reference_wrapper<APIVersionParser const> apiVersionParser,
bool const isAdmin bool const isAdmin
) )

View File

@@ -54,6 +54,7 @@ namespace rpc {
* @param range The ledger range that is available at request time * @param range The ledger range that is available at request time
* @param clientIp The IP address of the connected client * @param clientIp The IP address of the connected client
* @param apiVersionParser A parser that is used to parse out the "api_version" field * @param apiVersionParser A parser that is used to parse out the "api_version" field
* @return A Websocket context or error Status
*/ */
util::Expected<web::Context, Status> util::Expected<web::Context, Status>
make_WsContext( make_WsContext(
@@ -76,6 +77,7 @@ make_WsContext(
* @param clientIp The IP address of the connected client * @param clientIp The IP address of the connected client
* @param apiVersionParser A parser that is used to parse out the "api_version" field * @param apiVersionParser A parser that is used to parse out the "api_version" field
* @param isAdmin Whether the connection has admin privileges * @param isAdmin Whether the connection has admin privileges
* @return A HTTP context or error Status
*/ */
util::Expected<web::Context, Status> util::Expected<web::Context, Status>
make_HttpContext( make_HttpContext(

View File

@@ -73,6 +73,16 @@ class RPCEngine {
impl::ForwardingProxy<etl::LoadBalancer, Counters, HandlerProvider> forwardingProxy_; impl::ForwardingProxy<etl::LoadBalancer, Counters, HandlerProvider> forwardingProxy_;
public: public:
/**
* @brief Construct a new RPCEngine object
*
* @param backend The backend to use
* @param balancer The load balancer to use
* @param dosGuard The DOS guard to use
* @param workQueue The work queue to use
* @param counters The counters to use
* @param handlerProvider The handler provider to use
*/
RPCEngine( RPCEngine(
std::shared_ptr<BackendInterface> const& backend, std::shared_ptr<BackendInterface> const& backend,
std::shared_ptr<etl::LoadBalancer> const& balancer, std::shared_ptr<etl::LoadBalancer> const& balancer,
@@ -90,6 +100,17 @@ public:
{ {
} }
/**
* @brief Factory function to create a new instance of the RPC engine.
*
* @param backend The backend to use
* @param balancer The load balancer to use
* @param dosGuard The DOS guard to use
* @param workQueue The work queue to use
* @param counters The counters to use
* @param handlerProvider The handler provider to use
* @return A new instance of the RPC engine
*/
static std::shared_ptr<RPCEngine> static std::shared_ptr<RPCEngine>
make_RPCEngine( make_RPCEngine(
std::shared_ptr<BackendInterface> const& backend, std::shared_ptr<BackendInterface> const& backend,
@@ -159,6 +180,7 @@ public:
* @tparam FnType The type of function * @tparam FnType The type of function
* @param func The lambda to execute when this request is handled * @param func The lambda to execute when this request is handled
* @param ip The ip address for which this request is being executed * @param ip The ip address for which this request is being executed
* @return true if the request was successfully scheduled; false otherwise
*/ */
template <typename FnType> template <typename FnType>
bool bool

View File

@@ -795,105 +795,6 @@ parseRippleLibSeed(boost::json::value const& value)
return {}; return {};
} }
std::variant<Status, std::pair<ripple::PublicKey, ripple::SecretKey>>
keypairFromRequst(boost::json::object const& request)
{
bool const has_key_type = request.contains("key_type");
// All of the secret types we allow, but only one at a time.
// The array should be constexpr, but that makes Visual Studio unhappy.
static std::string const secretTypes[]{"passphrase", "secret", "seed", "seed_hex"};
// Identify which secret type is in use.
std::string secretType;
int count = 0;
for (auto const& t : secretTypes) {
if (request.contains(t)) {
++count;
secretType = t;
}
}
if (count == 0)
return Status{RippledError::rpcINVALID_PARAMS, "missing field secret"};
if (count > 1) {
return Status{
RippledError::rpcINVALID_PARAMS,
"Exactly one of the following must be specified: passphrase, secret, seed, or seed_hex"
};
}
std::optional<ripple::KeyType> keyType;
std::optional<ripple::Seed> seed;
if (has_key_type) {
if (!request.at("key_type").is_string())
return Status{RippledError::rpcINVALID_PARAMS, "keyTypeNotString"};
auto const key_type = boost::json::value_to<std::string>(request.at("key_type"));
keyType = ripple::keyTypeFromString(key_type);
if (!keyType)
return Status{RippledError::rpcINVALID_PARAMS, "invalidFieldKeyType"};
if (secretType == "secret")
return Status{RippledError::rpcINVALID_PARAMS, "The secret field is not allowed if key_type is used."};
}
// ripple-lib encodes seed used to generate an Ed25519 wallet in a
// non-standard way. While we never encode seeds that way, we try
// to detect such keys to avoid user confusion.
if (secretType != "seed_hex") {
seed = parseRippleLibSeed(request.at(secretType));
if (seed) {
// If the user passed in an Ed25519 seed but *explicitly*
// requested another key type, return an error.
if (keyType.value_or(ripple::KeyType::ed25519) != ripple::KeyType::ed25519)
return Status{RippledError::rpcINVALID_PARAMS, "Specified seed is for an Ed25519 wallet."};
keyType = ripple::KeyType::ed25519;
}
}
if (!keyType)
keyType = ripple::KeyType::secp256k1;
if (!seed) {
if (has_key_type) {
if (!request.at(secretType).is_string())
return Status{RippledError::rpcINVALID_PARAMS, "secret value must be string"};
auto const key = boost::json::value_to<std::string>(request.at(secretType));
if (secretType == "seed") {
seed = ripple::parseBase58<ripple::Seed>(key);
} else if (secretType == "passphrase") {
seed = ripple::parseGenericSeed(key);
} else if (secretType == "seed_hex") {
ripple::uint128 s;
if (s.parseHex(key))
seed.emplace(ripple::Slice(s.data(), ripple::uint128::size()));
}
} else {
if (!request.at("secret").is_string())
return Status{RippledError::rpcINVALID_PARAMS, "field secret should be a string"};
auto const secret = boost::json::value_to<std::string>(request.at("secret"));
seed = ripple::parseGenericSeed(secret);
}
}
if (!seed)
return Status{RippledError::rpcBAD_SEED, "Bad Seed: invalid field message secretType"};
if (keyType != ripple::KeyType::secp256k1 && keyType != ripple::KeyType::ed25519)
return Status{RippledError::rpcINVALID_PARAMS, "keypairForSignature: invalid key type"};
return generateKeyPair(*keyType, *seed);
}
std::vector<ripple::AccountID> std::vector<ripple::AccountID>
getAccountsFromTransaction(boost::json::object const& transaction) getAccountsFromTransaction(boost::json::object const& transaction)
{ {

View File

@@ -75,34 +75,76 @@
namespace rpc { namespace rpc {
/** @brief Enum for NFT json manipulation */
enum class NFTokenjson { ENABLE, DISABLE }; enum class NFTokenjson { ENABLE, DISABLE };
/**
* @brief Get a ripple::AccountID from its string representation
*
* @param account The string representation of the account
* @return The account ID or std::nullopt if the string is not a valid account
*/
std::optional<ripple::AccountID> std::optional<ripple::AccountID>
accountFromStringStrict(std::string const& account); accountFromStringStrict(std::string const& account);
/**
* @brief Check whether the SLE is owned by the account
*
* @param sle The ledger entry
* @param accountID The account ID
* @return true if the SLE is owned by the account
*/
bool bool
isOwnedByAccount(ripple::SLE const& sle, ripple::AccountID const& accountID); isOwnedByAccount(ripple::SLE const& sle, ripple::AccountID const& accountID);
/**
* @brief Get the start hint for the account
*
* @param sle The ledger entry
* @param accountID The account ID
* @return The start hint
*/
std::uint64_t std::uint64_t
getStartHint(ripple::SLE const& sle, ripple::AccountID const& accountID); getStartHint(ripple::SLE const& sle, ripple::AccountID const& accountID);
/**
* @brief Parse the account cursor from the JSON
*
* @param jsonCursor The JSON cursor
* @return The parsed account cursor
*/
std::optional<AccountCursor> std::optional<AccountCursor>
parseAccountCursor(std::optional<std::string> jsonCursor); parseAccountCursor(std::optional<std::string> jsonCursor);
// TODO this function should probably be in a different file and namespace // TODO this function should probably be in a different file and namespace
/**
* @brief Deserialize a TransactionAndMetadata into a pair of STTx and STObject
*
* @param blobs The TransactionAndMetadata to deserialize
* @return The deserialized objects
*/
std::pair<std::shared_ptr<ripple::STTx const>, std::shared_ptr<ripple::STObject const>> std::pair<std::shared_ptr<ripple::STTx const>, std::shared_ptr<ripple::STObject const>>
deserializeTxPlusMeta(data::TransactionAndMetadata const& blobs); deserializeTxPlusMeta(data::TransactionAndMetadata const& blobs);
// TODO this function should probably be in a different file and namespace // TODO this function should probably be in a different file and namespace
/**
* @brief Deserialize a TransactionAndMetadata into a pair of STTx and TxMeta
*
* @param blobs The TransactionAndMetadata to deserialize
* @param seq The sequence number to set
* @return The deserialized objects
*/
std::pair<std::shared_ptr<ripple::STTx const>, std::shared_ptr<ripple::TxMeta const>> std::pair<std::shared_ptr<ripple::STTx const>, std::shared_ptr<ripple::TxMeta const>>
deserializeTxPlusMeta(data::TransactionAndMetadata const& blobs, std::uint32_t seq); deserializeTxPlusMeta(data::TransactionAndMetadata const& blobs, std::uint32_t seq);
/** /**
* @brief Convert a TransactionAndMetadata to two JSON objects. * @brief Convert a TransactionAndMetadata to two JSON objects
* *
* @param blobs The TransactionAndMetadata to convert. * @param blobs The TransactionAndMetadata to convert
* @param nftEnabled Whether to include NFT information in the JSON. * @param apiVersion The api version to generate the JSON for
* @param networkId The network ID to use for ctid, not include ctid if nullopt. * @param nftEnabled Whether to include NFT information in the JSON
* @param networkId The network ID to use for ctid, not include ctid if nullopt
* @return The JSON objects
*/ */
std::pair<boost::json::object, boost::json::object> std::pair<boost::json::object, boost::json::object>
toExpandedJson( toExpandedJson(
@@ -131,6 +173,15 @@ toJsonWithBinaryTx(data::TransactionAndMetadata const& txnPlusMeta, std::uint32_
void void
insertDeliverMaxAlias(boost::json::object& txJson, std::uint32_t apiVersion); insertDeliverMaxAlias(boost::json::object& txJson, std::uint32_t apiVersion);
/**
* @brief Add "DeliveredAmount" to the transaction json object
*
* @param metaJson The metadata json object to add "DeliveredAmount"
* @param txn The transaction object
* @param meta The metadata object
* @param date The date of the ledger
* @return true if the "DeliveredAmount" is added to the metadata json object
*/
bool bool
insertDeliveredAmount( insertDeliveredAmount(
boost::json::object& metaJson, boost::json::object& metaJson,
@@ -139,9 +190,21 @@ insertDeliveredAmount(
uint32_t date uint32_t date
); );
/**
* @brief Convert STBase object to JSON
*
* @param obj The object to convert
* @return The JSON object
*/
boost::json::object boost::json::object
toJson(ripple::STBase const& obj); toJson(ripple::STBase const& obj);
/**
* @brief Convert SLE to JSON
*
* @param sle The ledger entry to convert
* @return The JSON object
*/
boost::json::object boost::json::object
toJson(ripple::SLE const& sle); toJson(ripple::SLE const& sle);
@@ -156,13 +219,35 @@ toJson(ripple::SLE const& sle);
boost::json::object boost::json::object
toJson(ripple::LedgerHeader const& info, bool binary, std::uint32_t apiVersion); toJson(ripple::LedgerHeader const& info, bool binary, std::uint32_t apiVersion);
/**
* @brief Convert a TxMeta to JSON object.
*
* @param meta The TxMeta to convert.
* @return The JSON object.
*/
boost::json::object boost::json::object
toJson(ripple::TxMeta const& meta); toJson(ripple::TxMeta const& meta);
using RippledJson = Json::Value; using RippledJson = Json::Value;
/**
* @brief Convert a RippledJson to boost::json::value
*
* @param value The RippledJson to convert
* @return The JSON value
*/
boost::json::value boost::json::value
toBoostJson(RippledJson const& value); toBoostJson(RippledJson const& value);
/**
* @brief Generate a JSON object to publish ledger message
*
* @param lgrInfo The ledger header
* @param fees The fees
* @param ledgerRange The ledger range
* @param txnCount The transaction count
* @return The JSON object
*/
boost::json::object boost::json::object
generatePubLedgerMessage( generatePubLedgerMessage(
ripple::LedgerHeader const& lgrInfo, ripple::LedgerHeader const& lgrInfo,
@@ -171,9 +256,26 @@ generatePubLedgerMessage(
std::uint32_t txnCount std::uint32_t txnCount
); );
/**
* @brief Get ledger info from the request
*
* @param backend The backend to use
* @param ctx The context of the request
* @return The ledger info or an error status
*/
std::variant<Status, ripple::LedgerHeader> std::variant<Status, ripple::LedgerHeader>
ledgerInfoFromRequest(std::shared_ptr<data::BackendInterface const> const& backend, web::Context const& ctx); ledgerInfoFromRequest(std::shared_ptr<data::BackendInterface const> const& backend, web::Context const& ctx);
/**
* @brief Get ledger info from hash or sequence
*
* @param backend The backend to use
* @param yield The coroutine context
* @param ledgerHash The optional ledger hash
* @param ledgerIndex The optional ledger index
* @param maxSeq The maximum sequence to search
* @return The ledger info or an error status
*/
std::variant<Status, ripple::LedgerHeader> std::variant<Status, ripple::LedgerHeader>
getLedgerInfoFromHashOrSeq( getLedgerInfoFromHashOrSeq(
BackendInterface const& backend, BackendInterface const& backend,
@@ -183,6 +285,19 @@ getLedgerInfoFromHashOrSeq(
uint32_t maxSeq uint32_t maxSeq
); );
/**
* @brief Traverse nodes owned by an account
*
* @param backend The backend to use
* @param owner The keylet of the owner
* @param hexMarker The marker
* @param startHint The start hint
* @param sequence The sequence
* @param limit The limit of nodes to traverse
* @param yield The coroutine context
* @param atOwnedNode The function to call for each owned node
* @return The status or the account cursor
*/
std::variant<Status, AccountCursor> std::variant<Status, AccountCursor>
traverseOwnedNodes( traverseOwnedNodes(
BackendInterface const& backend, BackendInterface const& backend,
@@ -195,8 +310,21 @@ traverseOwnedNodes(
std::function<void(ripple::SLE)> atOwnedNode std::function<void(ripple::SLE)> atOwnedNode
); );
// Remove the account check from traverseOwnedNodes /**
// Account check has been done by framework,remove it from internal function * @brief Traverse nodes owned by an account
*
* @note Like the other one but removes the account check
*
* @param backend The backend to use
* @param accountID The account ID
* @param sequence The sequence
* @param limit The limit of nodes to traverse
* @param jsonCursor The optional JSON cursor
* @param yield The coroutine context
* @param atOwnedNode The function to call for each owned node
* @param nftIncluded Whether to include NFTs
* @return The status or the account cursor
*/
std::variant<Status, AccountCursor> std::variant<Status, AccountCursor>
traverseOwnedNodes( traverseOwnedNodes(
BackendInterface const& backend, BackendInterface const& backend,
@@ -209,6 +337,15 @@ traverseOwnedNodes(
bool nftIncluded = false bool nftIncluded = false
); );
/**
* @brief Read SLE from the backend
*
* @param backend The backend to use
* @param keylet The keylet to read
* @param lgrInfo The ledger header
* @param context The context of the request
* @return The SLE or nullptr if not found
*/
std::shared_ptr<ripple::SLE const> std::shared_ptr<ripple::SLE const>
read( read(
std::shared_ptr<data::BackendInterface const> const& backend, std::shared_ptr<data::BackendInterface const> const& backend,
@@ -217,15 +354,34 @@ read(
web::Context const& context web::Context const& context
); );
std::variant<Status, std::pair<ripple::PublicKey, ripple::SecretKey>> /**
keypairFromRequst(boost::json::object const& request); * @brief Get the account associated with a transaction
*
* @param transaction The transaction
* @return A vector of accounts associated with the transaction
*/
std::vector<ripple::AccountID> std::vector<ripple::AccountID>
getAccountsFromTransaction(boost::json::object const& transaction); getAccountsFromTransaction(boost::json::object const& transaction);
/**
* @brief Convert a ledger header to a blob
*
* @param info The ledger header
* @param includeHash Whether to include the hash
* @return The blob
*/
std::vector<unsigned char> std::vector<unsigned char>
ledgerInfoToBlob(ripple::LedgerHeader const& info, bool includeHash = false); ledgerInfoToBlob(ripple::LedgerHeader const& info, bool includeHash = false);
/**
* @brief Whether global frozen is set
*
* @param backend The backend to use
* @param seq The ledger sequence
* @param issuer The issuer
* @param yield The coroutine context
* @return true if the global frozen is set; false otherwise
*/
bool bool
isGlobalFrozen( isGlobalFrozen(
BackendInterface const& backend, BackendInterface const& backend,
@@ -234,6 +390,17 @@ isGlobalFrozen(
boost::asio::yield_context yield boost::asio::yield_context yield
); );
/**
* @brief Whether the account is frozen
*
* @param backend The backend to use
* @param sequence The sequence
* @param account The account
* @param currency The currency
* @param issuer The issuer
* @param yield The coroutine context
* @return true if the account is frozen; false otherwise
*/
bool bool
isFrozen( isFrozen(
BackendInterface const& backend, BackendInterface const& backend,
@@ -244,6 +411,16 @@ isFrozen(
boost::asio::yield_context yield boost::asio::yield_context yield
); );
/**
* @brief Get the account funds
*
* @param backend The backend to use
* @param sequence The sequence
* @param amount The amount
* @param id The account ID
* @param yield The coroutine context
* @return The account funds
*/
ripple::STAmount ripple::STAmount
accountFunds( accountFunds(
BackendInterface const& backend, BackendInterface const& backend,
@@ -253,6 +430,18 @@ accountFunds(
boost::asio::yield_context yield boost::asio::yield_context yield
); );
/**
* @brief Get the amount that an account holds
*
* @param backend The backend to use
* @param sequence The sequence
* @param account The account
* @param currency The currency
* @param issuer The issuer
* @param zeroIfFrozen Whether to return zero if frozen
* @param yield The coroutine context
* @return The amount account holds
*/
ripple::STAmount ripple::STAmount
accountHolds( accountHolds(
BackendInterface const& backend, BackendInterface const& backend,
@@ -264,6 +453,15 @@ accountHolds(
boost::asio::yield_context yield boost::asio::yield_context yield
); );
/**
* @brief Get the transfer rate
*
* @param backend The backend to use
* @param sequence The sequence
* @param issuer The issuer
* @param yield The coroutine context
* @return The transfer rate
*/
ripple::Rate ripple::Rate
transferRate( transferRate(
BackendInterface const& backend, BackendInterface const& backend,
@@ -272,6 +470,15 @@ transferRate(
boost::asio::yield_context yield boost::asio::yield_context yield
); );
/**
* @brief Get the XRP liquidity
*
* @param backend The backend to use
* @param sequence The sequence
* @param id The account ID
* @param yield The coroutine context
* @return The XRP liquidity
*/
ripple::XRPAmount ripple::XRPAmount
xrpLiquid( xrpLiquid(
BackendInterface const& backend, BackendInterface const& backend,
@@ -280,6 +487,17 @@ xrpLiquid(
boost::asio::yield_context yield boost::asio::yield_context yield
); );
/**
* @brief Post process an order book
*
* @param offers The offers
* @param book The book
* @param takerID The taker ID
* @param backend The backend to use
* @param ledgerSequence The ledger sequence
* @param yield The coroutine context
* @return The post processed order book
*/
boost::json::array boost::json::array
postProcessOrderBook( postProcessOrderBook(
std::vector<data::LedgerObject> const& offers, std::vector<data::LedgerObject> const& offers,
@@ -290,12 +508,33 @@ postProcessOrderBook(
boost::asio::yield_context yield boost::asio::yield_context yield
); );
/**
* @brief Parse the book from the request
*
* @param pays The currency to pay
* @param payIssuer The issuer of the currency to pay
* @param gets The currency to get
* @param getIssuer The issuer of the currency to get
* @return The book or an error status
*/
std::variant<Status, ripple::Book> std::variant<Status, ripple::Book>
parseBook(ripple::Currency pays, ripple::AccountID payIssuer, ripple::Currency gets, ripple::AccountID getIssuer); parseBook(ripple::Currency pays, ripple::AccountID payIssuer, ripple::Currency gets, ripple::AccountID getIssuer);
/**
* @brief Parse the book from the request
*
* @param request The request
* @return The book or an error status
*/
std::variant<Status, ripple::Book> std::variant<Status, ripple::Book>
parseBook(boost::json::object const& request); parseBook(boost::json::object const& request);
/**
* @brief Parse the taker from the request
*
* @param taker The taker as json
* @return The taker account or an error status
*/
std::variant<Status, ripple::AccountID> std::variant<Status, ripple::AccountID>
parseTaker(boost::json::value const& taker); parseTaker(boost::json::value const& taker);
@@ -309,12 +548,32 @@ parseTaker(boost::json::value const& taker);
ripple::Issue ripple::Issue
parseIssue(boost::json::object const& issue); parseIssue(boost::json::object const& issue);
/**
* @brief Check whethe the request specifies the `current` or `closed` ledger
* @param request The request to check
* @return true if the request specifies the `current` or `closed` ledger
*/
bool bool
specifiesCurrentOrClosedLedger(boost::json::object const& request); specifiesCurrentOrClosedLedger(boost::json::object const& request);
/**
* @brief Get the NFTID from the request
*
* @param request The request
* @return The NFTID or an error status
*/
std::variant<ripple::uint256, Status> std::variant<ripple::uint256, Status>
getNFTID(boost::json::object const& request); getNFTID(boost::json::object const& request);
/**
* @brief Check if the amendment is enabled
*
* @param backend The backend to use
* @param yield The yield context
* @param seq The ledger sequence
* @param amendmentId The amendment ID
* @return true if the amendment is enabled
*/
bool bool
isAmendmentEnabled( isAmendmentEnabled(
std::shared_ptr<data::BackendInterface const> const& backend, std::shared_ptr<data::BackendInterface const> const& backend,
@@ -323,9 +582,24 @@ isAmendmentEnabled(
ripple::uint256 amendmentId ripple::uint256 amendmentId
); );
/**
* @brief Encode CTID as string
*
* @param ledgerSeq The ledger sequence
* @param txnIndex The transaction index
* @param networkId The network ID
* @return The encoded CTID or std::nullopt if the input is invalid
*/
std::optional<std::string> std::optional<std::string>
encodeCTID(uint32_t ledgerSeq, uint16_t txnIndex, uint16_t networkId) noexcept; encodeCTID(uint32_t ledgerSeq, uint16_t txnIndex, uint16_t networkId) noexcept;
/**
* @brief Decode the CTID from a string or a uint64_t
*
* @tparam T The type of the CTID
* @param ctid The CTID to decode
* @return The decoded CTID
*/
template <typename T> template <typename T>
inline std::optional<std::tuple<uint32_t, uint16_t, uint16_t>> inline std::optional<std::tuple<uint32_t, uint16_t, uint16_t>>
decodeCTID(T const ctid) noexcept decodeCTID(T const ctid) noexcept
@@ -363,7 +637,14 @@ decodeCTID(T const ctid) noexcept
return {{ledgerSeq, txnIndex, networkId}}; return {{ledgerSeq, txnIndex, networkId}};
} }
template <class T> /**
* @brief Log the duration of the request processing
*
* @tparam T The type of the duration
* @param ctx The context of the request
* @param dur The duration to log
*/
template <typename T>
void void
logDuration(web::Context const& ctx, T const& dur) logDuration(web::Context const& ctx, T const& dur)
{ {
@@ -386,4 +667,75 @@ logDuration(web::Context const& ctx, T const& dur)
LOG(log.info()) << ctx.tag() << msg; LOG(log.info()) << ctx.tag() << msg;
} }
/**
* @brief Parse a ripple-lib seed
*
* @param value JSON value to parse from
* @return The parsed seed if successful; std::nullopt otherwise
*/
std::optional<ripple::Seed>
parseRippleLibSeed(boost::json::value const& value);
/**
* @brief Traverse NFT objects and call the callback for each owned node
*
* @param backend The backend to use
* @param sequence The sequence
* @param accountID The account ID
* @param nextPage The next page
* @param limit The limit
* @param yield The coroutine context
* @param atOwnedNode The function to call for each owned node
* @return The account cursor or an error status
*/
std::variant<Status, AccountCursor>
traverseNFTObjects(
BackendInterface const& backend,
std::uint32_t sequence,
ripple::AccountID const& accountID,
ripple::uint256 nextPage,
std::uint32_t limit,
boost::asio::yield_context yield,
std::function<void(ripple::SLE)> atOwnedNode
);
/**
* @brief Parse the string as a uint32_t
*
* @param value The string to parse
* @return The parsed value or std::nullopt if the string is not a valid uint32_t
*/
std::optional<std::uint32_t>
parseStringAsUInt(std::string const& value); // TODO: move to string utils or something?
/**
* @brief Whether the transaction can have a delivered amount
*
* @param txn The transaction
* @param meta The metadata
* @return true if the transaction can have a delivered amount
*/
bool
canHaveDeliveredAmount(
std::shared_ptr<ripple::STTx const> const& txn,
std::shared_ptr<ripple::TxMeta const> const& meta
);
/**
* @brief Get the delivered amount
*
* @param txn The transaction
* @param meta The metadata
* @param ledgerSequence The sequence
* @param date The date of the ledger
* @return The delivered amount or std::nullopt if not available
*/
std::optional<ripple::STAmount>
getDeliveredAmount(
std::shared_ptr<ripple::STTx const> const& txn,
std::shared_ptr<ripple::TxMeta const> const& meta,
std::uint32_t const ledgerSequence,
uint32_t date
);
} // namespace rpc } // namespace rpc

View File

@@ -66,6 +66,7 @@ public:
* @brief A factory function that creates the work queue based on a config. * @brief A factory function that creates the work queue based on a config.
* *
* @param config The Clio config to use * @param config The Clio config to use
* @return The work queue
*/ */
static WorkQueue static WorkQueue
make_WorkQueue(util::Config const& config) make_WorkQueue(util::Config const& config)

View File

@@ -51,6 +51,7 @@ public:
{ {
} }
/** @cond */
~AnyHandler() = default; ~AnyHandler() = default;
AnyHandler(AnyHandler const& other) : pimpl_{other.pimpl_->clone()} AnyHandler(AnyHandler const& other) : pimpl_{other.pimpl_->clone()}
{ {
@@ -67,6 +68,7 @@ public:
AnyHandler(AnyHandler&&) = default; AnyHandler(AnyHandler&&) = default;
AnyHandler& AnyHandler&
operator=(AnyHandler&&) = default; operator=(AnyHandler&&) = default;
/** @endcond */
/** /**
* @brief Process incoming JSON by the stored handler * @brief Process incoming JSON by the stored handler

View File

@@ -33,12 +33,30 @@ class HandlerProvider {
public: public:
virtual ~HandlerProvider() = default; virtual ~HandlerProvider() = default;
/**
* @brief Check if the provider contains a handler for a given method
*
* @param command The method to check for
* @return true if the provider contains a handler for the method, false otherwise
*/
virtual bool virtual bool
contains(std::string const& method) const = 0; contains(std::string const& command) const = 0;
/**
* @brief Get the handler for a given method
*
* @param command The method to get the handler for
* @return The handler for the method, or std::nullopt if the method is not found
*/
virtual std::optional<AnyHandler> virtual std::optional<AnyHandler>
getHandler(std::string const& command) const = 0; getHandler(std::string const& command) const = 0;
/**
* @brief Check if a given method is Clio-only
*
* @param command The method to check
* @return true if the method is Clio-only, false otherwise
*/
virtual bool virtual bool
isClioOnly(std::string const& command) const = 0; isClioOnly(std::string const& command) const = 0;
}; };

View File

@@ -34,12 +34,20 @@ namespace rpc {
struct JsonBool { struct JsonBool {
bool value = false; bool value = false;
/** @cond */
operator bool() const operator bool() const
{ {
return value; return value;
} }
/** @endcond */
}; };
/**
* @brief Convert a JSON value to a JsonBool
*
* @param jsonValue The JSON value to convert
* @return The converted JsonBool
*/
inline JsonBool inline JsonBool
tag_invoke(boost::json::value_to_tag<JsonBool> const&, boost::json::value const& jsonValue) tag_invoke(boost::json::value_to_tag<JsonBool> const&, boost::json::value const& jsonValue)
{ {

View File

@@ -168,6 +168,9 @@ public:
/** /**
* @brief Constructs a validator that calls the given validator `req` and returns a custom error `err` in case `req` * @brief Constructs a validator that calls the given validator `req` and returns a custom error `err` in case `req`
* fails. * fails.
*
* @param req The requirement to validate against
* @param err The custom error to return in case `req` fails
*/ */
WithCustomError(SomeRequirement req, Status err) : requirement{std::move(req)}, error{std::move(err)} WithCustomError(SomeRequirement req, Status err) : requirement{std::move(req)}, error{std::move(err)}
{ {

View File

@@ -106,12 +106,22 @@ struct AccountCursor {
ripple::uint256 index; ripple::uint256 index;
std::uint32_t hint{}; std::uint32_t hint{};
/**
* @brief Convert the cursor to a string
*
* @return The string representation of the cursor
*/
std::string std::string
toString() const toString() const
{ {
return ripple::strHex(index) + "," + std::to_string(hint); return ripple::strHex(index) + "," + std::to_string(hint);
} }
/**
* @brief Check if the cursor is non-zero
*
* @return true if the cursor is non-zero, false otherwise
*/
bool bool
isNonZero() const isNonZero() const
{ {
@@ -119,6 +129,13 @@ struct AccountCursor {
} }
}; };
/**
* @brief Convert an empty output to a JSON object
*
* @note Always generates empty JSON object
*
* @param [out] jv The JSON object to convert to
*/
inline void inline void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, VoidOutput const&) tag_invoke(boost::json::value_from_tag, boost::json::value& jv, VoidOutput const&)
{ {

View File

@@ -81,6 +81,13 @@ template <typename Expected>
* @brief A validator that simply requires a field to be present. * @brief A validator that simply requires a field to be present.
*/ */
struct Required final { struct Required final {
/**
* @brief Verify that the JSON value is present and not null.
*
* @param value The JSON value representing the outer object
* @param key The key used to retrieve the tested value from the outer object
* @return An error if validation failed; otherwise no error is returned
*/
[[nodiscard]] static MaybeError [[nodiscard]] static MaybeError
verify(boost::json::value const& value, std::string_view key); verify(boost::json::value const& value, std::string_view key);
}; };
@@ -386,7 +393,7 @@ public:
* *
* @param begin,end the range to copy the elements from * @param begin,end the range to copy the elements from
*/ */
template <class InputIt> template <typename InputIt>
explicit OneOf(InputIt begin, InputIt end) : options_{begin, end} explicit OneOf(InputIt begin, InputIt end) : options_{begin, end}
{ {
} }

View File

@@ -63,7 +63,7 @@ public:
); );
bool bool
contains(std::string const& method) const override; contains(std::string const& command) const override;
std::optional<AnyHandler> std::optional<AnyHandler>
getHandler(std::string const& command) const override; getHandler(std::string const& command) const override;

View File

@@ -44,6 +44,9 @@ class AMMInfoHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
// todo: use better type than json types // todo: use better type than json types
boost::json::value amount1; boost::json::value amount1;
@@ -61,6 +64,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::optional<ripple::AccountID> accountID; std::optional<ripple::AccountID> accountID;
std::optional<ripple::AccountID> ammAccount; std::optional<ripple::AccountID> ammAccount;
@@ -72,20 +78,50 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new AMMInfoHandler object
*
* @param sharedPtrBackend The backend to use
*/
AMMInfoHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) AMMInfoHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion); spec([[maybe_unused]] uint32_t apiVersion);
/**
* @brief Process the AMMInfo command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -55,7 +55,11 @@ public:
static constexpr auto LIMIT_MAX = 400; static constexpr auto LIMIT_MAX = 400;
static constexpr auto LIMIT_DEFAULT = 200; static constexpr auto LIMIT_DEFAULT = 200;
// type align with SField.h /**
* @brief A struct to hold data for one channel response
*
* @note type aligned with SField.h
*/
struct ChannelResponse { struct ChannelResponse {
std::string channelID; std::string channelID;
std::string account; std::string account;
@@ -71,6 +75,9 @@ public:
std::optional<uint32_t> destinationTag; std::optional<uint32_t> destinationTag;
}; };
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::vector<ChannelResponse> channels; std::vector<ChannelResponse> channels;
std::string account; std::string account;
@@ -82,6 +89,9 @@ public:
std::optional<std::string> marker; std::optional<std::string> marker;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string account; std::string account;
std::optional<std::string> destinationAccount; std::optional<std::string> destinationAccount;
@@ -93,11 +103,22 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new AccountChannelsHandler object
*
* @param sharedPtrBackend The backend to use
*/
AccountChannelsHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) AccountChannelsHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
: sharedPtrBackend_(sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -116,6 +137,13 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the AccountChannels command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
@@ -123,12 +151,30 @@ private:
static void static void
addChannel(std::vector<ChannelResponse>& jsonChannels, ripple::SLE const& channelSle); addChannel(std::vector<ChannelResponse>& jsonChannels, ripple::SLE const& channelSle);
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
/**
* @brief Convert the ChannelResponse to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param channel The channel response to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, ChannelResponse const& channel); tag_invoke(boost::json::value_from_tag, boost::json::value& jv, ChannelResponse const& channel);
}; };

View File

@@ -48,6 +48,9 @@ class AccountCurrenciesHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string ledgerHash; std::string ledgerHash;
uint32_t ledgerIndex{}; uint32_t ledgerIndex{};
@@ -57,6 +60,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string account; std::string account;
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
@@ -65,11 +71,22 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new AccountCurrenciesHandler object
*
* @param sharedPtrBackend The backend to use
*/
AccountCurrenciesHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) AccountCurrenciesHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
: sharedPtrBackend_(sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -82,13 +99,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the AccountCurrencies command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -49,6 +49,9 @@ class AccountInfoHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
uint32_t ledgerIndex; uint32_t ledgerIndex;
std::string ledgerHash; std::string ledgerHash;
@@ -60,6 +63,17 @@ public:
// validated should be sent via framework // validated should be sent via framework
bool validated = true; bool validated = true;
/**
* @brief Construct a new Output object
*
* @param ledgerId The ledger index
* @param ledgerHash The ledger hash
* @param sle The account data
* @param isDisallowIncomingEnabled Whether disallow incoming is enabled
* @param isClawbackEnabled Whether clawback is enabled
* @param version The API version
* @param signerLists The signer lists
*/
Output( Output(
uint32_t ledgerId, uint32_t ledgerId,
std::string ledgerHash, std::string ledgerHash,
@@ -80,8 +94,12 @@ public:
} }
}; };
// "queue" is not available in Reporting mode /**
// "ident" is deprecated, keep it for now, in line with rippled * @brief A struct to hold the input data for the command
*
* `queue` is not available in Reporting mode
* `ident` is deprecated, keep it for now, in line with rippled
*/
struct Input { struct Input {
std::optional<std::string> account; std::optional<std::string> account;
std::optional<std::string> ident; std::optional<std::string> ident;
@@ -92,10 +110,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new AccountInfoHandler object
*
* @param sharedPtrBackend The backend to use
*/
AccountInfoHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) AccountInfoHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -111,13 +140,32 @@ public:
return apiVersion == 1 ? rpcSpecV1 : rpcSpec; return apiVersion == 1 ? rpcSpecV1 : rpcSpec;
} }
/**
* @brief Process the AccountInfo command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -57,6 +57,9 @@ public:
static auto constexpr LIMIT_MAX = 400; static auto constexpr LIMIT_MAX = 400;
static auto constexpr LIMIT_DEFAULT = 200; static auto constexpr LIMIT_DEFAULT = 200;
/**
* @brief A struct to hold data for one line response
*/
struct LineResponse { struct LineResponse {
std::string account; std::string account;
std::string balance; std::string balance;
@@ -73,6 +76,9 @@ public:
std::optional<bool> freezePeer; std::optional<bool> freezePeer;
}; };
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string account; std::string account;
std::vector<LineResponse> lines; std::vector<LineResponse> lines;
@@ -83,6 +89,9 @@ public:
uint32_t limit{}; uint32_t limit{};
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string account; std::string account;
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
@@ -96,10 +105,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new AccountLinesHandler object
*
* @param sharedPtrBackend The backend to use
*/
AccountLinesHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) AccountLinesHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -121,6 +141,13 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the AccountLines command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
@@ -134,12 +161,30 @@ private:
); );
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
/**
* @brief Convert the LineResponse to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param line The line response to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, LineResponse const& line); tag_invoke(boost::json::value_from_tag, boost::json::value& jv, LineResponse const& line);
}; };

View File

@@ -51,6 +51,9 @@ public:
static auto constexpr LIMIT_MAX = 400; static auto constexpr LIMIT_MAX = 400;
static auto constexpr LIMIT_DEFAULT = 100; static auto constexpr LIMIT_DEFAULT = 100;
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string account; std::string account;
std::string ledgerHash; std::string ledgerHash;
@@ -62,6 +65,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string account; std::string account;
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
@@ -72,10 +78,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new AccountNFTsHandler object
*
* @param sharedPtrBackend The backend to use
*/
AccountNFTsHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) AccountNFTsHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -93,13 +110,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the AccountNFTs command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -64,6 +64,9 @@ public:
static auto constexpr LIMIT_MAX = 400; static auto constexpr LIMIT_MAX = 400;
static auto constexpr LIMIT_DEFAULT = 200; static auto constexpr LIMIT_DEFAULT = 200;
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string account; std::string account;
std::string ledgerHash; std::string ledgerHash;
@@ -74,6 +77,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string account; std::string account;
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
@@ -86,11 +92,22 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new AccountObjectsHandler object
*
* @param sharedPtrBackend The backend to use
*/
AccountObjectsHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) AccountObjectsHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
: sharedPtrBackend_(sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -113,13 +130,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the AccountObjects command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -53,6 +53,9 @@ public:
static auto constexpr LIMIT_MAX = 400; static auto constexpr LIMIT_MAX = 400;
static auto constexpr LIMIT_DEFAULT = 200; static auto constexpr LIMIT_DEFAULT = 200;
/**
* @brief A struct to hold data for one offer response
*/
struct Offer { struct Offer {
uint32_t flags{}; uint32_t flags{};
uint32_t seq{}; uint32_t seq{};
@@ -62,6 +65,9 @@ public:
std::optional<uint32_t> expiration; std::optional<uint32_t> expiration;
}; };
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string account; std::string account;
std::string ledgerHash; std::string ledgerHash;
@@ -72,6 +78,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string account; std::string account;
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
@@ -82,11 +91,22 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new AccountOffersHandler object
*
* @param sharedPtrBackend The backend to use
*/
AccountOffersHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) AccountOffersHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
: sharedPtrBackend_(sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -104,6 +124,13 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the AccountOffers command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
@@ -111,12 +138,30 @@ private:
static void static void
addOffer(std::vector<Offer>& offers, ripple::SLE const& offerSle); addOffer(std::vector<Offer>& offers, ripple::SLE const& offerSle);
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
/**
* @brief Convert the Offer to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param offer The offer to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Offer const& offer); tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Offer const& offer);
}; };

View File

@@ -61,11 +61,17 @@ public:
static auto constexpr LIMIT_MIN = 1; static auto constexpr LIMIT_MIN = 1;
static auto constexpr LIMIT_DEFAULT = 200; static auto constexpr LIMIT_DEFAULT = 200;
/**
* @brief A struct to hold the marker data
*/
struct Marker { struct Marker {
uint32_t ledger; uint32_t ledger;
uint32_t seq; uint32_t seq;
}; };
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string account; std::string account;
uint32_t ledgerIndexMin{0}; uint32_t ledgerIndexMin{0};
@@ -78,6 +84,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string account; std::string account;
// You must use at least one of the following fields in your request: // You must use at least one of the following fields in your request:
@@ -96,10 +105,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new AccountTxHandler object
*
* @param sharedPtrBackend The backend to use
*/
AccountTxHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) AccountTxHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -142,16 +162,41 @@ public:
return apiVersion == 1 ? rpcSpecForV1 : rpcSpec; return apiVersion == 1 ? rpcSpecForV1 : rpcSpec;
} }
/**
* @brief Process the AccountTx command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
/**
* @brief Convert the Marker to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param marker The marker to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Marker const& marker); tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Marker const& marker);
}; };

View File

@@ -47,6 +47,9 @@ class BookChangesHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string ledgerHash; std::string ledgerHash;
uint32_t ledgerIndex{}; uint32_t ledgerIndex{};
@@ -55,7 +58,11 @@ public:
bool validated = true; bool validated = true;
}; };
// Clio does not implement deletion_blockers_only /**
* @brief A struct to hold the input data for the command
*
* @note Clio does not implement `deletion_blockers_only`
*/
struct Input { struct Input {
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
std::optional<uint32_t> ledgerIndex; std::optional<uint32_t> ledgerIndex;
@@ -63,10 +70,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new BookChangesHandler object
*
* @param sharedPtrBackend The backend to use
*/
BookChangesHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) BookChangesHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -78,13 +96,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the BookChanges command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -57,6 +57,9 @@ public:
static auto constexpr LIMIT_MAX = 100; static auto constexpr LIMIT_MAX = 100;
static auto constexpr LIMIT_DEFAULT = 60; static auto constexpr LIMIT_DEFAULT = 60;
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string ledgerHash; std::string ledgerHash;
uint32_t ledgerIndex; uint32_t ledgerIndex;
@@ -64,8 +67,12 @@ public:
bool validated = true; bool validated = true;
}; };
// the taker is not really used in both clio and rippled, both of them return all the offers regardless the funding /**
// status * @brief A struct to hold the input data for the command
*
* @note The taker is not really used in both Clio and `rippled`, both of them return all the offers regardless of
* the funding status
*/
struct Input { struct Input {
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
std::optional<uint32_t> ledgerIndex; std::optional<uint32_t> ledgerIndex;
@@ -80,10 +87,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new BookOffersHandler object
*
* @param sharedPtrBackend The backend to use
*/
BookOffersHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) BookOffersHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -124,13 +142,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the BookOffers command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -37,7 +37,9 @@
namespace rpc { namespace rpc {
/** /**
* @brief The deposit_authorized command indicates whether one account is authorized to send payments directly to * @brief Handles the `deposit_authorized` command
*
* The deposit_authorized command indicates whether one account is authorized to send payments directly to
* another. See Deposit Authorization for information on how to require authorization to deliver money to your account. * another. See Deposit Authorization for information on how to require authorization to deliver money to your account.
* *
* For more details see: https://xrpl.org/deposit_authorized.html * For more details see: https://xrpl.org/deposit_authorized.html
@@ -48,6 +50,9 @@ class DepositAuthorizedHandler {
public: public:
// Note: `ledger_current_index` is omitted because it only makes sense for rippled // Note: `ledger_current_index` is omitted because it only makes sense for rippled
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
bool depositAuthorized = true; bool depositAuthorized = true;
std::string sourceAccount; std::string sourceAccount;
@@ -58,6 +63,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string sourceAccount; std::string sourceAccount;
std::string destinationAccount; std::string destinationAccount;
@@ -67,11 +75,22 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new DepositAuthorizedHandler object
*
* @param sharedPtrBackend The backend to use
*/
DepositAuthorizedHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) DepositAuthorizedHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
: sharedPtrBackend_(sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -85,13 +104,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the DepositAuthorized command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -49,6 +49,8 @@
namespace rpc { namespace rpc {
/** /**
* @brief Handles the `gateway_balances` command
*
* The gateway_balances command calculates the total balances issued by a given account, optionally excluding amounts * The gateway_balances command calculates the total balances issued by a given account, optionally excluding amounts
* held by operational addresses. * held by operational addresses.
* *
@@ -58,6 +60,9 @@ class GatewayBalancesHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string ledgerHash; std::string ledgerHash;
uint32_t ledgerIndex; uint32_t ledgerIndex;
@@ -71,6 +76,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string account; std::string account;
std::set<ripple::AccountID> hotWallets; std::set<ripple::AccountID> hotWallets;
@@ -80,11 +88,22 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new GatewayBalancesHandler object
*
* @param sharedPtrBackend The backend to use
*/
GatewayBalancesHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) GatewayBalancesHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
: sharedPtrBackend_(sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -128,13 +147,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the GatewayBalances command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -46,6 +46,9 @@ class LedgerHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
uint32_t ledgerIndex{}; uint32_t ledgerIndex{};
std::string ledgerHash; std::string ledgerHash;
@@ -54,9 +57,19 @@ public:
bool validated = true; bool validated = true;
}; };
// clio not support : accounts/full/owner_finds/queue/type /**
// clio will throw error when accounts/full/owner_funds/queue is set to true * @brief A struct to hold the input data for the command
// https://github.com/XRPLF/clio/issues/603 *
* Clio does not support:
* - accounts
* - full
* - owner_finds
* - queue
* - type
*
* Clio will throw an error when any of `accounts`/`full`/`owner_funds`/`queue` are set to `true`
* @see https://github.com/XRPLF/clio/issues/603
*/
struct Input { struct Input {
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
std::optional<uint32_t> ledgerIndex; std::optional<uint32_t> ledgerIndex;
@@ -69,10 +82,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new LedgerHandler object
*
* @param sharedPtrBackend The backend to use
*/
LedgerHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) LedgerHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -92,13 +116,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the Ledger command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -62,6 +62,9 @@ public:
static uint32_t constexpr LIMITBINARY = 2048; static uint32_t constexpr LIMITBINARY = 2048;
static uint32_t constexpr LIMITJSON = 256; static uint32_t constexpr LIMITJSON = 256;
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
uint32_t ledgerIndex{}; uint32_t ledgerIndex{};
std::string ledgerHash; std::string ledgerHash;
@@ -73,9 +76,12 @@ public:
bool validated = true; bool validated = true;
}; };
// TODO: Clio does not implement "type" filter /**
// outOfOrder only for clio, there is no document, traverse via seq diff * @brief A struct to hold the input data for the command
// outOfOrder implementation is copied from old rpc handler *
* @note `outOfOrder` is only for Clio, there is no document, traverse via seq diff (outOfOrder implementation is
* copied from old rpc handler)
*/
struct Input { struct Input {
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
std::optional<uint32_t> ledgerIndex; std::optional<uint32_t> ledgerIndex;
@@ -89,10 +95,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new LedgerDataHandler object
*
* @param sharedPtrBackend The backend to use
*/
LedgerDataHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) LedgerDataHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -116,13 +133,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the LedgerData command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -58,6 +58,9 @@ class LedgerEntryHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string index; std::string index;
uint32_t ledgerIndex; uint32_t ledgerIndex;
@@ -67,6 +70,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
std::optional<uint32_t> ledgerIndex; std::optional<uint32_t> ledgerIndex;
@@ -96,10 +102,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new LedgerEntryHandler object
*
* @param sharedPtrBackend The backend to use
*/
LedgerEntryHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) LedgerEntryHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -266,6 +283,13 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the LedgerEntry command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
@@ -275,9 +299,21 @@ private:
static std::variant<ripple::uint256, Status> static std::variant<ripple::uint256, Status>
composeKeyFromDirectory(boost::json::object const& directory) noexcept; composeKeyFromDirectory(boost::json::object const& directory) noexcept;
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -40,20 +40,40 @@ class LedgerRangeHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
data::LedgerRange range; data::LedgerRange range;
}; };
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new LedgerRangeHandler object
*
* @param sharedPtrBackend The backend to use
*/
LedgerRangeHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) LedgerRangeHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @brief Process the LedgerRange command
*
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Context const& ctx) const; process(Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output);
}; };

View File

@@ -34,11 +34,23 @@ namespace rpc {
*/ */
class NFTBuyOffersHandler : public NFTOffersHandlerBase { class NFTBuyOffersHandler : public NFTOffersHandlerBase {
public: public:
/**
* @brief Construct a new NFTBuyOffersHandler object
*
* @param sharedPtrBackend The backend to use
*/
NFTBuyOffersHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) NFTBuyOffersHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
: NFTOffersHandlerBase(sharedPtrBackend) : NFTOffersHandlerBase(sharedPtrBackend)
{ {
} }
/**
* @brief Process the NFTBuyOffers command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
}; };

View File

@@ -57,12 +57,18 @@ public:
static auto constexpr LIMIT_MAX = 100; static auto constexpr LIMIT_MAX = 100;
static auto constexpr LIMIT_DEFAULT = 50; static auto constexpr LIMIT_DEFAULT = 50;
/**
* @brief A struct to hold the marker data
*/
// TODO: this marker is same as account_tx, reuse in future // TODO: this marker is same as account_tx, reuse in future
struct Marker { struct Marker {
uint32_t ledger; uint32_t ledger;
uint32_t seq; uint32_t seq;
}; };
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string nftID; std::string nftID;
uint32_t ledgerIndexMin{0}; uint32_t ledgerIndexMin{0};
@@ -75,6 +81,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string nftID; std::string nftID;
// You must use at least one of the following fields in your request: // You must use at least one of the following fields in your request:
@@ -91,10 +100,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new NFTHistoryHandler object
*
* @param sharedPtrBackend The backend to use
*/
NFTHistoryHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) NFTHistoryHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -123,16 +143,41 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the NFTHistory command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
/**
* @brief Convert the Marker to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param marker The marker to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Marker const& marker); tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Marker const& marker);
}; };

View File

@@ -45,6 +45,9 @@ class NFTInfoHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string nftID; std::string nftID;
uint32_t ledgerIndex; uint32_t ledgerIndex;
@@ -62,6 +65,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string nftID; std::string nftID;
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
@@ -70,10 +76,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new NFTInfoHandler object
*
* @param sharedPtrBackend The backend to use
*/
NFTInfoHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) NFTInfoHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -86,13 +103,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the NFTInfo command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -42,6 +42,9 @@
namespace rpc { namespace rpc {
/**
* @brief Contains common functionality for handling the `nft_offers` command
*/
class NFTOffersHandlerBase { class NFTOffersHandlerBase {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
@@ -50,6 +53,9 @@ public:
static auto constexpr LIMIT_MAX = 500; static auto constexpr LIMIT_MAX = 500;
static auto constexpr LIMIT_DEFAULT = 250; static auto constexpr LIMIT_DEFAULT = 250;
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string nftID = {}; std::string nftID = {};
std::vector<ripple::SLE> offers = {}; std::vector<ripple::SLE> offers = {};
@@ -60,6 +66,9 @@ public:
std::optional<std::string> marker = {}; std::optional<std::string> marker = {};
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string nftID; std::string nftID;
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
@@ -70,11 +79,22 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new NFTOffersHandlerBase object
*
* @param sharedPtrBackend The backend to use
*/
NFTOffersHandlerBase(std::shared_ptr<BackendInterface> const& sharedPtrBackend) NFTOffersHandlerBase(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
: sharedPtrBackend_(sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -93,6 +113,15 @@ public:
} }
protected: protected:
/**
* @brief Iterate the NFT offer directory
*
* @param input The input data for the command
* @param tokenID The tokenID of the NFT
* @param directory The directory to iterate
* @param yield The coroutine context
* @return The result of the iteration
*/
Result Result
iterateOfferDirectory( iterateOfferDirectory(
Input input, Input input,
@@ -102,9 +131,21 @@ protected:
) const; ) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -34,11 +34,23 @@ namespace rpc {
*/ */
class NFTSellOffersHandler : public NFTOffersHandlerBase { class NFTSellOffersHandler : public NFTOffersHandlerBase {
public: public:
/**
* @brief Construct a new NFTSellOffersHandler object
*
* @param sharedPtrBackend The backend to use
*/
NFTSellOffersHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) NFTSellOffersHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
: NFTOffersHandlerBase(sharedPtrBackend) : NFTOffersHandlerBase(sharedPtrBackend)
{ {
} }
/**
* @brief Process the NFTSellOffers command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
}; };

View File

@@ -37,6 +37,10 @@
#include <string> #include <string>
namespace rpc { namespace rpc {
/**
* @brief Handler for the `nfts_by_issuer` command
*/
class NFTsByIssuerHandler { class NFTsByIssuerHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
@@ -45,6 +49,9 @@ public:
static auto constexpr LIMIT_MAX = 100; static auto constexpr LIMIT_MAX = 100;
static auto constexpr LIMIT_DEFAULT = 50; static auto constexpr LIMIT_DEFAULT = 50;
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
boost::json::array nfts; boost::json::array nfts;
uint32_t ledgerIndex; uint32_t ledgerIndex;
@@ -55,6 +62,9 @@ public:
std::optional<std::string> marker; std::optional<std::string> marker;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string issuer; std::string issuer;
std::optional<uint32_t> nftTaxon; std::optional<uint32_t> nftTaxon;
@@ -66,10 +76,21 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new NFTsByIssuerHandler object
*
* @param sharedPtrBackend The backend to use
*/
NFTsByIssuerHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend) NFTsByIssuerHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -88,13 +109,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the NFTsByIssuer command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -44,7 +44,9 @@
namespace rpc { namespace rpc {
/** /**
* @brief The noripple_check command provides a quick way to check the status of the Default Ripple field for an account * @brief Handles the `noripple_check` command
*
* The noripple_check command provides a quick way to check the status of the Default Ripple field for an account
* and the No Ripple flag of its trust lines, compared with the recommended settings. * and the No Ripple flag of its trust lines, compared with the recommended settings.
* *
* For more details see: https://xrpl.org/noripple_check.html * For more details see: https://xrpl.org/noripple_check.html
@@ -57,6 +59,9 @@ public:
static auto constexpr LIMIT_MAX = 500; static auto constexpr LIMIT_MAX = 500;
static auto constexpr LIMIT_DEFAULT = 300; static auto constexpr LIMIT_DEFAULT = 300;
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string ledgerHash; std::string ledgerHash;
uint32_t ledgerIndex{}; uint32_t ledgerIndex{};
@@ -66,6 +71,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string account; std::string account;
bool roleGateway = false; bool roleGateway = false;
@@ -77,11 +85,22 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new NoRippleCheckHandler object
*
* @param sharedPtrBackend The backend to use
*/
NoRippleCheckHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) NoRippleCheckHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
: sharedPtrBackend_(sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -110,13 +129,32 @@ public:
return apiVersion == 1 ? rpcSpecV1 : rpcSpec; return apiVersion == 1 ? rpcSpecV1 : rpcSpec;
} }
/**
* @brief Process the NoRippleCheck command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -33,6 +33,12 @@ public:
using Output = VoidOutput; using Output = VoidOutput;
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Process the Ping command
*
* @param ctx The context of the request
* @return The result of the operation
*/
static Result static Result
process([[maybe_unused]] Context const& ctx) process([[maybe_unused]] Context const& ctx)
{ {

View File

@@ -36,16 +36,31 @@ namespace rpc {
*/ */
class RandomHandler { class RandomHandler {
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::string random; std::string random;
}; };
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Process the Random command
*
* @param ctx The context of the request
* @return The result of the operation
*/
static Result static Result
process(Context const& ctx); process(Context const& ctx);
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output);
}; };

View File

@@ -60,6 +60,14 @@ class Counters;
namespace rpc { namespace rpc {
/**
* @brief Contains common functionality for handling the `server_info` command
*
* @tparam SubscriptionManagerType The type of the subscription manager
* @tparam LoadBalancerType The type of the load balancer
* @tparam ETLServiceType The type of the ETL service
* @tparam CountersType The type of the counters
*/
template <typename SubscriptionManagerType, typename LoadBalancerType, typename ETLServiceType, typename CountersType> template <typename SubscriptionManagerType, typename LoadBalancerType, typename ETLServiceType, typename CountersType>
class BaseServerInfoHandler { class BaseServerInfoHandler {
static constexpr auto BACKEND_COUNTERS_KEY = "backend_counters"; static constexpr auto BACKEND_COUNTERS_KEY = "backend_counters";
@@ -71,10 +79,16 @@ class BaseServerInfoHandler {
std::reference_wrapper<CountersType const> counters_; std::reference_wrapper<CountersType const> counters_;
public: public:
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
bool backendCounters = false; bool backendCounters = false;
}; };
/**
* @brief A struct to hold the admin section of the output
*/
struct AdminSection { struct AdminSection {
boost::json::object counters = {}; boost::json::object counters = {};
std::optional<boost::json::object> backendCounters = {}; std::optional<boost::json::object> backendCounters = {};
@@ -82,6 +96,9 @@ public:
boost::json::object etl = {}; boost::json::object etl = {};
}; };
/**
* @brief A struct to hold the validated ledger section of the output
*/
struct ValidatedLedgerSection { struct ValidatedLedgerSection {
uint32_t age = 0; uint32_t age = 0;
std::string hash = {}; std::string hash = {};
@@ -89,6 +106,9 @@ public:
std::optional<ripple::Fees> fees = std::nullopt; std::optional<ripple::Fees> fees = std::nullopt;
}; };
/**
* @brief A struct to hold the cache section of the output
*/
struct CacheSection { struct CacheSection {
std::size_t size = 0; std::size_t size = 0;
bool isFull = false; bool isFull = false;
@@ -97,6 +117,9 @@ public:
float successorHitRate = 1.0; float successorHitRate = 1.0;
}; };
/**
* @brief A struct to hold the info section of the output
*/
struct InfoSection { struct InfoSection {
std::optional<AdminSection> adminSection = std::nullopt; std::optional<AdminSection> adminSection = std::nullopt;
std::string completeLedgers = {}; std::string completeLedgers = {};
@@ -111,6 +134,9 @@ public:
bool isAmendmentBlocked = false; bool isAmendmentBlocked = false;
}; };
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
InfoSection info = {}; InfoSection info = {};
@@ -120,6 +146,15 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new BaseServerInfoHandler object
*
* @param backend The backend to use
* @param subscriptions The subscription manager to use
* @param balancer The load balancer to use
* @param etl The ETL service to use
* @param counters The counters to use
*/
BaseServerInfoHandler( BaseServerInfoHandler(
std::shared_ptr<BackendInterface> const& backend, std::shared_ptr<BackendInterface> const& backend,
std::shared_ptr<SubscriptionManagerType> const& subscriptions, std::shared_ptr<SubscriptionManagerType> const& subscriptions,
@@ -135,6 +170,12 @@ public:
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -142,6 +183,13 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the ServerInfo command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const process(Input input, Context const& ctx) const
{ {

View File

@@ -52,12 +52,21 @@ class SubscriptionManager;
} // namespace feed } // namespace feed
namespace rpc { namespace rpc {
/**
* @brief Contains functionality for handling the `subscribe` command
*
* @tparam SubscriptionManagerType The type of the subscription manager to use
*/
template <typename SubscriptionManagerType> template <typename SubscriptionManagerType>
class BaseSubscribeHandler { class BaseSubscribeHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
std::shared_ptr<SubscriptionManagerType> subscriptions_; std::shared_ptr<SubscriptionManagerType> subscriptions_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
// response of stream "ledger" // response of stream "ledger"
// TODO: use better type than json, this type will be used in the stream as well // TODO: use better type than json, this type will be used in the stream as well
@@ -71,6 +80,9 @@ public:
std::optional<boost::json::array> bids; std::optional<boost::json::array> bids;
}; };
/**
* @brief A struct to hold the data for one order book
*/
struct OrderBook { struct OrderBook {
ripple::Book book; ripple::Book book;
std::optional<std::string> taker; std::optional<std::string> taker;
@@ -78,6 +90,9 @@ public:
bool both = false; bool both = false;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::optional<std::vector<std::string>> accounts; std::optional<std::vector<std::string>> accounts;
std::optional<std::vector<std::string>> streams; std::optional<std::vector<std::string>> streams;
@@ -87,6 +102,12 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new BaseSubscribeHandler object
*
* @param sharedPtrBackend The backend to use
* @param subscriptions The subscription manager to use
*/
BaseSubscribeHandler( BaseSubscribeHandler(
std::shared_ptr<BackendInterface> const& sharedPtrBackend, std::shared_ptr<BackendInterface> const& sharedPtrBackend,
std::shared_ptr<SubscriptionManagerType> const& subscriptions std::shared_ptr<SubscriptionManagerType> const& subscriptions
@@ -95,6 +116,12 @@ public:
{ {
} }
/**
* @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
*/
RpcSpecConstRef RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) const spec([[maybe_unused]] uint32_t apiVersion) const
{ {
@@ -141,6 +168,13 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the Subscribe command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const process(Input input, Context const& ctx) const
{ {

View File

@@ -49,6 +49,9 @@ class TransactionEntryHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
std::optional<ripple::LedgerHeader> ledgerHeader; std::optional<ripple::LedgerHeader> ledgerHeader;
// TODO: use a better type for this // TODO: use a better type for this
@@ -59,6 +62,9 @@ public:
uint32_t apiVersion; uint32_t apiVersion;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::string txHash; std::string txHash;
std::optional<std::string> ledgerHash; std::optional<std::string> ledgerHash;
@@ -67,11 +73,22 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new Transaction Entry Handler object
*
* @param sharedPtrBackend The backend to use
*/
TransactionEntryHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend) TransactionEntryHandler(std::shared_ptr<BackendInterface> const& sharedPtrBackend)
: sharedPtrBackend_(sharedPtrBackend) : sharedPtrBackend_(sharedPtrBackend)
{ {
} }
/**
* @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 static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) spec([[maybe_unused]] uint32_t apiVersion)
{ {
@@ -86,13 +103,32 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the transaction_entry command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the command
*/
Result Result
process(Input input, Context const& ctx) const; process(Input input, Context const& ctx) const;
private: private:
/**
* @brief Convert the Output to a JSON object
*
* @param [out] jv The JSON object to convert to
* @param output The output to convert
*/
friend void friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output); 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 friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv); tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
}; };

View File

@@ -50,12 +50,20 @@
namespace rpc { namespace rpc {
/**
* @brief Contains common functionality for handling the `tx` command
*
* @tparam ETLServiceType The type of the ETL service to use
*/
template <typename ETLServiceType> template <typename ETLServiceType>
class BaseTxHandler { class BaseTxHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
std::shared_ptr<ETLServiceType const> etl_; std::shared_ptr<ETLServiceType const> etl_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
uint32_t date = 0u; uint32_t date = 0u;
std::string hash{}; std::string hash{};
@@ -70,6 +78,9 @@ public:
bool validated = true; bool validated = true;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::optional<std::string> transaction; std::optional<std::string> transaction;
std::optional<std::string> ctid; std::optional<std::string> ctid;
@@ -80,6 +91,12 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new BaseTxHandler object
*
* @param sharedPtrBackend The backend to use
* @param etl The ETL service to use
*/
BaseTxHandler( BaseTxHandler(
std::shared_ptr<BackendInterface> const& sharedPtrBackend, std::shared_ptr<BackendInterface> const& sharedPtrBackend,
std::shared_ptr<ETLServiceType const> const& etl std::shared_ptr<ETLServiceType const> const& etl
@@ -88,6 +105,12 @@ public:
{ {
} }
/**
* @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 static RpcSpecConstRef
spec(uint32_t apiVersion) spec(uint32_t apiVersion)
{ {
@@ -103,6 +126,13 @@ public:
return apiVersion == 1 ? rpcSpecForV1 : rpcSpec; return apiVersion == 1 ? rpcSpecForV1 : rpcSpec;
} }
/**
* @brief Process the Tx command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const process(Input input, Context const& ctx) const
{ {

View File

@@ -48,17 +48,26 @@ class SubscriptionManager;
namespace rpc { namespace rpc {
/**
* @brief Handles the `unsubscribe` command which is used to disconnect a subscriber from a feed
*/
template <typename SubscriptionManagerType> template <typename SubscriptionManagerType>
class BaseUnsubscribeHandler { class BaseUnsubscribeHandler {
std::shared_ptr<BackendInterface> sharedPtrBackend_; std::shared_ptr<BackendInterface> sharedPtrBackend_;
std::shared_ptr<SubscriptionManagerType> subscriptions_; std::shared_ptr<SubscriptionManagerType> subscriptions_;
public: public:
/**
* @brief A struct to hold one order book
*/
struct OrderBook { struct OrderBook {
ripple::Book book; ripple::Book book;
bool both = false; bool both = false;
}; };
/**
* @brief A struct to hold the input data for the command
*/
struct Input { struct Input {
std::optional<std::vector<std::string>> accounts; std::optional<std::vector<std::string>> accounts;
std::optional<std::vector<std::string>> streams; std::optional<std::vector<std::string>> streams;
@@ -69,6 +78,12 @@ public:
using Output = VoidOutput; using Output = VoidOutput;
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Construct a new BaseUnsubscribeHandler object
*
* @param sharedPtrBackend The backend to use
* @param subscriptions The subscription manager to use
*/
BaseUnsubscribeHandler( BaseUnsubscribeHandler(
std::shared_ptr<BackendInterface> const& sharedPtrBackend, std::shared_ptr<BackendInterface> const& sharedPtrBackend,
std::shared_ptr<SubscriptionManagerType> const& subscriptions std::shared_ptr<SubscriptionManagerType> const& subscriptions
@@ -77,6 +92,12 @@ public:
{ {
} }
/**
* @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
*/
RpcSpecConstRef RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion) const spec([[maybe_unused]] uint32_t apiVersion) const
{ {
@@ -110,6 +131,13 @@ public:
return rpcSpec; return rpcSpec;
} }
/**
* @brief Process the Unsubscribe command
*
* @param input The input data for the command
* @param ctx The context of the request
* @return The result of the operation
*/
Result Result
process(Input input, Context const& ctx) const process(Input input, Context const& ctx) const
{ {

View File

@@ -39,12 +39,20 @@ class VersionHandler {
rpc::impl::ProductionAPIVersionParser apiVersionParser_; rpc::impl::ProductionAPIVersionParser apiVersionParser_;
public: public:
/**
* @brief A struct to hold the output data of the command
*/
struct Output { struct Output {
uint32_t minVersion; uint32_t minVersion;
uint32_t maxVersion; uint32_t maxVersion;
uint32_t currVersion; uint32_t currVersion;
}; };
/**
* @brief Construct a new Version Handler object
*
* @param config The configuration to use
*/
explicit VersionHandler(util::Config const& config) explicit VersionHandler(util::Config const& config)
: apiVersionParser_( : apiVersionParser_(
config.valueOr("default", API_VERSION_DEFAULT), config.valueOr("default", API_VERSION_DEFAULT),
@@ -56,6 +64,12 @@ public:
using Result = HandlerReturnType<Output>; using Result = HandlerReturnType<Output>;
/**
* @brief Process the version command
*
* @param ctx The context of the request
* @return The result of the command
*/
Result Result
process([[maybe_unused]] Context const& ctx) const process([[maybe_unused]] Context const& ctx) const
{ {

View File

@@ -31,6 +31,17 @@
namespace util { namespace util {
/**
* @brief Assert that a condition is true
* @note Calls std::exit if the condition is false
*
* @tparam Args The format argument types
* @param location The location of the assertion
* @param expression The expression to assert
* @param condition The condition to assert
* @param format The format string
* @param args The format arguments
*/
template <typename... Args> template <typename... Args>
constexpr void constexpr void
assertImpl( assertImpl(

View File

@@ -35,6 +35,12 @@ public:
using ValueType = NumberType; using ValueType = NumberType;
Atomic() = default; Atomic() = default;
/**
* @brief Construct a new Atomic object
*
* @param value The initial value
*/
Atomic(ValueType const value) : value_(value) Atomic(ValueType const value) : value_(value)
{ {
} }
@@ -86,7 +92,7 @@ public:
/** /**
* @brief Get the current value * @brief Get the current value
* *
* @return ValueType The current value * @return The current value
*/ */
ValueType ValueType
value() const value() const

View File

@@ -27,6 +27,13 @@
namespace util { namespace util {
/**
* @brief Iterate over a container in batches
*
* @param container The container to iterate over
* @param batchSize The size of each batch
* @param fn The function to call for each batch
*/
void void
forEachBatch(std::ranges::forward_range auto&& container, std::size_t batchSize, auto&& fn) forEachBatch(std::ranges::forward_range auto&& container, std::size_t batchSize, auto&& fn)
{ {

View File

@@ -23,6 +23,9 @@
namespace util { namespace util {
/**
* @brief Specifies a number type
*/
template <typename T> template <typename T>
concept SomeNumberType = std::is_arithmetic_v<T> && !std::is_same_v<T, bool> && !std::is_const_v<T>; concept SomeNumberType = std::is_arithmetic_v<T> && !std::is_same_v<T, bool> && !std::is_const_v<T>;

View File

@@ -53,6 +53,9 @@ namespace util {
The implementation is entirely based on boost::outcome_v2::result. The implementation is entirely based on boost::outcome_v2::result.
*/ */
// Documentation is not needed - will be removed as soon as `std::expected` available
/** @cond */
// Exception thrown by an invalid access to Expected. // Exception thrown by an invalid access to Expected.
struct bad_expected_access : public std::runtime_error { struct bad_expected_access : public std::runtime_error {
bad_expected_access() : runtime_error("bad expected access") bad_expected_access() : runtime_error("bad expected access")
@@ -64,7 +67,7 @@ namespace impl {
// Custom policy for Expected. Always throw on an invalid access. // Custom policy for Expected. Always throw on an invalid access.
struct throw_policy : public boost::outcome_v2::policy::base { struct throw_policy : public boost::outcome_v2::policy::base {
template <class Impl> template <typename Impl>
static constexpr void static constexpr void
wide_value_check(Impl&& self) wide_value_check(Impl&& self)
{ {
@@ -72,7 +75,7 @@ struct throw_policy : public boost::outcome_v2::policy::base {
ripple::Throw<bad_expected_access>(); ripple::Throw<bad_expected_access>();
} }
template <class Impl> template <typename Impl>
static constexpr void static constexpr void
wide_error_check(Impl&& self) wide_error_check(Impl&& self)
{ {
@@ -80,7 +83,7 @@ struct throw_policy : public boost::outcome_v2::policy::base {
ripple::Throw<bad_expected_access>(); ripple::Throw<bad_expected_access>();
} }
template <class Impl> template <typename Impl>
static constexpr void static constexpr void
wide_exception_check(Impl&& self) wide_exception_check(Impl&& self)
{ {
@@ -93,7 +96,7 @@ struct throw_policy : public boost::outcome_v2::policy::base {
// Definition of Unexpected, which is used to construct the unexpected // Definition of Unexpected, which is used to construct the unexpected
// return type of an Expected. // return type of an Expected.
template <class E> template <typename E>
class Unexpected { class Unexpected {
public: public:
static_assert(!std::is_same_v<E, void>, "E must not be void"); static_assert(!std::is_same_v<E, void>, "E must not be void");
@@ -141,7 +144,7 @@ template <typename E, std::size_t N>
Unexpected(E (&)[N]) -> Unexpected<E const*>; Unexpected(E (&)[N]) -> Unexpected<E const*>;
// Definition of Expected. All of the machinery comes from boost::result. // Definition of Expected. All of the machinery comes from boost::result.
template <class T, class E> template <typename T, typename E>
class Expected : private boost::outcome_v2::result<T, E, impl::throw_policy> { class Expected : private boost::outcome_v2::result<T, E, impl::throw_policy> {
using Base = boost::outcome_v2::result<T, E, impl::throw_policy>; using Base = boost::outcome_v2::result<T, E, impl::throw_policy>;
@@ -243,7 +246,7 @@ private:
// Specialization of Expected<void, E>. Allows returning either success // Specialization of Expected<void, E>. Allows returning either success
// (without a value) or the reason for the failure. // (without a value) or the reason for the failure.
template <class E> template <typename E>
class [[nodiscard]] Expected<void, E> : private boost::outcome_v2::result<void, E, impl::throw_policy> { class [[nodiscard]] Expected<void, E> : private boost::outcome_v2::result<void, E, impl::throw_policy> {
using Base = boost::outcome_v2::result<void, E, impl::throw_policy>; using Base = boost::outcome_v2::result<void, E, impl::throw_policy>;
@@ -278,4 +281,6 @@ public:
} }
}; };
/** @endcond */
} // namespace util } // namespace util

View File

@@ -31,6 +31,12 @@
*/ */
namespace util { namespace util {
/**
* @brief Convert a string to lowercase
*
* @param str The string to convert
* @return The string in lowercase
*/
inline std::string inline std::string
toLower(std::string str) toLower(std::string str)
{ {
@@ -38,6 +44,12 @@ toLower(std::string str)
return str; return str;
} }
/**
* @brief Convert a string to uppercase
*
* @param str The string to convert
* @return The string in uppercase
*/
inline std::string inline std::string
toUpper(std::string str) toUpper(std::string str)
{ {

View File

@@ -34,19 +34,26 @@
namespace util { namespace util {
/** /**
* @brief Returns a string set of all supported ledger entry types. * @brief Returns a string set of all supported ledger entry types
*
* @return const& The set of ledger entry types
*/ */
std::unordered_set<std::string> const& std::unordered_set<std::string> const&
getLedgerEntryTypeStrs(); getLedgerEntryTypeStrs();
/** /**
* @brief Return the ledger type from a string representation. * @brief Return the ledger type from a string representation
*
* @param entryName The string representation of the ledger entry type
* @return The ledger entry type
*/ */
ripple::LedgerEntryType ripple::LedgerEntryType
getLedgerEntryTypeFromStr(std::string const& entryName); getLedgerEntryTypeFromStr(std::string const& entryName);
/** /**
* @brief Return the list of ledger entry types which will block the account deletion. * @brief Return the list of ledger entry types which will block the account deletion
*
* @return const& The list of ledger entry types
*/ */
std::vector<ripple::LedgerEntryType> const& std::vector<ripple::LedgerEntryType> const&
getDeletionBlockerLedgerTypes(); getDeletionBlockerLedgerTypes();

View File

@@ -38,6 +38,7 @@ class Lock {
ProtectedDataType& data_; ProtectedDataType& data_;
public: public:
/** @cond */
ProtectedDataType const& ProtectedDataType const&
operator*() const operator*() const
{ {
@@ -73,6 +74,7 @@ public:
{ {
return &data_; return &data_;
} }
/** @endcond */
private: private:
friend class Mutex<std::remove_const_t<ProtectedDataType>>; friend class Mutex<std::remove_const_t<ProtectedDataType>>;
@@ -95,10 +97,22 @@ class Mutex {
public: public:
Mutex() = default; Mutex() = default;
/**
* @brief Construct a new Mutex object with the given data
*
* @param data The data to protect
*/
explicit Mutex(ProtectedDataType data) : data_(std::move(data)) explicit Mutex(ProtectedDataType data) : data_(std::move(data))
{ {
} }
/**
* @brief Make a new Mutex object with the given data
*
* @tparam Args The types of the arguments to forward to the constructor of the protected data
* @param args The arguments to forward to the constructor of the protected data
* @return The Mutex object that protects the given data
*/
template <typename... Args> template <typename... Args>
static Mutex static Mutex
make(Args&&... args) make(Args&&... args)
@@ -106,12 +120,22 @@ public:
return Mutex{ProtectedDataType{std::forward<Args>(args)...}}; return Mutex{ProtectedDataType{std::forward<Args>(args)...}};
} }
/**
* @brief Lock the mutex and get a lock object allowing access to the protected data
*
* @return A lock on the mutex and a reference to the protected data
*/
Lock<ProtectedDataType const> Lock<ProtectedDataType const>
lock() const lock() const
{ {
return Lock<ProtectedDataType const>{mutex_, data_}; return Lock<ProtectedDataType const>{mutex_, data_};
} }
/**
* @brief Lock the mutex and get a lock object allowing access to the protected data
*
* @return A lock on the mutex and a reference to the protected data
*/
Lock<ProtectedDataType> Lock<ProtectedDataType>
lock() lock()
{ {

View File

@@ -38,13 +38,16 @@ class RetryStrategy {
std::chrono::steady_clock::duration delay_; std::chrono::steady_clock::duration delay_;
public: public:
/**
* @brief Construct a new Retry Strategy object
*
* @param delay The initial delay value
*/
RetryStrategy(std::chrono::steady_clock::duration delay); RetryStrategy(std::chrono::steady_clock::duration delay);
virtual ~RetryStrategy() = default; virtual ~RetryStrategy() = default;
/** /**
* @brief Get the current delay value * @return The current delay value
*
* @return std::chrono::steady_clock::duration
*/ */
std::chrono::steady_clock::duration std::chrono::steady_clock::duration
getDelay() const; getDelay() const;
@@ -63,9 +66,7 @@ public:
protected: protected:
/** /**
* @brief Compute the next delay value * @return The next computed delay value
*
* @return std::chrono::steady_clock::duration
*/ */
virtual std::chrono::steady_clock::duration virtual std::chrono::steady_clock::duration
nextDelay() const = 0; nextDelay() const = 0;
@@ -81,6 +82,12 @@ class Retry {
size_t attemptNumber_ = 0; size_t attemptNumber_ = 0;
public: public:
/**
* @brief Construct a new Retry object
*
* @param strategy The retry strategy to use
* @param strand The strand to use for async operations
*/
Retry(RetryStrategyPtr strategy, boost::asio::strand<boost::asio::io_context::executor_type> strand); Retry(RetryStrategyPtr strategy, boost::asio::strand<boost::asio::io_context::executor_type> strand);
~Retry(); ~Retry();
@@ -112,17 +119,13 @@ public:
cancel(); cancel();
/** /**
* @brief Get the current attempt number * @return The current attempt number
*
* @return size_t
*/ */
size_t size_t
attemptNumber() const; attemptNumber() const;
/** /**
* @brief Get the current delay value * @return The current delay value
*
* @return std::chrono::steady_clock::duration
*/ */
std::chrono::steady_clock::duration std::chrono::steady_clock::duration
delayValue() const; delayValue() const;
@@ -135,17 +138,18 @@ public:
}; };
/** /**
* @brief Create a retry mechanism with exponential backoff strategy * @brief A retry strategy that retries while exponentially increasing the delay between attempts
*
* @param delay The initial delay value
* @param maxDelay The maximum delay value
* @param strand The strand to use for async operations
* @return Retry
*/ */
class ExponentialBackoffStrategy : public RetryStrategy { class ExponentialBackoffStrategy : public RetryStrategy {
std::chrono::steady_clock::duration maxDelay_; std::chrono::steady_clock::duration maxDelay_;
public: public:
/**
* @brief Construct a new Exponential Backoff Strategy object
*
* @param delay The initial delay value
* @param maxDelay The maximum delay value
*/
ExponentialBackoffStrategy(std::chrono::steady_clock::duration delay, std::chrono::steady_clock::duration maxDelay); ExponentialBackoffStrategy(std::chrono::steady_clock::duration delay, std::chrono::steady_clock::duration maxDelay);
private: private:
@@ -159,7 +163,7 @@ private:
* @param delay The initial delay value * @param delay The initial delay value
* @param maxDelay The maximum delay value * @param maxDelay The maximum delay value
* @param strand The strand to use for async operations * @param strand The strand to use for async operations
* @return Retry * @return The retry object
*/ */
Retry Retry
makeRetryExponentialBackoff( makeRetryExponentialBackoff(

View File

@@ -43,23 +43,43 @@ using SourceLocationType = std::source_location;
using SourceLocationType = std::experimental::source_location; using SourceLocationType = std::experimental::source_location;
#else #else
// A workaround for AppleClang that is lacking source_location atm. /**
// TODO: remove this workaround when all compilers catch up to c++20 * @brief A class representing the source location of the current code
*
* @note This is a workaround for AppleClang that is lacking source_location atm.
* TODO: remove this class when all compilers catch up to c++20
*/
class SourceLocation { class SourceLocation {
char const* file_; char const* file_;
std::size_t line_; std::size_t line_;
public: public:
/**
* @brief Construct a new Source Location object
*
* @param file The file name
* @param line The line number
*/
constexpr SourceLocation(char const* file, std::size_t line) : file_{file}, line_{line} constexpr SourceLocation(char const* file, std::size_t line) : file_{file}, line_{line}
{ {
} }
/**
* @brief Get the file name
*
* @return The file name
*/
constexpr std::string_view constexpr std::string_view
file_name() const file_name() const
{ {
return file_; return file_;
} }
/**
* @brief Get the line number
*
* @return The line number
*/
constexpr std::size_t constexpr std::size_t
line() const line() const
{ {

View File

@@ -199,7 +199,7 @@ public:
/** /**
* @brief Instantiates the TagDecorator specified by `type_` with parent bound from `parent_`. * @brief Instantiates the TagDecorator specified by `type_` with parent bound from `parent_`.
* *
* @return std::unique_ptr<BaseTagDecorator> An instance of the requested decorator * @return An instance of the requested decorator
*/ */
std::unique_ptr<BaseTagDecorator> std::unique_ptr<BaseTagDecorator>
make() const; make() const;
@@ -254,6 +254,7 @@ protected:
public: public:
virtual ~Taggable() = default; virtual ~Taggable() = default;
Taggable(Taggable&&) = default; Taggable(Taggable&&) = default;
Taggable& Taggable&
operator=(Taggable&&) = default; operator=(Taggable&&) = default;

View File

@@ -28,6 +28,11 @@
namespace util { namespace util {
/**
* @brief Get the transaction types in lowercase
*
* @return The transaction types in lowercase
*/
[[nodiscard]] std::unordered_set<std::string> const& [[nodiscard]] std::unordered_set<std::string> const&
getTxTypesInLowercase() getTxTypesInLowercase()
{ {

View File

@@ -41,10 +41,16 @@ namespace util::async {
*/ */
class AnyExecutionContext { class AnyExecutionContext {
public: public:
/**
* @brief Construct a new type-erased Execution Context object
*
* @tparam CtxType The type of the execution context to wrap
* @param ctx The execution context to wrap
*/
template <typename CtxType> template <typename CtxType>
requires(not std::is_same_v<std::decay_t<CtxType>, AnyExecutionContext>) requires(not std::is_same_v<std::decay_t<CtxType>, AnyExecutionContext>)
/* implicit */ AnyExecutionContext(CtxType&& ctx) /* implicit */
: pimpl_{std::make_unique<Model<CtxType>>(std::forward<CtxType>(ctx))} AnyExecutionContext(CtxType&& ctx) : pimpl_{std::make_unique<Model<CtxType>>(std::forward<CtxType>(ctx))}
{ {
} }

View File

@@ -45,6 +45,12 @@ namespace util::async {
template <typename RetType> template <typename RetType>
class AnyOperation { class AnyOperation {
public: public:
/**
* @brief Construct a new type-erased Operation object
*
* @tparam OpType The type of the operation to wrap
* @param operation The operation to wrap
*/
template <SomeOperation OpType> template <SomeOperation OpType>
requires std::is_same_v<std::decay_t<OpType>, impl::ErasedOperation> requires std::is_same_v<std::decay_t<OpType>, impl::ErasedOperation>
/* implicit */ AnyOperation(OpType&& operation) : operation_{std::forward<OpType>(operation)} /* implicit */ AnyOperation(OpType&& operation) : operation_{std::forward<OpType>(operation)}
@@ -60,7 +66,10 @@ public:
AnyOperation& AnyOperation&
operator=(AnyOperation&&) = default; operator=(AnyOperation&&) = default;
/** @brief Wait for the operation to complete */ /**
* @brief Wait for the operation to complete
* @note This will block the current thread until the operation is complete
*/
void void
wait() noexcept wait() noexcept
{ {
@@ -81,7 +90,11 @@ public:
operation_.cancel(); operation_.cancel();
} }
/** @brief Get the result of the operation */ /**
* @brief Get the result of the operation
*
* @return The result of the operation
*/
[[nodiscard]] util::Expected<RetType, ExecutionError> [[nodiscard]] util::Expected<RetType, ExecutionError>
get() get()
{ {

View File

@@ -34,6 +34,12 @@ namespace util::async {
*/ */
class AnyStopToken { class AnyStopToken {
public: public:
/**
* @brief Construct a new type-erased Stop Token object
*
* @tparam TokenType The type of the stop token to wrap
* @param token The stop token to wrap
*/
template <SomeStopToken TokenType> template <SomeStopToken TokenType>
requires(not std::is_same_v<std::decay_t<TokenType>, AnyStopToken>) requires(not std::is_same_v<std::decay_t<TokenType>, AnyStopToken>)
/* implicit */ AnyStopToken(TokenType&& token) /* implicit */ AnyStopToken(TokenType&& token)
@@ -41,6 +47,7 @@ public:
{ {
} }
/** @cond */
~AnyStopToken() = default; ~AnyStopToken() = default;
AnyStopToken(AnyStopToken const& other) : pimpl_{other.pimpl_->clone()} AnyStopToken(AnyStopToken const& other) : pimpl_{other.pimpl_->clone()}
@@ -56,25 +63,37 @@ public:
} }
AnyStopToken(AnyStopToken&&) = default; AnyStopToken(AnyStopToken&&) = default;
AnyStopToken& AnyStopToken&
operator=(AnyStopToken&&) = default; operator=(AnyStopToken&&) = default;
/** @endcond */
/** @returns true if stop is requested; false otherwise */ /**
* @brief Check if stop is requested
*
* @returns true if stop is requested; false otherwise
*/
[[nodiscard]] bool [[nodiscard]] bool
isStopRequested() const noexcept isStopRequested() const noexcept
{ {
return pimpl_->isStopRequested(); return pimpl_->isStopRequested();
} }
/** @returns true if stop is requested; false otherwise */ /**
* @brief Check if stop is requested
*
* @returns true if stop is requested; false otherwise
*/
[[nodiscard]] operator bool() const noexcept [[nodiscard]] operator bool() const noexcept
{ {
return isStopRequested(); return isStopRequested();
} }
/** /**
* @returns The underlying boost::asio::yield_context * @brief Get the underlying boost::asio::yield_context
* @note ASSERTs if the stop token is not convertible to boost::asio::yield_context * @note ASSERTs if the stop token is not convertible to boost::asio::yield_context
*
* @returns The underlying boost::asio::yield_context
*/ */
[[nodiscard]] operator boost::asio::yield_context() const [[nodiscard]] operator boost::asio::yield_context() const
{ {

View File

@@ -39,6 +39,12 @@ namespace util::async {
*/ */
class AnyStrand { class AnyStrand {
public: public:
/**
* @brief Construct a new Any Strand object
*
* @tparam StrandType The type of the strand to wrap
* @param strand The strand to wrap
*/
template <typename StrandType> template <typename StrandType>
requires(not std::is_same_v<std::decay_t<StrandType>, AnyStrand>) requires(not std::is_same_v<std::decay_t<StrandType>, AnyStrand>)
/* implicit */ AnyStrand(StrandType&& strand) /* implicit */ AnyStrand(StrandType&& strand)
@@ -48,7 +54,12 @@ public:
~AnyStrand() = default; ~AnyStrand() = default;
/** @brief Execute a function without a stop token on the strand */ /**
* @brief Execute a function without a stop token on the strand
*
* @param fn The function to execute
* @return The type-erased operation
*/
[[nodiscard]] auto [[nodiscard]] auto
execute(SomeHandlerWithoutStopToken auto&& fn) execute(SomeHandlerWithoutStopToken auto&& fn)
{ {
@@ -67,7 +78,12 @@ public:
); );
} }
/** @brief Execute a function taking a stop token on the strand */ /**
* @brief Execute a function taking a stop token on the strand
*
* @param fn The function to execute
* @return The type-erased operation
*/
[[nodiscard]] auto [[nodiscard]] auto
execute(SomeHandlerWith<AnyStopToken> auto&& fn) execute(SomeHandlerWith<AnyStopToken> auto&& fn)
{ {
@@ -86,7 +102,13 @@ public:
); );
} }
/** @brief Execute a function taking a stop token on the strand with a timeout */ /**
* @brief Execute a function taking a stop token on the strand with a timeout
*
* @param fn The function to execute
* @param timeout The timeout for the function
* @return The type-erased operation
*/
[[nodiscard]] auto [[nodiscard]] auto
execute(SomeHandlerWith<AnyStopToken> auto&& fn, SomeStdDuration auto timeout) execute(SomeHandlerWith<AnyStopToken> auto&& fn, SomeStdDuration auto timeout)
{ {

View File

@@ -27,6 +27,9 @@
namespace util::async { namespace util::async {
/**
* @brief Specifies the interface for an entity that can be stopped
*/
template <typename T> template <typename T>
concept SomeStoppable = requires(T v) { concept SomeStoppable = requires(T v) {
{ {
@@ -34,6 +37,9 @@ concept SomeStoppable = requires(T v) {
} -> std::same_as<void>; } -> std::same_as<void>;
}; };
/**
* @brief Specifies the interface for an entity that can be cancelled
*/
template <typename T> template <typename T>
concept SomeCancellable = requires(T v) { concept SomeCancellable = requires(T v) {
{ {
@@ -41,6 +47,9 @@ concept SomeCancellable = requires(T v) {
} -> std::same_as<void>; } -> std::same_as<void>;
}; };
/**
* @brief Specifies the interface for an operation
*/
template <typename T> template <typename T>
concept SomeOperation = requires(T v) { concept SomeOperation = requires(T v) {
{ {
@@ -51,12 +60,21 @@ concept SomeOperation = requires(T v) {
}; };
}; };
/**
* @brief Specifies the interface for an operation that can be stopped
*/
template <typename T> template <typename T>
concept SomeStoppableOperation = SomeOperation<T> and SomeStoppable<T>; concept SomeStoppableOperation = SomeOperation<T> and SomeStoppable<T>;
/**
* @brief Specifies the interface for an operation that can be cancelled
*/
template <typename T> template <typename T>
concept SomeCancellableOperation = SomeOperation<T> and SomeCancellable<T>; concept SomeCancellableOperation = SomeOperation<T> and SomeCancellable<T>;
/**
* @brief Specifies the interface for an outcome (promise)
*/
template <typename T> template <typename T>
concept SomeOutcome = requires(T v) { concept SomeOutcome = requires(T v) {
{ {
@@ -64,6 +82,9 @@ concept SomeOutcome = requires(T v) {
} -> SomeOperation; } -> SomeOperation;
}; };
/**
* @brief Specifies the interface for a stop token
*/
template <typename T> template <typename T>
concept SomeStopToken = requires(T v) { concept SomeStopToken = requires(T v) {
{ {
@@ -71,6 +92,9 @@ concept SomeStopToken = requires(T v) {
} -> std::same_as<bool>; } -> std::same_as<bool>;
}; };
/**
* @brief Specifies the interface for a stop token that internally uses a boost::asio::yield_context
*/
template <typename T> template <typename T>
concept SomeYieldStopSource = requires(T v, boost::asio::yield_context yield) { concept SomeYieldStopSource = requires(T v, boost::asio::yield_context yield) {
{ {
@@ -78,6 +102,9 @@ concept SomeYieldStopSource = requires(T v, boost::asio::yield_context yield) {
} -> SomeStopToken; } -> SomeStopToken;
}; };
/**
* @brief Specifies the interface for a simple stop token
*/
template <typename T> template <typename T>
concept SomeSimpleStopSource = requires(T v) { concept SomeSimpleStopSource = requires(T v) {
{ {
@@ -85,9 +112,15 @@ concept SomeSimpleStopSource = requires(T v) {
} -> SomeStopToken; } -> SomeStopToken;
}; };
/**
* @brief Specifies the interface for a stop source
*/
template <typename T> template <typename T>
concept SomeStopSource = (SomeSimpleStopSource<T> or SomeYieldStopSource<T>)and SomeStoppable<T>; concept SomeStopSource = (SomeSimpleStopSource<T> or SomeYieldStopSource<T>)and SomeStoppable<T>;
/**
* @brief Specifies the interface for a provider of stop sources
*/
template <typename T> template <typename T>
concept SomeStopSourceProvider = requires(T v) { concept SomeStopSourceProvider = requires(T v) {
{ {
@@ -95,9 +128,15 @@ concept SomeStopSourceProvider = requires(T v) {
} -> SomeStopSource; } -> SomeStopSource;
}; };
/**
* @brief Specifies the interface for an outcome (promise) that can be stopped
*/
template <typename T> template <typename T>
concept SomeStoppableOutcome = SomeOutcome<T> and SomeStopSourceProvider<T>; concept SomeStoppableOutcome = SomeOutcome<T> and SomeStopSourceProvider<T>;
/**
* @brief Specifies the interface for a handler that can be stopped
*/
template <typename T> template <typename T>
concept SomeHandlerWithoutStopToken = requires(T fn) { concept SomeHandlerWithoutStopToken = requires(T fn) {
{ {
@@ -105,6 +144,9 @@ concept SomeHandlerWithoutStopToken = requires(T fn) {
}; };
}; };
/**
* @brief Specifies the interface for a handler that can be invoked with the specified args
*/
template <typename T, typename... Args> template <typename T, typename... Args>
concept SomeHandlerWith = requires(T fn) { concept SomeHandlerWith = requires(T fn) {
{ {
@@ -112,6 +154,9 @@ concept SomeHandlerWith = requires(T fn) {
}; };
}; };
/**
* @brief Specifies that the type must be some std::duration
*/
template <typename T> template <typename T>
concept SomeStdDuration = requires { concept SomeStdDuration = requires {
// Thank you Ed Catmur for this trick. // Thank you Ed Catmur for this trick.
@@ -121,6 +166,9 @@ concept SomeStdDuration = requires {
) {}(std::type_identity<T>()); ) {}(std::type_identity<T>());
}; };
/**
* @brief Specifies that the type must be some std::duration wrapped in an optional
*/
template <typename T> template <typename T>
concept SomeOptStdDuration = requires(T v) { SomeStdDuration<decltype(v.value())>; }; concept SomeOptStdDuration = requires(T v) { SomeStdDuration<decltype(v.value())>; };

View File

@@ -32,6 +32,12 @@ namespace util::async {
* @brief Error channel type for async operation of any ExecutionContext * @brief Error channel type for async operation of any ExecutionContext
*/ */
struct ExecutionError { struct ExecutionError {
/**
* @brief Construct a new Execution Error object
*
* @param tid The thread id
* @param msg The error message
*/
ExecutionError(std::string tid, std::string msg) ExecutionError(std::string tid, std::string msg)
: message{fmt::format("Thread {} exit with exception: {}", std::move(tid), std::move(msg))} : message{fmt::format("Thread {} exit with exception: {}", std::move(tid), std::move(msg))}
{ {
@@ -44,7 +50,12 @@ struct ExecutionError {
ExecutionError& ExecutionError&
operator=(ExecutionError const&) = default; operator=(ExecutionError const&) = default;
operator char const*() const noexcept /**
* @brief Conversion to string
*
* @return The error message as a C string
*/
[[nodiscard]] operator char const*() const noexcept
{ {
return message.c_str(); return message.c_str();
} }

View File

@@ -46,6 +46,7 @@ public:
} }
BasicOperation(BasicOperation&&) = default; BasicOperation(BasicOperation&&) = default;
BasicOperation(BasicOperation const&) = delete; BasicOperation(BasicOperation const&) = delete;
[[nodiscard]] auto [[nodiscard]] auto
@@ -136,6 +137,11 @@ class StoppableOperation : public impl::BasicOperation<StoppableOutcome<RetType,
StopSourceType stopSource_; StopSourceType stopSource_;
public: public:
/**
* @brief Construct a new Stoppable Operation object
*
* @param outcome The outcome to wrap
*/
explicit StoppableOperation(OutcomeType* outcome) explicit StoppableOperation(OutcomeType* outcome)
: impl::BasicOperation<OutcomeType>(outcome), stopSource_(outcome->getStopSource()) : impl::BasicOperation<OutcomeType>(outcome), stopSource_(outcome->getStopSource())
{ {

View File

@@ -48,23 +48,34 @@ public:
BasicOutcome() = default; BasicOutcome() = default;
BasicOutcome(BasicOutcome&&) = default; BasicOutcome(BasicOutcome&&) = default;
BasicOutcome(BasicOutcome const&) = delete; BasicOutcome(BasicOutcome const&) = delete;
/** @brief Sets the value on the inner `promise` */ /**
* @brief Sets the value on the inner `promise`
*
* @param val The value to set
*/
void void
setValue(std::convertible_to<RetType> auto&& val) setValue(std::convertible_to<RetType> auto&& val)
{ {
promise_.set_value(std::forward<decltype(val)>(val)); promise_.set_value(std::forward<decltype(val)>(val));
} }
/** @brief Sets the value channel for void operations */ /**
* @brief Sets the value channel for void operations
*/
void void
setValue() setValue()
{ {
promise_.set_value({}); promise_.set_value({});
} }
/** @brief Get the `future` for the inner `promise` */ /**
* @brief Get the `future` for the inner `promise`
*
* @return The standard future matching the inner `promise`
*/
[[nodiscard]] std::future<RetType> [[nodiscard]] std::future<RetType>
getStdFuture() getStdFuture()
{ {
@@ -82,7 +93,11 @@ public:
template <typename RetType> template <typename RetType>
class Outcome : public impl::BasicOutcome<RetType> { class Outcome : public impl::BasicOutcome<RetType> {
public: public:
/** @brief Gets the unstoppable operation for this outcome */ /**
* @brief Gets the unstoppable operation for this outcome
*
* @return An unstoppable operation for this outcome
*/
[[nodiscard]] impl::BasicOperation<Outcome> [[nodiscard]] impl::BasicOperation<Outcome>
getOperation() getOperation()
{ {
@@ -102,14 +117,22 @@ private:
StopSourceType stopSource_; StopSourceType stopSource_;
public: public:
/** @brief Gets the stoppable operation for this outcome */ /**
* @brief Gets the stoppable operation for this outcome
*
* @return A stoppable operation for this outcome
*/
[[nodiscard]] StoppableOperation<RetType, StopSourceType> [[nodiscard]] StoppableOperation<RetType, StopSourceType>
getOperation() getOperation()
{ {
return StoppableOperation<RetType, StopSourceType>{this}; return StoppableOperation<RetType, StopSourceType>{this};
} }
/** @brief Gets the stop source for this outcome */ /**
* @brief Gets the stop source for this outcome
*
* @return The stop source
*/
[[nodiscard]] StopSourceType& [[nodiscard]] StopSourceType&
getStopSource() getStopSource()
{ {

View File

@@ -42,6 +42,16 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
/**
* @brief This namespace implements an async framework built on top of execution contexts
*
* There are multiple execution contexts available, each with its own set of features and trade-offs.
*
* @see util::async::CoroExecutionContext
* @see util::async::PoolExecutionContext
* @see util::async::SyncExecutionContext
* @see util::async::SystemExecutionContext
*/
namespace util::async { namespace util::async {
namespace impl { namespace impl {
@@ -84,12 +94,17 @@ template <
typename ErrorHandlerType = impl::DefaultErrorHandler> typename ErrorHandlerType = impl::DefaultErrorHandler>
class BasicExecutionContext { class BasicExecutionContext {
ContextType context_; ContextType context_;
/** @cond */
friend impl::AssociatedExecutorExtractor; friend impl::AssociatedExecutorExtractor;
/** @endcond */
public: public:
/** @brief Whether operations on this execution context are noexcept */
static constexpr bool isNoexcept = noexcept(ErrorHandlerType::wrap([](auto&) { throw 0; })); static constexpr bool isNoexcept = noexcept(ErrorHandlerType::wrap([](auto&) { throw 0; }));
using ContextHolderType = ContextType; using ContextHolderType = ContextType;
using ExecutorType = typename ContextHolderType::Executor; using ExecutorType = typename ContextHolderType::Executor;
template <typename T> template <typename T>
@@ -110,7 +125,12 @@ public:
using Timer = typename ContextHolderType::Timer; using Timer = typename ContextHolderType::Timer;
// note: scheduled operations are always stoppable /**
* @brief Create a new execution context with the given number of threads.
*
* Note: scheduled operations are always stoppable
* @tparam T The type of the value returned by operations
*/
template <typename T> template <typename T>
using ScheduledOperation = ScheduledOperation<BasicExecutionContext, StoppableOperation<T>>; using ScheduledOperation = ScheduledOperation<BasicExecutionContext, StoppableOperation<T>>;
@@ -290,6 +310,8 @@ public:
/** /**
* @brief Create a strand for this execution context * @brief Create a strand for this execution context
*
* @return A strand for this execution context
*/ */
[[nodiscard]] Strand [[nodiscard]] Strand
makeStrand() makeStrand()
@@ -311,7 +333,7 @@ public:
* @brief A Boost.Coroutine-based (asio yield_context) execution context. * @brief A Boost.Coroutine-based (asio yield_context) execution context.
* *
* This execution context uses `asio::spawn` to create a coroutine per executed operation. * This execution context uses `asio::spawn` to create a coroutine per executed operation.
* The stop token that is sent to the lambda to execute is @ref impl::YieldContextStopSource::Token * The stop token that is sent to the lambda to execute is YieldContextStopSource::Token
* and is special in the way that each time your code checks `token.isStopRequested()` the coroutine will * and is special in the way that each time your code checks `token.isStopRequested()` the coroutine will
* be suspended and other work such as timers and/or other operations in the queue will get a chance to run. * be suspended and other work such as timers and/or other operations in the queue will get a chance to run.
* This makes it possible to have 1 thread in the execution context and still be able to execute operations AND timers * This makes it possible to have 1 thread in the execution context and still be able to execute operations AND timers

View File

@@ -31,6 +31,11 @@ namespace util::async {
*/ */
class SystemExecutionContext { class SystemExecutionContext {
public: public:
/**
* @brief Get the instance of the system execution context
*
* @return Reference to the global system execution context
*/
[[nodiscard]] static auto& [[nodiscard]] static auto&
instance() instance()
{ {

View File

@@ -63,8 +63,8 @@ public:
public: public:
Token(Token const&) = default; Token(Token const&) = default;
Token(Token&&) = default;
Token(Token&&) = default;
[[nodiscard]] bool [[nodiscard]] bool
isStopRequested() const noexcept isStopRequested() const noexcept
{ {
@@ -111,8 +111,8 @@ public:
public: public:
Token(Token const&) = default; Token(Token const&) = default;
Token(Token&&) = default;
Token(Token&&) = default;
[[nodiscard]] bool [[nodiscard]] bool
isStopRequested() const noexcept isStopRequested() const noexcept
{ {

View File

@@ -60,6 +60,7 @@ public:
~BasicStrand() = default; ~BasicStrand() = default;
BasicStrand(BasicStrand&&) = default; BasicStrand(BasicStrand&&) = default;
BasicStrand(BasicStrand const&) = delete; BasicStrand(BasicStrand const&) = delete;
[[nodiscard]] auto [[nodiscard]] auto

View File

@@ -40,6 +40,7 @@ public:
} }
SteadyTimer(SteadyTimer&&) = default; SteadyTimer(SteadyTimer&&) = default;
SteadyTimer(SteadyTimer const&) = delete; SteadyTimer(SteadyTimer const&) = delete;
void void

View File

@@ -37,8 +37,8 @@ class Any {
public: public:
Any() = default; Any() = default;
Any(Any const&) = default; Any(Any const&) = default;
Any(Any&&) = default;
Any(Any&&) = default;
// note: this needs to be `auto` instead of `std::any` because of a bug in gcc 11.4 // note: this needs to be `auto` instead of `std::any` because of a bug in gcc 11.4
Any(auto&& v) Any(auto&& v)
requires(std::is_same_v<std::decay_t<decltype(v)>, std::any>) requires(std::is_same_v<std::decay_t<decltype(v)>, std::any>)

Some files were not shown because too many files have changed in this diff Show More