refactor: Use std::expected instead of std::variant for errors (#2160)

This commit is contained in:
Ayaz Salikhov
2025-06-03 13:34:25 +01:00
committed by GitHub
parent 19257f8aa9
commit 550f0fae85
40 changed files with 295 additions and 310 deletions

View File

@@ -163,19 +163,17 @@ public:
[this, &ctx](boost::asio::yield_context [this, &ctx](boost::asio::yield_context
) -> std::expected<util::ResponseExpirationCache::EntryData, util::ResponseExpirationCache::Error> { ) -> std::expected<util::ResponseExpirationCache::EntryData, util::ResponseExpirationCache::Error> {
auto result = buildResponseImpl(ctx); auto result = buildResponseImpl(ctx);
auto extracted = std::visit(
util::OverloadSet{ auto const extracted =
[&result](Status status [&result]() -> std::expected<boost::json::object, util::ResponseExpirationCache::Error> {
) -> std::expected<boost::json::object, util::ResponseExpirationCache::Error> { if (result.response.has_value())
return std::move(result.response).value();
else
return std::unexpected{util::ResponseExpirationCache::Error{ return std::unexpected{util::ResponseExpirationCache::Error{
.status = std::move(status), .warnings = std::move(result.warnings) .status = std::move(result.response).error(), .warnings = std::move(result.warnings)
}}; }};
}, }();
[](boost::json::object obj
) -> std::expected<boost::json::object, util::ResponseExpirationCache::Error> { return obj; }
},
std::move(result.response)
);
if (extracted.has_value()) { if (extracted.has_value()) {
return util::ResponseExpirationCache::EntryData{ return util::ResponseExpirationCache::EntryData{
.lastUpdated = std::chrono::steady_clock::now(), .response = std::move(extracted).value() .lastUpdated = std::chrono::steady_clock::now(), .response = std::move(extracted).value()

View File

@@ -467,23 +467,23 @@ parseStringAsUInt(std::string const& value)
return index; return index;
} }
std::variant<Status, ripple::LedgerHeader> std::expected<ripple::LedgerHeader, Status>
ledgerHeaderFromRequest(std::shared_ptr<data::BackendInterface const> const& backend, web::Context const& ctx) ledgerHeaderFromRequest(std::shared_ptr<data::BackendInterface const> const& backend, web::Context const& ctx)
{ {
auto hashValue = ctx.params.contains("ledger_hash") ? ctx.params.at("ledger_hash") : nullptr; auto hashValue = ctx.params.contains("ledger_hash") ? ctx.params.at("ledger_hash") : nullptr;
if (!hashValue.is_null()) { if (!hashValue.is_null()) {
if (!hashValue.is_string()) if (!hashValue.is_string())
return Status{RippledError::rpcINVALID_PARAMS, "ledgerHashNotString"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "ledgerHashNotString"}};
ripple::uint256 ledgerHash; ripple::uint256 ledgerHash;
if (!ledgerHash.parseHex(boost::json::value_to<std::string>(hashValue))) if (!ledgerHash.parseHex(boost::json::value_to<std::string>(hashValue)))
return Status{RippledError::rpcINVALID_PARAMS, "ledgerHashMalformed"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "ledgerHashMalformed"}};
auto lgrInfo = backend->fetchLedgerByHash(ledgerHash, ctx.yield); auto lgrInfo = backend->fetchLedgerByHash(ledgerHash, ctx.yield);
if (!lgrInfo || lgrInfo->seq > ctx.range.maxSequence) if (!lgrInfo || lgrInfo->seq > ctx.range.maxSequence)
return Status{RippledError::rpcLGR_NOT_FOUND, "ledgerNotFound"}; return std::unexpected{Status{RippledError::rpcLGR_NOT_FOUND, "ledgerNotFound"}};
return *lgrInfo; return *lgrInfo;
} }
@@ -507,18 +507,18 @@ ledgerHeaderFromRequest(std::shared_ptr<data::BackendInterface const> const& bac
} }
if (!ledgerSequence) if (!ledgerSequence)
return Status{RippledError::rpcINVALID_PARAMS, "ledgerIndexMalformed"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "ledgerIndexMalformed"}};
auto lgrInfo = backend->fetchLedgerBySequence(*ledgerSequence, ctx.yield); auto lgrInfo = backend->fetchLedgerBySequence(*ledgerSequence, ctx.yield);
if (!lgrInfo || lgrInfo->seq > ctx.range.maxSequence) if (!lgrInfo || lgrInfo->seq > ctx.range.maxSequence)
return Status{RippledError::rpcLGR_NOT_FOUND, "ledgerNotFound"}; return std::unexpected{Status{RippledError::rpcLGR_NOT_FOUND, "ledgerNotFound"}};
return *lgrInfo; return *lgrInfo;
} }
// extract ledgerHeaderFromRequest's parameter from context // extract ledgerHeaderFromRequest's parameter from context
std::variant<Status, ripple::LedgerHeader> std::expected<ripple::LedgerHeader, Status>
getLedgerHeaderFromHashOrSeq( getLedgerHeaderFromHashOrSeq(
BackendInterface const& backend, BackendInterface const& backend,
boost::asio::yield_context yield, boost::asio::yield_context yield,
@@ -528,7 +528,7 @@ getLedgerHeaderFromHashOrSeq(
) )
{ {
std::optional<ripple::LedgerHeader> lgrInfo; std::optional<ripple::LedgerHeader> lgrInfo;
auto err = Status{RippledError::rpcLGR_NOT_FOUND, "ledgerNotFound"}; auto const err = std::unexpected{Status{RippledError::rpcLGR_NOT_FOUND, "ledgerNotFound"}};
if (ledgerHash) { if (ledgerHash) {
// invoke uint256's constructor to parse the hex string , instead of // invoke uint256's constructor to parse the hex string , instead of
// copying buffer // copying buffer
@@ -589,7 +589,7 @@ getStartHint(ripple::SLE const& sle, ripple::AccountID const& accountID)
// traverse account's nfts // traverse account's nfts
// return Status if error occurs // return Status if error occurs
// return [nextpage, count of nft already found] if success // return [nextpage, count of nft already found] if success
std::variant<Status, AccountCursor> std::expected<AccountCursor, Status>
traverseNFTObjects( traverseNFTObjects(
BackendInterface const& backend, BackendInterface const& backend,
std::uint32_t sequence, std::uint32_t sequence,
@@ -605,7 +605,7 @@ traverseNFTObjects(
// check if nextPage is valid // check if nextPage is valid
if (nextPage != beast::zero and firstNFTPage.key != (nextPage & ~ripple::nft::pageMask)) if (nextPage != beast::zero and firstNFTPage.key != (nextPage & ~ripple::nft::pageMask))
return Status{RippledError::rpcINVALID_PARAMS, "Invalid marker."}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "Invalid marker."}};
// no marker, start from the last page // no marker, start from the last page
ripple::uint256 const currentPage = nextPage == beast::zero ? lastNFTPage.key : nextPage; ripple::uint256 const currentPage = nextPage == beast::zero ? lastNFTPage.key : nextPage;
@@ -618,7 +618,7 @@ traverseNFTObjects(
return AccountCursor{.index = beast::zero, .hint = 0}; return AccountCursor{.index = beast::zero, .hint = 0};
} }
// marker is in the right range, but still invalid // marker is in the right range, but still invalid
return Status{RippledError::rpcINVALID_PARAMS, "Invalid marker."}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "Invalid marker."}};
} }
// the object exists and the key is in right range, must be nft page // the object exists and the key is in right range, must be nft page
@@ -641,7 +641,7 @@ traverseNFTObjects(
return AccountCursor{.index = beast::zero, .hint = 0}; return AccountCursor{.index = beast::zero, .hint = 0};
} }
std::variant<Status, AccountCursor> std::expected<AccountCursor, Status>
traverseOwnedNodes( traverseOwnedNodes(
BackendInterface const& backend, BackendInterface const& backend,
ripple::AccountID const& accountID, ripple::AccountID const& accountID,
@@ -656,7 +656,7 @@ traverseOwnedNodes(
auto const maybeCursor = parseAccountCursor(jsonCursor); auto const maybeCursor = parseAccountCursor(jsonCursor);
if (!maybeCursor) if (!maybeCursor)
return Status{RippledError::rpcINVALID_PARAMS, "Malformed cursor."}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "Malformed cursor."}};
// the format is checked in RPC framework level // the format is checked in RPC framework level
auto [hexCursor, startHint] = *maybeCursor; auto [hexCursor, startHint] = *maybeCursor;
@@ -670,10 +670,10 @@ traverseOwnedNodes(
if (nftIncluded and (!jsonCursor or isNftMarkerNonZero)) { if (nftIncluded and (!jsonCursor or isNftMarkerNonZero)) {
auto const cursorMaybe = traverseNFTObjects(backend, sequence, accountID, hexCursor, limit, yield, atOwnedNode); auto const cursorMaybe = traverseNFTObjects(backend, sequence, accountID, hexCursor, limit, yield, atOwnedNode);
if (auto const status = std::get_if<Status>(&cursorMaybe)) if (!cursorMaybe.has_value())
return *status; return cursorMaybe;
auto const [nextNFTPage, nftsCount] = std::get<AccountCursor>(cursorMaybe); auto const [nextNFTPage, nftsCount] = cursorMaybe.value();
// if limit reach , we return the next page and max as marker // if limit reach , we return the next page and max as marker
if (nftsCount >= limit) if (nftsCount >= limit)
@@ -694,7 +694,7 @@ traverseOwnedNodes(
); );
} }
std::variant<Status, AccountCursor> std::expected<AccountCursor, Status>
traverseOwnedNodes( traverseOwnedNodes(
BackendInterface const& backend, BackendInterface const& backend,
ripple::Keylet const& owner, ripple::Keylet const& owner,
@@ -728,7 +728,7 @@ traverseOwnedNodes(
auto hintDir = backend.fetchLedgerObject(hintIndex.key, sequence, yield); auto hintDir = backend.fetchLedgerObject(hintIndex.key, sequence, yield);
if (!hintDir) if (!hintDir)
return Status(ripple::rpcINVALID_PARAMS, "Invalid marker."); return std::unexpected{Status(ripple::rpcINVALID_PARAMS, "Invalid marker.")};
ripple::SerialIter hintDirIt{hintDir->data(), hintDir->size()}; ripple::SerialIter hintDirIt{hintDir->data(), hintDir->size()};
ripple::SLE const hintDirSle{hintDirIt, hintIndex.key}; ripple::SLE const hintDirSle{hintDirIt, hintIndex.key};
@@ -736,7 +736,7 @@ traverseOwnedNodes(
if (auto const& indexes = hintDirSle.getFieldV256(ripple::sfIndexes); if (auto const& indexes = hintDirSle.getFieldV256(ripple::sfIndexes);
std::ranges::find(indexes, hexMarker) == std::end(indexes)) { std::ranges::find(indexes, hexMarker) == std::end(indexes)) {
// the index specified by marker is not in the page specified by marker // the index specified by marker is not in the page specified by marker
return Status(ripple::rpcINVALID_PARAMS, "Invalid marker."); return std::unexpected{Status(ripple::rpcINVALID_PARAMS, "Invalid marker.")};
} }
currentIndex = hintIndex; currentIndex = hintIndex;
@@ -745,7 +745,7 @@ traverseOwnedNodes(
auto const ownerDir = backend.fetchLedgerObject(currentIndex.key, sequence, yield); auto const ownerDir = backend.fetchLedgerObject(currentIndex.key, sequence, yield);
if (!ownerDir) if (!ownerDir)
return Status(ripple::rpcINVALID_PARAMS, "Owner directory not found."); return std::unexpected{Status(ripple::rpcINVALID_PARAMS, "Owner directory not found.")};
ripple::SerialIter ownedDirIt{ownerDir->data(), ownerDir->size()}; ripple::SerialIter ownedDirIt{ownerDir->data(), ownerDir->size()};
ripple::SLE const ownedDirSle{ownedDirIt, currentIndex.key}; ripple::SLE const ownedDirSle{ownedDirIt, currentIndex.key};
@@ -1309,120 +1309,122 @@ postProcessOrderBook(
} }
// get book via currency type // get book via currency type
std::variant<Status, ripple::Book> std::expected<ripple::Book, Status>
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)
{ {
if (isXRP(pays) && !isXRP(payIssuer)) { if (isXRP(pays) && !isXRP(payIssuer)) {
return Status{ return std::unexpected{Status{
RippledError::rpcSRC_ISR_MALFORMED, "Unneeded field 'taker_pays.issuer' for XRP currency specification." RippledError::rpcSRC_ISR_MALFORMED, "Unneeded field 'taker_pays.issuer' for XRP currency specification."
}; }};
} }
if (!isXRP(pays) && isXRP(payIssuer)) { if (!isXRP(pays) && isXRP(payIssuer)) {
return Status{ return std::unexpected{
RippledError::rpcSRC_ISR_MALFORMED, "Invalid field 'taker_pays.issuer', expected non-XRP issuer." Status{RippledError::rpcSRC_ISR_MALFORMED, "Invalid field 'taker_pays.issuer', expected non-XRP issuer."}
}; };
} }
if (ripple::isXRP(gets) && !ripple::isXRP(getIssuer)) { if (ripple::isXRP(gets) && !ripple::isXRP(getIssuer)) {
return Status{ return std::unexpected{Status{
RippledError::rpcDST_ISR_MALFORMED, "Unneeded field 'taker_gets.issuer' for XRP currency specification." RippledError::rpcDST_ISR_MALFORMED, "Unneeded field 'taker_gets.issuer' for XRP currency specification."
}; }};
} }
if (!ripple::isXRP(gets) && ripple::isXRP(getIssuer)) { if (!ripple::isXRP(gets) && ripple::isXRP(getIssuer)) {
return Status{ return std::unexpected{
RippledError::rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', expected non-XRP issuer." Status{RippledError::rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', expected non-XRP issuer."}
}; };
} }
if (pays == gets && payIssuer == getIssuer) if (pays == gets && payIssuer == getIssuer)
return Status{RippledError::rpcBAD_MARKET, "badMarket"}; return std::unexpected{Status{RippledError::rpcBAD_MARKET, "badMarket"}};
return ripple::Book{{pays, payIssuer}, {gets, getIssuer}}; return ripple::Book{{pays, payIssuer}, {gets, getIssuer}};
} }
std::variant<Status, ripple::Book> std::expected<ripple::Book, Status>
parseBook(boost::json::object const& request) parseBook(boost::json::object const& request)
{ {
if (!request.contains("taker_pays")) if (!request.contains("taker_pays"))
return Status{RippledError::rpcINVALID_PARAMS, "Missing field 'taker_pays'"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "Missing field 'taker_pays'"}};
if (!request.contains("taker_gets")) if (!request.contains("taker_gets"))
return Status{RippledError::rpcINVALID_PARAMS, "Missing field 'taker_gets'"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "Missing field 'taker_gets'"}};
if (!request.at("taker_pays").is_object()) if (!request.at("taker_pays").is_object())
return Status{RippledError::rpcINVALID_PARAMS, "Field 'taker_pays' is not an object"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "Field 'taker_pays' is not an object"}};
if (!request.at("taker_gets").is_object()) if (!request.at("taker_gets").is_object())
return Status{RippledError::rpcINVALID_PARAMS, "Field 'taker_gets' is not an object"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "Field 'taker_gets' is not an object"}};
auto takerPays = request.at("taker_pays").as_object(); auto takerPays = request.at("taker_pays").as_object();
if (!takerPays.contains("currency")) if (!takerPays.contains("currency"))
return Status{RippledError::rpcSRC_CUR_MALFORMED}; return std::unexpected{Status{RippledError::rpcSRC_CUR_MALFORMED}};
if (!takerPays.at("currency").is_string()) if (!takerPays.at("currency").is_string())
return Status{RippledError::rpcSRC_CUR_MALFORMED}; return std::unexpected{Status{RippledError::rpcSRC_CUR_MALFORMED}};
auto takerGets = request.at("taker_gets").as_object(); auto takerGets = request.at("taker_gets").as_object();
if (!takerGets.contains("currency")) if (!takerGets.contains("currency"))
return Status{RippledError::rpcDST_AMT_MALFORMED}; return std::unexpected{Status{RippledError::rpcDST_AMT_MALFORMED}};
if (!takerGets.at("currency").is_string()) { if (!takerGets.at("currency").is_string()) {
return Status{ return std::unexpected{Status{
RippledError::rpcDST_AMT_MALFORMED, RippledError::rpcDST_AMT_MALFORMED,
}; }};
} }
ripple::Currency payCurrency; ripple::Currency payCurrency;
if (!ripple::to_currency(payCurrency, boost::json::value_to<std::string>(takerPays.at("currency")))) if (!ripple::to_currency(payCurrency, boost::json::value_to<std::string>(takerPays.at("currency"))))
return Status{RippledError::rpcSRC_CUR_MALFORMED}; return std::unexpected{Status{RippledError::rpcSRC_CUR_MALFORMED}};
ripple::Currency getCurrency; ripple::Currency getCurrency;
if (!ripple::to_currency(getCurrency, boost::json::value_to<std::string>(takerGets["currency"]))) if (!ripple::to_currency(getCurrency, boost::json::value_to<std::string>(takerGets["currency"])))
return Status{RippledError::rpcDST_AMT_MALFORMED}; return std::unexpected{Status{RippledError::rpcDST_AMT_MALFORMED}};
ripple::AccountID payIssuer; ripple::AccountID payIssuer;
if (takerPays.contains("issuer")) { if (takerPays.contains("issuer")) {
if (!takerPays.at("issuer").is_string()) if (!takerPays.at("issuer").is_string())
return Status{RippledError::rpcINVALID_PARAMS, "takerPaysIssuerNotString"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "takerPaysIssuerNotString"}};
if (!ripple::to_issuer(payIssuer, boost::json::value_to<std::string>(takerPays.at("issuer")))) if (!ripple::to_issuer(payIssuer, boost::json::value_to<std::string>(takerPays.at("issuer"))))
return Status{RippledError::rpcSRC_ISR_MALFORMED}; return std::unexpected{Status{RippledError::rpcSRC_ISR_MALFORMED}};
if (payIssuer == ripple::noAccount()) if (payIssuer == ripple::noAccount())
return Status{RippledError::rpcSRC_ISR_MALFORMED}; return std::unexpected{Status{RippledError::rpcSRC_ISR_MALFORMED}};
} else { } else {
payIssuer = ripple::xrpAccount(); payIssuer = ripple::xrpAccount();
} }
if (isXRP(payCurrency) && !isXRP(payIssuer)) { if (isXRP(payCurrency) && !isXRP(payIssuer)) {
return Status{ return std::unexpected{Status{
RippledError::rpcSRC_ISR_MALFORMED, "Unneeded field 'taker_pays.issuer' for XRP currency specification." RippledError::rpcSRC_ISR_MALFORMED, "Unneeded field 'taker_pays.issuer' for XRP currency specification."
}; }};
} }
if (!isXRP(payCurrency) && isXRP(payIssuer)) { if (!isXRP(payCurrency) && isXRP(payIssuer)) {
return Status{ return std::unexpected{
RippledError::rpcSRC_ISR_MALFORMED, "Invalid field 'taker_pays.issuer', expected non-XRP issuer." Status{RippledError::rpcSRC_ISR_MALFORMED, "Invalid field 'taker_pays.issuer', expected non-XRP issuer."}
}; };
} }
if ((!isXRP(payCurrency)) && (!takerPays.contains("issuer"))) if ((!isXRP(payCurrency)) && (!takerPays.contains("issuer")))
return Status{RippledError::rpcSRC_ISR_MALFORMED, "Missing non-XRP issuer."}; return std::unexpected{Status{RippledError::rpcSRC_ISR_MALFORMED, "Missing non-XRP issuer."}};
ripple::AccountID getIssuer; ripple::AccountID getIssuer;
if (takerGets.contains("issuer")) { if (takerGets.contains("issuer")) {
if (!takerGets["issuer"].is_string()) if (!takerGets["issuer"].is_string())
return Status{RippledError::rpcINVALID_PARAMS, "taker_gets.issuer should be string"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "taker_gets.issuer should be string"}};
if (!ripple::to_issuer(getIssuer, boost::json::value_to<std::string>(takerGets.at("issuer")))) if (!ripple::to_issuer(getIssuer, boost::json::value_to<std::string>(takerGets.at("issuer"))))
return Status{RippledError::rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', bad issuer."}; return std::unexpected{
Status{RippledError::rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', bad issuer."}
};
if (getIssuer == ripple::noAccount()) { if (getIssuer == ripple::noAccount()) {
return Status{ return std::unexpected{
RippledError::rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', bad issuer account one." Status{RippledError::rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', bad issuer account one."}
}; };
} }
} else { } else {
@@ -1430,34 +1432,34 @@ parseBook(boost::json::object const& request)
} }
if (ripple::isXRP(getCurrency) && !ripple::isXRP(getIssuer)) { if (ripple::isXRP(getCurrency) && !ripple::isXRP(getIssuer)) {
return Status{ return std::unexpected{Status{
RippledError::rpcDST_ISR_MALFORMED, "Unneeded field 'taker_gets.issuer' for XRP currency specification." RippledError::rpcDST_ISR_MALFORMED, "Unneeded field 'taker_gets.issuer' for XRP currency specification."
}; }};
} }
if (!ripple::isXRP(getCurrency) && ripple::isXRP(getIssuer)) { if (!ripple::isXRP(getCurrency) && ripple::isXRP(getIssuer)) {
return Status{ return std::unexpected{
RippledError::rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', expected non-XRP issuer." Status{RippledError::rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', expected non-XRP issuer."}
}; };
} }
if (payCurrency == getCurrency && payIssuer == getIssuer) if (payCurrency == getCurrency && payIssuer == getIssuer)
return Status{RippledError::rpcBAD_MARKET, "badMarket"}; return std::unexpected{Status{RippledError::rpcBAD_MARKET, "badMarket"}};
return ripple::Book{{payCurrency, payIssuer}, {getCurrency, getIssuer}}; return ripple::Book{{payCurrency, payIssuer}, {getCurrency, getIssuer}};
} }
std::variant<Status, ripple::AccountID> std::expected<ripple::AccountID, Status>
parseTaker(boost::json::value const& taker) parseTaker(boost::json::value const& taker)
{ {
std::optional<ripple::AccountID> takerID = {}; std::optional<ripple::AccountID> takerID = {};
if (!taker.is_string()) if (!taker.is_string())
return {Status{RippledError::rpcINVALID_PARAMS, "takerNotString"}}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "takerNotString"}};
takerID = accountFromStringStrict(boost::json::value_to<std::string>(taker)); takerID = accountFromStringStrict(boost::json::value_to<std::string>(taker));
if (!takerID) if (!takerID)
return Status{RippledError::rpcBAD_ISSUER, "invalidTakerAccount"}; return std::unexpected{Status{RippledError::rpcBAD_ISSUER, "invalidTakerAccount"}};
return *takerID; return *takerID;
} }
@@ -1511,18 +1513,18 @@ isAdminCmd(std::string const& method, boost::json::object const& request)
return false; return false;
} }
std::variant<ripple::uint256, Status> std::expected<ripple::uint256, Status>
getNFTID(boost::json::object const& request) getNFTID(boost::json::object const& request)
{ {
if (!request.contains(JS(nft_id))) if (!request.contains(JS(nft_id)))
return Status{RippledError::rpcINVALID_PARAMS, "missingTokenID"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "missingTokenID"}};
if (!request.at(JS(nft_id)).is_string()) if (!request.at(JS(nft_id)).is_string())
return Status{RippledError::rpcINVALID_PARAMS, "tokenIDNotString"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "tokenIDNotString"}};
ripple::uint256 tokenid; ripple::uint256 tokenid;
if (!tokenid.parseHex(boost::json::value_to<std::string>(request.at(JS(nft_id))))) if (!tokenid.parseHex(boost::json::value_to<std::string>(request.at(JS(nft_id)))))
return Status{RippledError::rpcINVALID_PARAMS, "malformedTokenID"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "malformedTokenID"}};
return tokenid; return tokenid;
} }

View File

@@ -73,7 +73,6 @@
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <utility> #include <utility>
#include <variant>
#include <vector> #include <vector>
namespace rpc { namespace rpc {
@@ -281,7 +280,7 @@ generatePubLedgerMessage(
* @param ctx The context of the request * @param ctx The context of the request
* @return The ledger info or an error status * @return The ledger info or an error status
*/ */
std::variant<Status, ripple::LedgerHeader> std::expected<ripple::LedgerHeader, Status>
ledgerHeaderFromRequest(std::shared_ptr<data::BackendInterface const> const& backend, web::Context const& ctx); ledgerHeaderFromRequest(std::shared_ptr<data::BackendInterface const> const& backend, web::Context const& ctx);
/** /**
@@ -294,7 +293,7 @@ ledgerHeaderFromRequest(std::shared_ptr<data::BackendInterface const> const& bac
* @param maxSeq The maximum sequence to search * @param maxSeq The maximum sequence to search
* @return The ledger info or an error status * @return The ledger info or an error status
*/ */
std::variant<Status, ripple::LedgerHeader> std::expected<ripple::LedgerHeader, Status>
getLedgerHeaderFromHashOrSeq( getLedgerHeaderFromHashOrSeq(
BackendInterface const& backend, BackendInterface const& backend,
boost::asio::yield_context yield, boost::asio::yield_context yield,
@@ -316,7 +315,7 @@ getLedgerHeaderFromHashOrSeq(
* @param atOwnedNode The function to call for each owned node * @param atOwnedNode The function to call for each owned node
* @return The status or the account cursor * @return The status or the account cursor
*/ */
std::variant<Status, AccountCursor> std::expected<AccountCursor, Status>
traverseOwnedNodes( traverseOwnedNodes(
BackendInterface const& backend, BackendInterface const& backend,
ripple::Keylet const& owner, ripple::Keylet const& owner,
@@ -343,7 +342,7 @@ traverseOwnedNodes(
* @param nftIncluded Whether to include NFTs * @param nftIncluded Whether to include NFTs
* @return The status or the account cursor * @return The status or the account cursor
*/ */
std::variant<Status, AccountCursor> std::expected<AccountCursor, Status>
traverseOwnedNodes( traverseOwnedNodes(
BackendInterface const& backend, BackendInterface const& backend,
ripple::AccountID const& accountID, ripple::AccountID const& accountID,
@@ -628,7 +627,7 @@ postProcessOrderBook(
* @param getIssuer The issuer of the currency to get * @param getIssuer The issuer of the currency to get
* @return The book or an error status * @return The book or an error status
*/ */
std::variant<Status, ripple::Book> std::expected<ripple::Book, Status>
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);
/** /**
@@ -637,7 +636,7 @@ parseBook(ripple::Currency pays, ripple::AccountID payIssuer, ripple::Currency g
* @param request The request * @param request The request
* @return The book or an error status * @return The book or an error status
*/ */
std::variant<Status, ripple::Book> std::expected<ripple::Book, Status>
parseBook(boost::json::object const& request); parseBook(boost::json::object const& request);
/** /**
@@ -646,7 +645,7 @@ parseBook(boost::json::object const& request);
* @param taker The taker as json * @param taker The taker as json
* @return The taker account or an error status * @return The taker account or an error status
*/ */
std::variant<Status, ripple::AccountID> std::expected<ripple::AccountID, Status>
parseTaker(boost::json::value const& taker); parseTaker(boost::json::value const& taker);
/** /**
@@ -683,7 +682,7 @@ isAdminCmd(std::string const& method, boost::json::object const& request);
* @param request The request * @param request The request
* @return The NFTID or an error status * @return The NFTID or an error status
*/ */
std::variant<ripple::uint256, Status> std::expected<ripple::uint256, Status>
getNFTID(boost::json::object const& request); getNFTID(boost::json::object const& request);
/** /**
@@ -793,7 +792,7 @@ parseRippleLibSeed(boost::json::value const& value);
* @param atOwnedNode The function to call for each owned node * @param atOwnedNode The function to call for each owned node
* @return The account cursor or an error status * @return The account cursor or an error status
*/ */
std::variant<Status, AccountCursor> std::expected<AccountCursor, Status>
traverseNFTObjects( traverseNFTObjects(
BackendInterface const& backend, BackendInterface const& backend,
std::uint32_t sequence, std::uint32_t sequence,

View File

@@ -100,7 +100,7 @@ struct ReturnType {
*/ */
operator bool() const operator bool() const
{ {
return result.operator bool(); return result.has_value();
} }
std::expected<boost::json::value, Status> result; std::expected<boost::json::value, Status> result;
@@ -137,7 +137,7 @@ struct Result {
if (returnType) { if (returnType) {
response = std::move(returnType.result).value().as_object(); response = std::move(returnType.result).value().as_object();
} else { } else {
response = std::move(returnType.result).error(); response = std::unexpected{std::move(returnType.result).error()};
} }
warnings = std::move(returnType.warnings); warnings = std::move(returnType.warnings);
} }
@@ -147,7 +147,7 @@ struct Result {
* *
* @param status The status to construct the result from * @param status The status to construct the result from
*/ */
explicit Result(Status status) : response{std::move(status)} explicit Result(Status status) : response{std::unexpected{std::move(status)}}
{ {
} }
@@ -160,7 +160,7 @@ struct Result {
{ {
} }
std::variant<Status, boost::json::object> response; std::expected<boost::json::object, Status> response;
boost::json::array warnings; boost::json::array warnings;
}; };

View File

@@ -97,14 +97,14 @@ AMMInfoHandler::process(AMMInfoHandler::Input input, Context const& ctx) const
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "AMMInfo's ledger range must be available"); ASSERT(range.has_value(), "AMMInfo's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
if (input.accountID) { if (input.accountID) {
auto keylet = keylet::account(*input.accountID); auto keylet = keylet::account(*input.accountID);

View File

@@ -86,14 +86,14 @@ AccountChannelsHandler::process(AccountChannelsHandler::Input input, Context con
{ {
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "AccountChannel's ledger range must be available"); ASSERT(range.has_value(), "AccountChannel's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const accountID = accountFromStringStrict(input.account); auto const accountID = accountFromStringStrict(input.account);
auto const accountLedgerObject = auto const accountLedgerObject =
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield); sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);
@@ -114,19 +114,19 @@ AccountChannelsHandler::process(AccountChannelsHandler::Input input, Context con
return true; return true;
}; };
auto const next = traverseOwnedNodes( auto const expectedNext = traverseOwnedNodes(
*sharedPtrBackend_, *accountID, lgrInfo.seq, input.limit, input.marker, ctx.yield, addToResponse *sharedPtrBackend_, *accountID, lgrInfo.seq, input.limit, input.marker, ctx.yield, addToResponse
); );
if (auto status = std::get_if<Status>(&next)) if (!expectedNext.has_value())
return Error{*status}; return Error{expectedNext.error()};
response.account = input.account; response.account = input.account;
response.limit = input.limit; response.limit = input.limit;
response.ledgerHash = ripple::strHex(lgrInfo.hash); response.ledgerHash = ripple::strHex(lgrInfo.hash);
response.ledgerIndex = lgrInfo.seq; response.ledgerIndex = lgrInfo.seq;
auto const nextMarker = std::get<AccountCursor>(next); auto const nextMarker = expectedNext.value();
if (nextMarker.isNonZero()) if (nextMarker.isNonZero())
response.marker = nextMarker.toString(); response.marker = nextMarker.toString();

View File

@@ -48,14 +48,14 @@ AccountCurrenciesHandler::process(AccountCurrenciesHandler::Input input, Context
{ {
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "AccountCurrencies' ledger range must be available"); ASSERT(range.has_value(), "AccountCurrencies' ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const accountID = accountFromStringStrict(input.account); auto const accountID = accountFromStringStrict(input.account);
auto const accountLedgerObject = auto const accountLedgerObject =

View File

@@ -60,14 +60,14 @@ AccountInfoHandler::process(AccountInfoHandler::Input input, Context const& ctx)
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "AccountInfo's ledger range must be available"); ASSERT(range.has_value(), "AccountInfo's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const accountStr = input.account.value_or(input.ident.value_or("")); auto const accountStr = input.account.value_or(input.ident.value_or(""));
auto const accountID = accountFromStringStrict(accountStr); auto const accountID = accountFromStringStrict(accountStr);
auto const accountKeylet = ripple::keylet::account(*accountID); auto const accountKeylet = ripple::keylet::account(*accountID);

View File

@@ -135,14 +135,14 @@ AccountLinesHandler::process(AccountLinesHandler::Input input, Context const& ct
{ {
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "AccountLines' ledger range must be available"); ASSERT(range.has_value(), "AccountLines' ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const accountID = accountFromStringStrict(input.account); auto const accountID = accountFromStringStrict(input.account);
auto const accountLedgerObject = auto const accountLedgerObject =
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield); sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);
@@ -171,14 +171,14 @@ AccountLinesHandler::process(AccountLinesHandler::Input input, Context const& ct
} }
}; };
auto const next = traverseOwnedNodes( auto const expectedNext = traverseOwnedNodes(
*sharedPtrBackend_, *accountID, lgrInfo.seq, input.limit, input.marker, ctx.yield, addToResponse *sharedPtrBackend_, *accountID, lgrInfo.seq, input.limit, input.marker, ctx.yield, addToResponse
); );
if (auto status = std::get_if<Status>(&next)) if (!expectedNext.has_value())
return Error{*status}; return Error{expectedNext.error()};
auto const nextMarker = std::get<AccountCursor>(next); auto const nextMarker = expectedNext.value();
response.account = input.account; response.account = input.account;
response.limit = input.limit; // not documented, response.limit = input.limit; // not documented,

View File

@@ -54,14 +54,14 @@ AccountNFTsHandler::process(AccountNFTsHandler::Input input, Context const& ctx)
{ {
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "AccountNFT's ledger range must be available"); ASSERT(range.has_value(), "AccountNFT's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const accountID = accountFromStringStrict(input.account); auto const accountID = accountFromStringStrict(input.account);
auto const accountLedgerObject = auto const accountLedgerObject =
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield); sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);

View File

@@ -54,14 +54,14 @@ AccountObjectsHandler::process(AccountObjectsHandler::Input input, Context const
{ {
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "AccountObject's ledger range must be available"); ASSERT(range.has_value(), "AccountObject's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const accountID = accountFromStringStrict(input.account); auto const accountID = accountFromStringStrict(input.account);
auto const accountLedgerObject = auto const accountLedgerObject =
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield); sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);
@@ -97,19 +97,19 @@ AccountObjectsHandler::process(AccountObjectsHandler::Input input, Context const
return true; return true;
}; };
auto const next = traverseOwnedNodes( auto const expectedNext = traverseOwnedNodes(
*sharedPtrBackend_, *accountID, lgrInfo.seq, input.limit, input.marker, ctx.yield, addToResponse, true *sharedPtrBackend_, *accountID, lgrInfo.seq, input.limit, input.marker, ctx.yield, addToResponse, true
); );
if (auto status = std::get_if<Status>(&next)) if (!expectedNext.has_value())
return Error{*status}; return Error{expectedNext.error()};
response.ledgerHash = ripple::strHex(lgrInfo.hash); response.ledgerHash = ripple::strHex(lgrInfo.hash);
response.ledgerIndex = lgrInfo.seq; response.ledgerIndex = lgrInfo.seq;
response.limit = input.limit; response.limit = input.limit;
response.account = input.account; response.account = input.account;
auto const& nextMarker = std::get<AccountCursor>(next); auto const& nextMarker = expectedNext.value();
if (nextMarker.isNonZero()) if (nextMarker.isNonZero())
response.marker = nextMarker.toString(); response.marker = nextMarker.toString();

View File

@@ -70,14 +70,14 @@ AccountOffersHandler::process(AccountOffersHandler::Input input, Context const&
{ {
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "AccountOffer's ledger range must be available"); ASSERT(range.has_value(), "AccountOffer's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const accountID = accountFromStringStrict(input.account); auto const accountID = accountFromStringStrict(input.account);
auto const accountLedgerObject = auto const accountLedgerObject =
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield); sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);
@@ -97,14 +97,14 @@ AccountOffersHandler::process(AccountOffersHandler::Input input, Context const&
return true; return true;
}; };
auto const next = traverseOwnedNodes( auto const expectedNext = traverseOwnedNodes(
*sharedPtrBackend_, *accountID, lgrInfo.seq, input.limit, input.marker, ctx.yield, addToResponse *sharedPtrBackend_, *accountID, lgrInfo.seq, input.limit, input.marker, ctx.yield, addToResponse
); );
if (auto const status = std::get_if<Status>(&next)) if (!expectedNext.has_value())
return Error{*status}; return Error{expectedNext.error()};
auto const nextMarker = std::get<AccountCursor>(next); auto const nextMarker = expectedNext.value();
if (nextMarker.isNonZero()) if (nextMarker.isNonZero())
response.marker = nextMarker.toString(); response.marker = nextMarker.toString();

View File

@@ -94,14 +94,14 @@ AccountTxHandler::process(AccountTxHandler::Input input, Context const& ctx) con
if (!input.ledgerIndexMax && !input.ledgerIndexMin) { if (!input.ledgerIndexMax && !input.ledgerIndexMin) {
// mimic rippled, when both range and index specified, respect the range. // mimic rippled, when both range and index specified, respect the range.
// take ledger from ledgerHash or ledgerIndex only when range is not specified // take ledger from ledgerHash or ledgerIndex only when range is not specified
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
maxIndex = minIndex = std::get<ripple::LedgerHeader>(lgrInfoOrStatus).seq; maxIndex = minIndex = expectedLgrInfo.value().seq;
} }
} }

View File

@@ -48,14 +48,14 @@ BookChangesHandler::process(BookChangesHandler::Input input, Context const& ctx)
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "BookChanges' ledger range must be available"); ASSERT(range.has_value(), "BookChanges' ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const transactions = sharedPtrBackend_->fetchAllTransactionsInLedger(lgrInfo.seq, ctx.yield); auto const transactions = sharedPtrBackend_->fetchAllTransactionsInLedger(lgrInfo.seq, ctx.yield);
Output response; Output response;

View File

@@ -47,22 +47,22 @@ BookOffersHandler::Result
BookOffersHandler::process(Input input, Context const& ctx) const BookOffersHandler::process(Input input, Context const& ctx) const
{ {
auto bookMaybe = parseBook(input.paysCurrency, input.paysID, input.getsCurrency, input.getsID); auto bookMaybe = parseBook(input.paysCurrency, input.paysID, input.getsCurrency, input.getsID);
if (auto const status = std::get_if<Status>(&bookMaybe)) if (!bookMaybe.has_value())
return Error{*status}; return Error{bookMaybe.error()};
// check ledger // check ledger
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "BookOffer's ledger range must be available"); ASSERT(range.has_value(), "BookOffer's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const book = std::get<ripple::Book>(bookMaybe); auto const book = bookMaybe.value();
auto const bookKey = getBookBase(book); auto const bookKey = getBookBase(book);
// TODO: Add performance metrics if needed in future // TODO: Add performance metrics if needed in future

View File

@@ -55,14 +55,14 @@ DepositAuthorizedHandler::process(DepositAuthorizedHandler::Input input, Context
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "DepositAuthorized ledger range must be available"); ASSERT(range.has_value(), "DepositAuthorized ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const sourceAccountID = accountFromStringStrict(input.sourceAccount); auto const sourceAccountID = accountFromStringStrict(input.sourceAccount);
auto const destinationAccountID = accountFromStringStrict(input.destinationAccount); auto const destinationAccountID = accountFromStringStrict(input.destinationAccount);

View File

@@ -59,14 +59,14 @@ FeatureHandler::process(FeatureHandler::Input input, Context const& ctx) const
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "Feature's ledger range must be available"); ASSERT(range.has_value(), "Feature's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const& all = amendmentCenter_->getAll(); auto const& all = amendmentCenter_->getAll();
auto searchPredicate = [search = input.feature](auto const& feature) { auto searchPredicate = [search = input.feature](auto const& feature) {

View File

@@ -62,15 +62,15 @@ GatewayBalancesHandler::process(GatewayBalancesHandler::Input input, Context con
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "GatewayBalances' ledger range must be available"); ASSERT(range.has_value(), "GatewayBalances' ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
// check account // check account
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const accountID = accountFromStringStrict(input.account); auto const accountID = accountFromStringStrict(input.account);
auto const accountLedgerObject = auto const accountLedgerObject =
sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield); sharedPtrBackend_->fetchLedgerObject(ripple::keylet::account(*accountID).key, lgrInfo.seq, ctx.yield);
@@ -142,8 +142,8 @@ GatewayBalancesHandler::process(GatewayBalancesHandler::Input input, Context con
addToResponse addToResponse
); );
if (auto status = std::get_if<Status>(&ret)) if (!ret.has_value())
return Error{*status}; return Error{ret.error()};
output.accountID = input.account; output.accountID = input.account;
output.ledgerHash = ripple::strHex(lgrInfo.hash); output.ledgerHash = ripple::strHex(lgrInfo.hash);

View File

@@ -64,14 +64,14 @@ GetAggregatePriceHandler::process(GetAggregatePriceHandler::Input input, Context
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "GetAggregatePrice's ledger range must be available"); ASSERT(range.has_value(), "GetAggregatePrice's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
// sorted descending by lastUpdateTime, ascending by AssetPrice // sorted descending by lastUpdateTime, ascending by AssetPrice
using TimestampPricesBiMap = boost::bimaps::bimap< using TimestampPricesBiMap = boost::bimaps::bimap<

View File

@@ -55,14 +55,14 @@ LedgerHandler::process(LedgerHandler::Input input, Context const& ctx) const
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "LedgerHandler's ledger range must be available"); ASSERT(range.has_value(), "LedgerHandler's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
Output output; Output output;
output.header = toJson(lgrInfo, input.binary, ctx.apiVersion); output.header = toJson(lgrInfo, input.binary, ctx.apiVersion);

View File

@@ -64,14 +64,14 @@ LedgerDataHandler::process(Input input, Context const& ctx) const
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "LedgerData's ledger range must be available"); ASSERT(range.has_value(), "LedgerData's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
Output output; Output output;

View File

@@ -70,11 +70,11 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
} else if (input.did) { } else if (input.did) {
key = ripple::keylet::did(*util::parseBase58Wrapper<ripple::AccountID>(*(input.did))).key; key = ripple::keylet::did(*util::parseBase58Wrapper<ripple::AccountID>(*(input.did))).key;
} else if (input.directory) { } else if (input.directory) {
auto const keyOrStatus = composeKeyFromDirectory(*input.directory); auto const expectedkey = composeKeyFromDirectory(*input.directory);
if (auto const status = std::get_if<Status>(&keyOrStatus)) if (!expectedkey.has_value())
return Error{*status}; return Error{expectedkey.error()};
key = std::get<ripple::uint256>(keyOrStatus); key = expectedkey.value();
} else if (input.offer) { } else if (input.offer) {
auto const id = auto const id =
util::parseBase58Wrapper<ripple::AccountID>(boost::json::value_to<std::string>(input.offer->at(JS(account))) util::parseBase58Wrapper<ripple::AccountID>(boost::json::value_to<std::string>(input.offer->at(JS(account)))
@@ -202,14 +202,14 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
// check ledger exists // check ledger exists
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "LedgerEntry's ledger range must be available"); ASSERT(range.has_value(), "LedgerEntry's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto output = LedgerEntryHandler::Output{}; auto output = LedgerEntryHandler::Output{};
auto ledgerObject = sharedPtrBackend_->fetchLedgerObject(key, lgrInfo.seq, ctx.yield); auto ledgerObject = sharedPtrBackend_->fetchLedgerObject(key, lgrInfo.seq, ctx.yield);
@@ -243,16 +243,16 @@ LedgerEntryHandler::process(LedgerEntryHandler::Input input, Context const& ctx)
return output; return output;
} }
std::variant<ripple::uint256, Status> std::expected<ripple::uint256, Status>
LedgerEntryHandler::composeKeyFromDirectory(boost::json::object const& directory) noexcept LedgerEntryHandler::composeKeyFromDirectory(boost::json::object const& directory) noexcept
{ {
// can not specify both dir_root and owner. // can not specify both dir_root and owner.
if (directory.contains(JS(dir_root)) && directory.contains(JS(owner))) if (directory.contains(JS(dir_root)) && directory.contains(JS(owner)))
return Status{RippledError::rpcINVALID_PARAMS, "mayNotSpecifyBothDirRootAndOwner"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "mayNotSpecifyBothDirRootAndOwner"}};
// at least one should available // at least one should available
if (!(directory.contains(JS(dir_root)) || directory.contains(JS(owner)))) if (!(directory.contains(JS(dir_root)) || directory.contains(JS(owner))))
return Status{RippledError::rpcINVALID_PARAMS, "missingOwnerOrDirRoot"}; return std::unexpected{Status{RippledError::rpcINVALID_PARAMS, "missingOwnerOrDirRoot"}};
uint64_t const subIndex = uint64_t const subIndex =
directory.contains(JS(sub_index)) ? boost::json::value_to<uint64_t>(directory.at(JS(sub_index))) : 0; directory.contains(JS(sub_index)) ? boost::json::value_to<uint64_t>(directory.at(JS(sub_index))) : 0;

View File

@@ -430,7 +430,7 @@ public:
private: private:
// dir_root and owner can not be both empty or filled at the same time // dir_root and owner can not be both empty or filled at the same time
// This function will return an error if this is the case // This function will return an error if this is the case
static std::variant<ripple::uint256, Status> static std::expected<ripple::uint256, Status>
composeKeyFromDirectory(boost::json::object const& directory) noexcept; composeKeyFromDirectory(boost::json::object const& directory) noexcept;
/** /**

View File

@@ -52,13 +52,13 @@ MPTHoldersHandler::process(MPTHoldersHandler::Input input, Context const& ctx) c
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "MPTHolder's ledger range must be available"); ASSERT(range.has_value(), "MPTHolder's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<LedgerInfo>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const limit = input.limit.value_or(MPTHoldersHandler::kLIMIT_DEFAULT); auto const limit = input.limit.value_or(MPTHoldersHandler::kLIMIT_DEFAULT);
auto const mptID = ripple::uint192{input.mptID.c_str()}; auto const mptID = ripple::uint192{input.mptID.c_str()};

View File

@@ -80,14 +80,14 @@ NFTHistoryHandler::process(NFTHistoryHandler::Input input, Context const& ctx) c
if (input.ledgerIndexMax || input.ledgerIndexMin) if (input.ledgerIndexMax || input.ledgerIndexMin)
return Error{Status{RippledError::rpcINVALID_PARAMS, "containsLedgerSpecifierAndRange"}}; return Error{Status{RippledError::rpcINVALID_PARAMS, "containsLedgerSpecifierAndRange"}};
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
maxIndex = minIndex = std::get<ripple::LedgerHeader>(lgrInfoOrStatus).seq; maxIndex = minIndex = expectedLgrInfo.value().seq;
} }
std::optional<data::TransactionsCursor> cursor; std::optional<data::TransactionsCursor> cursor;

View File

@@ -50,14 +50,14 @@ NFTInfoHandler::process(NFTInfoHandler::Input input, Context const& ctx) const
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "NFTInfo's ledger range must be available"); ASSERT(range.has_value(), "NFTInfo's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const maybeNft = sharedPtrBackend_->fetchNFT(tokenID, lgrInfo.seq, ctx.yield); auto const maybeNft = sharedPtrBackend_->fetchNFT(tokenID, lgrInfo.seq, ctx.yield);
if (not maybeNft.has_value()) if (not maybeNft.has_value())

View File

@@ -93,14 +93,14 @@ NFTOffersHandlerBase::iterateOfferDirectory(
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "NFTOffersCommon's ledger range must be available"); ASSERT(range.has_value(), "NFTOffersCommon's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
// TODO: just check for existence without pulling // TODO: just check for existence without pulling
if (not sharedPtrBackend_->fetchLedgerObject(directory.key, lgrInfo.seq, yield)) if (not sharedPtrBackend_->fetchLedgerObject(directory.key, lgrInfo.seq, yield))
@@ -156,8 +156,8 @@ NFTOffersHandlerBase::iterateOfferDirectory(
} }
); );
if (auto status = std::get_if<Status>(&result)) if (!result.has_value())
return Error{*status}; return Error{result.error()};
if (offers.size() == reserve) { if (offers.size() == reserve) {
output.limit = input.limit; output.limit = input.limit;

View File

@@ -51,13 +51,13 @@ NFTsByIssuerHandler::process(NFTsByIssuerHandler::Input input, Context const& ct
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "NFTsByIssuer's ledger range must be available"); ASSERT(range.has_value(), "NFTsByIssuer's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto const status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const limit = input.limit.value_or(NFTsByIssuerHandler::kLIMIT_DEFAULT); auto const limit = input.limit.value_or(NFTsByIssuerHandler::kLIMIT_DEFAULT);

View File

@@ -61,14 +61,14 @@ NoRippleCheckHandler::process(NoRippleCheckHandler::Input input, Context const&
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "NoRippleCheck's ledger range must be available"); ASSERT(range.has_value(), "NoRippleCheck's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto const lgrInfo = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); auto const& lgrInfo = expectedLgrInfo.value();
auto const accountID = accountFromStringStrict(input.account); auto const accountID = accountFromStringStrict(input.account);
auto const keylet = ripple::keylet::account(*accountID).key; auto const keylet = ripple::keylet::account(*accountID).key;
auto const accountObj = sharedPtrBackend_->fetchLedgerObject(keylet, lgrInfo.seq, ctx.yield); auto const accountObj = sharedPtrBackend_->fetchLedgerObject(keylet, lgrInfo.seq, ctx.yield);

View File

@@ -92,8 +92,8 @@ SubscribeHandler::spec([[maybe_unused]] uint32_t apiVersion)
} }
auto const parsedBook = parseBook(book.as_object()); auto const parsedBook = parseBook(book.as_object());
if (auto const status = std::get_if<Status>(&parsedBook)) if (!parsedBook)
return Error(*status); return Error(parsedBook.error());
} }
return MaybeError{}; return MaybeError{};
@@ -298,7 +298,8 @@ tag_invoke(boost::json::value_to_tag<SubscribeHandler::Input>, boost::json::valu
internalBook.snapshot = snapshot->value().as_bool(); internalBook.snapshot = snapshot->value().as_bool();
auto const parsedBookMaybe = parseBook(book.as_object()); auto const parsedBookMaybe = parseBook(book.as_object());
internalBook.book = std::get<ripple::Book>(parsedBookMaybe); ASSERT(parsedBookMaybe.has_value(), "Book parsing failed");
internalBook.book = parsedBookMaybe.value();
input.books->push_back(internalBook); input.books->push_back(internalBook);
} }
} }

View File

@@ -46,17 +46,17 @@ TransactionEntryHandler::process(TransactionEntryHandler::Input input, Context c
auto const range = sharedPtrBackend_->fetchLedgerRange(); auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "TransactionEntry's ledger range must be available"); ASSERT(range.has_value(), "TransactionEntry's ledger range must be available");
auto const lgrInfoOrStatus = getLedgerHeaderFromHashOrSeq( auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
*sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence *sharedPtrBackend_, ctx.yield, input.ledgerHash, input.ledgerIndex, range->maxSequence
); );
if (auto status = std::get_if<Status>(&lgrInfoOrStatus)) if (!expectedLgrInfo.has_value())
return Error{*status}; return Error{expectedLgrInfo.error()};
auto output = TransactionEntryHandler::Output{}; auto output = TransactionEntryHandler::Output{};
output.apiVersion = ctx.apiVersion; output.apiVersion = ctx.apiVersion;
output.ledgerHeader = std::get<ripple::LedgerHeader>(lgrInfoOrStatus); output.ledgerHeader = expectedLgrInfo.value();
auto const dbRet = sharedPtrBackend_->fetchTransaction(ripple::uint256{input.txHash.c_str()}, ctx.yield); auto const dbRet = sharedPtrBackend_->fetchTransaction(ripple::uint256{input.txHash.c_str()}, ctx.yield);
// Note: transaction_entry is meant to only search a specified ledger for // Note: transaction_entry is meant to only search a specified ledger for
// the specified transaction. tx searches the entire range of history. For // the specified transaction. tx searches the entire range of history. For

View File

@@ -66,8 +66,8 @@ UnsubscribeHandler::spec([[maybe_unused]] uint32_t apiVersion)
return Error{Status{RippledError::rpcINVALID_PARAMS, "bothNotBool"}}; return Error{Status{RippledError::rpcINVALID_PARAMS, "bothNotBool"}};
auto const parsedBook = parseBook(book.as_object()); auto const parsedBook = parseBook(book.as_object());
if (auto const status = std::get_if<Status>(&parsedBook)) if (!parsedBook.has_value())
return Error(*status); return Error(parsedBook.error());
} }
return MaybeError{}; return MaybeError{};
@@ -193,7 +193,8 @@ tag_invoke(boost::json::value_to_tag<UnsubscribeHandler::Input>, boost::json::va
internalBook.both = both->value().as_bool(); internalBook.both = both->value().as_bool();
auto const parsedBookMaybe = parseBook(book.as_object()); auto const parsedBookMaybe = parseBook(book.as_object());
internalBook.book = std::get<ripple::Book>(parsedBookMaybe); ASSERT(parsedBookMaybe.has_value(), "Invalid book format");
internalBook.book = parsedBookMaybe.value();
input.books->push_back(internalBook); input.books->push_back(internalBook);
} }
} }

View File

@@ -216,9 +216,9 @@ private:
boost::json::object response; boost::json::object response;
if (auto const status = std::get_if<rpc::Status>(&result.response)) { if (!result.response.has_value()) {
// note: error statuses are counted/notified in buildResponse itself // note: error statuses are counted/notified in buildResponse itself
response = web::impl::ErrorHelper(connection, request).composeError(*status); response = web::impl::ErrorHelper(connection, request).composeError(result.response.error());
auto const responseStr = boost::json::serialize(response); auto const responseStr = boost::json::serialize(response);
LOG(perfLog_.debug()) << context->tag() << "Encountered error: " << responseStr; LOG(perfLog_.debug()) << context->tag() << "Encountered error: " << responseStr;
@@ -227,7 +227,7 @@ private:
// This can still technically be an error. Clio counts forwarded requests as successful. // This can still technically be an error. Clio counts forwarded requests as successful.
rpcEngine_->notifyComplete(context->method, us); rpcEngine_->notifyComplete(context->method, us);
auto& json = std::get<boost::json::object>(result.response); auto& json = result.response.value();
auto const isForwarded = auto const isForwarded =
json.contains("forwarded") && json.at("forwarded").is_bool() && json.at("forwarded").as_bool(); json.contains("forwarded") && json.at("forwarded").is_bool() && json.at("forwarded").as_bool();

View File

@@ -264,9 +264,9 @@ private:
boost::json::object response; boost::json::object response;
if (auto const status = std::get_if<rpc::Status>(&result.response)) { if (!result.response.has_value()) {
// note: error statuses are counted/notified in buildResponse itself // note: error statuses are counted/notified in buildResponse itself
response = impl::ErrorHelper(rawRequest, request).composeError(*status); response = impl::ErrorHelper(rawRequest, request).composeError(result.response.error());
auto const responseStr = boost::json::serialize(response); auto const responseStr = boost::json::serialize(response);
LOG(perfLog_.debug()) << context->tag() << "Encountered error: " << responseStr; LOG(perfLog_.debug()) << context->tag() << "Encountered error: " << responseStr;
@@ -275,7 +275,7 @@ private:
// This can still technically be an error. Clio counts forwarded requests as successful. // This can still technically be an error. Clio counts forwarded requests as successful.
rpcEngine_->notifyComplete(context->method, us); rpcEngine_->notifyComplete(context->method, us);
auto& json = std::get<boost::json::object>(result.response); auto& json = result.response.value();
auto const isForwarded = auto const isForwarded =
json.contains("forwarded") && json.at("forwarded").is_bool() && json.at("forwarded").as_bool(); json.contains("forwarded") && json.at("forwarded").is_bool() && json.at("forwarded").as_bool();

View File

@@ -318,8 +318,7 @@ TEST_F(RPCForwardingProxyTest, ForwardCallsBalancerWithCorrectParams)
auto const res = proxy_.forward(ctx); auto const res = proxy_.forward(ctx);
auto const data = std::get_if<json::object>(&res.response); EXPECT_TRUE(res.response.has_value());
EXPECT_TRUE(data != nullptr);
}); });
} }
@@ -348,8 +347,7 @@ TEST_F(RPCForwardingProxyTest, ForwardingFailYieldsErrorStatus)
auto const res = proxy_.forward(ctx); auto const res = proxy_.forward(ctx);
auto const status = std::get_if<Status>(&res.response); EXPECT_FALSE(res.response.has_value());
EXPECT_TRUE(status != nullptr); EXPECT_EQ(res.response.error(), rpc::ClioError::EtlInvalidResponse);
EXPECT_EQ(*status, rpc::ClioError::EtlInvalidResponse);
}); });
} }

View File

@@ -258,13 +258,11 @@ TEST_P(RPCEngineFlowParameterTest, Test)
); );
auto const res = engine->buildResponse(ctx); auto const res = engine->buildResponse(ctx);
auto const status = std::get_if<rpc::Status>(&res.response); ASSERT_EQ(res.response.has_value(), testBundle.response.has_value());
auto const response = std::get_if<boost::json::object>(&res.response);
ASSERT_EQ(status == nullptr, testBundle.response.has_value());
if (testBundle.response.has_value()) { if (testBundle.response.has_value()) {
EXPECT_EQ(*response, testBundle.response.value()); EXPECT_EQ(res.response.value(), testBundle.response.value());
} else { } else {
EXPECT_EQ(*status, testBundle.status.value()); EXPECT_EQ(res.response.error(), testBundle.status.value());
} }
}); });
} }
@@ -295,9 +293,8 @@ TEST_F(RPCEngineTest, ThrowDatabaseError)
); );
auto const res = engine->buildResponse(ctx); auto const res = engine->buildResponse(ctx);
auto const status = std::get_if<rpc::Status>(&res.response); ASSERT_FALSE(res.response.has_value());
ASSERT_TRUE(status != nullptr); EXPECT_EQ(res.response.error(), Status{RippledError::rpcTOO_BUSY});
EXPECT_EQ(*status, Status{RippledError::rpcTOO_BUSY});
}); });
} }
@@ -327,9 +324,8 @@ TEST_F(RPCEngineTest, ThrowException)
); );
auto const res = engine->buildResponse(ctx); auto const res = engine->buildResponse(ctx);
auto const status = std::get_if<rpc::Status>(&res.response); ASSERT_FALSE(res.response.has_value());
ASSERT_TRUE(status != nullptr); EXPECT_EQ(res.response.error(), Status{RippledError::rpcINTERNAL});
EXPECT_EQ(*status, Status{RippledError::rpcINTERNAL});
}); });
} }
@@ -454,8 +450,8 @@ TEST_P(RPCEngineCacheParameterTest, Test)
); );
auto const res = engine->buildResponse(ctx); auto const res = engine->buildResponse(ctx);
auto const response = std::get_if<boost::json::object>(&res.response); ASSERT_TRUE(res.response.has_value());
EXPECT_EQ(*response, boost::json::parse(R"JSON({ "computed": "world_50"})JSON").as_object()); EXPECT_EQ(res.response.value(), boost::json::parse(R"JSON({ "computed": "world_50"})JSON").as_object());
}); });
} }
} }
@@ -499,9 +495,8 @@ TEST_F(RPCEngineTest, NotCacheIfErrorHappen)
); );
auto const res = engine->buildResponse(ctx); auto const res = engine->buildResponse(ctx);
auto const error = std::get_if<rpc::Status>(&res.response); ASSERT_FALSE(res.response.has_value());
ASSERT_NE(error, nullptr); EXPECT_EQ(res.response.error(), rpc::Status{"Very custom error"});
EXPECT_EQ(*error, rpc::Status{"Very custom error"});
}); });
} }
} }

View File

@@ -103,10 +103,9 @@ TEST_F(RPCHelpersTest, TraverseOwnedNodesMarkerInvalidIndexNotHex)
auto ret = traverseOwnedNodes(*backend_, account, 9, 10, "nothex,10", yield, [](auto) { auto ret = traverseOwnedNodes(*backend_, account, 9, 10, "nothex,10", yield, [](auto) {
}); });
auto status = std::get_if<Status>(&ret); EXPECT_FALSE(ret.has_value());
EXPECT_TRUE(status != nullptr); EXPECT_EQ(ret.error(), ripple::rpcINVALID_PARAMS);
EXPECT_EQ(*status, ripple::rpcINVALID_PARAMS); EXPECT_EQ(ret.error().message, "Malformed cursor.");
EXPECT_EQ(status->message, "Malformed cursor.");
}); });
ctx_.run(); ctx_.run();
} }
@@ -118,10 +117,9 @@ TEST_F(RPCHelpersTest, TraverseOwnedNodesMarkerInvalidPageNotInt)
auto ret = traverseOwnedNodes(*backend_, account, 9, 10, "nothex,abc", yield, [](auto) { auto ret = traverseOwnedNodes(*backend_, account, 9, 10, "nothex,abc", yield, [](auto) {
}); });
auto status = std::get_if<Status>(&ret); EXPECT_FALSE(ret.has_value());
EXPECT_TRUE(status != nullptr); EXPECT_EQ(ret.error(), ripple::rpcINVALID_PARAMS);
EXPECT_EQ(*status, ripple::rpcINVALID_PARAMS); EXPECT_EQ(ret.error().message, "Malformed cursor.");
EXPECT_EQ(status->message, "Malformed cursor.");
}); });
ctx_.run(); ctx_.run();
} }
@@ -148,13 +146,10 @@ TEST_F(RPCHelpersTest, TraverseOwnedNodesNoInputMarker)
EXPECT_CALL(*backend_, doFetchLedgerObjects).Times(1); EXPECT_CALL(*backend_, doFetchLedgerObjects).Times(1);
boost::asio::spawn(ctx_, [this, &account](boost::asio::yield_context yield) { boost::asio::spawn(ctx_, [this, &account](boost::asio::yield_context yield) {
auto ret = traverseOwnedNodes(*backend_, account, 9, 10, {}, yield, [](auto) { auto ret = traverseOwnedNodes(*backend_, account, 9, 10, {}, yield, [](auto) {});
EXPECT_TRUE(ret.has_value());
});
auto cursor = std::get_if<AccountCursor>(&ret);
EXPECT_TRUE(cursor != nullptr);
EXPECT_EQ( EXPECT_EQ(
cursor->toString(), ret.value().toString(),
"0000000000000000000000000000000000000000000000000000000000000000," "0000000000000000000000000000000000000000000000000000000000000000,"
"0" "0"
); );
@@ -192,10 +187,9 @@ TEST_F(RPCHelpersTest, TraverseOwnedNodesNoInputMarkerReturnSamePageMarker)
boost::asio::spawn(ctx_, [this, &account](boost::asio::yield_context yield) { boost::asio::spawn(ctx_, [this, &account](boost::asio::yield_context yield) {
auto count = 0; auto count = 0;
auto ret = traverseOwnedNodes(*backend_, account, 9, 10, {}, yield, [&](auto) { count++; }); auto ret = traverseOwnedNodes(*backend_, account, 9, 10, {}, yield, [&](auto) { count++; });
auto cursor = std::get_if<AccountCursor>(&ret); EXPECT_TRUE(ret.has_value());
EXPECT_TRUE(cursor != nullptr);
EXPECT_EQ(count, 10); EXPECT_EQ(count, 10);
EXPECT_EQ(cursor->toString(), fmt::format("{},0", kINDEX1)); EXPECT_EQ(ret.value().toString(), fmt::format("{},0", kINDEX1));
}); });
ctx_.run(); ctx_.run();
} }
@@ -244,10 +238,9 @@ TEST_F(RPCHelpersTest, TraverseOwnedNodesNoInputMarkerReturnOtherPageMarker)
boost::asio::spawn(ctx_, [&, this](boost::asio::yield_context yield) { boost::asio::spawn(ctx_, [&, this](boost::asio::yield_context yield) {
auto count = 0; auto count = 0;
auto ret = traverseOwnedNodes(*backend_, account, 9, kLIMIT, {}, yield, [&](auto) { count++; }); auto ret = traverseOwnedNodes(*backend_, account, 9, kLIMIT, {}, yield, [&](auto) { count++; });
auto cursor = std::get_if<AccountCursor>(&ret); EXPECT_TRUE(ret.has_value());
EXPECT_TRUE(cursor != nullptr);
EXPECT_EQ(count, kLIMIT); EXPECT_EQ(count, kLIMIT);
EXPECT_EQ(cursor->toString(), fmt::format("{},{}", kINDEX1, kNEXT_PAGE)); EXPECT_EQ(ret.value().toString(), fmt::format("{},{}", kINDEX1, kNEXT_PAGE));
}); });
ctx_.run(); ctx_.run();
} }
@@ -291,10 +284,9 @@ TEST_F(RPCHelpersTest, TraverseOwnedNodesWithMarkerReturnSamePageMarker)
auto ret = traverseOwnedNodes( auto ret = traverseOwnedNodes(
*backend_, account, 9, kLIMIT, fmt::format("{},{}", kINDEX1, kPAGE_NUM), yield, [&](auto) { count++; } *backend_, account, 9, kLIMIT, fmt::format("{},{}", kINDEX1, kPAGE_NUM), yield, [&](auto) { count++; }
); );
auto cursor = std::get_if<AccountCursor>(&ret); EXPECT_TRUE(ret.has_value());
EXPECT_TRUE(cursor != nullptr);
EXPECT_EQ(count, kLIMIT); EXPECT_EQ(count, kLIMIT);
EXPECT_EQ(cursor->toString(), fmt::format("{},{}", kINDEX1, kPAGE_NUM)); EXPECT_EQ(ret.value().toString(), fmt::format("{},{}", kINDEX1, kPAGE_NUM));
}); });
ctx_.run(); ctx_.run();
} }
@@ -328,10 +320,9 @@ TEST_F(RPCHelpersTest, TraverseOwnedNodesWithUnexistingIndexMarker)
auto ret = traverseOwnedNodes( auto ret = traverseOwnedNodes(
*backend_, account, 9, kLIMIT, fmt::format("{},{}", kINDEX2, kPAGE_NUM), yield, [&](auto) { count++; } *backend_, account, 9, kLIMIT, fmt::format("{},{}", kINDEX2, kPAGE_NUM), yield, [&](auto) { count++; }
); );
auto status = std::get_if<Status>(&ret); EXPECT_FALSE(ret.has_value());
EXPECT_TRUE(status != nullptr); EXPECT_EQ(ret.error(), ripple::rpcINVALID_PARAMS);
EXPECT_EQ(*status, ripple::rpcINVALID_PARAMS); EXPECT_EQ(ret.error().message, "Invalid marker.");
EXPECT_EQ(status->message, "Invalid marker.");
}); });
ctx_.run(); ctx_.run();
} }

View File

@@ -611,12 +611,12 @@ generateNormalPathBookOffersTestBundles()
kPAYS20_USD_GETS10_XRP_BOOK_DIR kPAYS20_USD_GETS10_XRP_BOOK_DIR
); );
auto const getsXRPPaysUSDBook = getBookBase(std::get<ripple::Book>( auto const getsXRPPaysUSDBook = getBookBase(
rpc::parseBook(ripple::to_currency("USD"), account, ripple::xrpCurrency(), ripple::xrpAccount()) rpc::parseBook(ripple::to_currency("USD"), account, ripple::xrpCurrency(), ripple::xrpAccount()).value()
)); );
auto const getsUSDPaysXRPBook = getBookBase(std::get<ripple::Book>( auto const getsUSDPaysXRPBook = getBookBase(
rpc::parseBook(ripple::xrpCurrency(), ripple::xrpAccount(), ripple::to_currency("USD"), account) rpc::parseBook(ripple::xrpCurrency(), ripple::xrpAccount(), ripple::to_currency("USD"), account).value()
)); );
auto const getsXRPPaysUSDInputJson = fmt::format( auto const getsXRPPaysUSDInputJson = fmt::format(
R"JSON({{ R"JSON({{
@@ -1450,9 +1450,9 @@ TEST_F(RPCBookOffersHandlerTest, Limit)
// return valid book dir // return valid book dir
EXPECT_CALL(*backend_, doFetchSuccessorKey).Times(1); EXPECT_CALL(*backend_, doFetchSuccessorKey).Times(1);
auto const getsXRPPaysUSDBook = getBookBase(std::get<ripple::Book>( auto const getsXRPPaysUSDBook = getBookBase(
rpc::parseBook(ripple::to_currency("USD"), issuer, ripple::xrpCurrency(), ripple::xrpAccount()) rpc::parseBook(ripple::to_currency("USD"), issuer, ripple::xrpCurrency(), ripple::xrpAccount()).value()
)); );
ON_CALL(*backend_, doFetchSuccessorKey(getsXRPPaysUSDBook, seq, _)) ON_CALL(*backend_, doFetchSuccessorKey(getsXRPPaysUSDBook, seq, _))
.WillByDefault(Return(ripple::uint256{kPAYS20_USD_GETS10_XRP_BOOK_DIR})); .WillByDefault(Return(ripple::uint256{kPAYS20_USD_GETS10_XRP_BOOK_DIR}));
@@ -1523,9 +1523,9 @@ TEST_F(RPCBookOffersHandlerTest, LimitMoreThanMax)
// return valid book dir // return valid book dir
EXPECT_CALL(*backend_, doFetchSuccessorKey).Times(1); EXPECT_CALL(*backend_, doFetchSuccessorKey).Times(1);
auto const getsXRPPaysUSDBook = getBookBase(std::get<ripple::Book>( auto const getsXRPPaysUSDBook = getBookBase(
rpc::parseBook(ripple::to_currency("USD"), issuer, ripple::xrpCurrency(), ripple::xrpAccount()) rpc::parseBook(ripple::to_currency("USD"), issuer, ripple::xrpCurrency(), ripple::xrpAccount()).value()
)); );
ON_CALL(*backend_, doFetchSuccessorKey(getsXRPPaysUSDBook, seq, _)) ON_CALL(*backend_, doFetchSuccessorKey(getsXRPPaysUSDBook, seq, _))
.WillByDefault(Return(ripple::uint256{kPAYS20_USD_GETS10_XRP_BOOK_DIR})); .WillByDefault(Return(ripple::uint256{kPAYS20_USD_GETS10_XRP_BOOK_DIR}));

View File

@@ -822,13 +822,13 @@ TEST_F(RPCSubscribeHandlerTest, BooksBothSnapshotSet)
auto const issuer = getAccountIdWithString(kACCOUNT); auto const issuer = getAccountIdWithString(kACCOUNT);
auto const getsXRPPaysUSDBook = getBookBase(std::get<ripple::Book>( auto const getsXRPPaysUSDBook = getBookBase(
rpc::parseBook(ripple::to_currency("USD"), issuer, ripple::xrpCurrency(), ripple::xrpAccount()) rpc::parseBook(ripple::to_currency("USD"), issuer, ripple::xrpCurrency(), ripple::xrpAccount()).value()
)); );
auto const reversedBook = getBookBase(std::get<ripple::Book>( auto const reversedBook = getBookBase(
rpc::parseBook(ripple::xrpCurrency(), ripple::xrpAccount(), ripple::to_currency("USD"), issuer) rpc::parseBook(ripple::xrpCurrency(), ripple::xrpAccount(), ripple::to_currency("USD"), issuer).value()
)); );
ON_CALL(*backend_, doFetchSuccessorKey(getsXRPPaysUSDBook, kMAX_SEQ, _)) ON_CALL(*backend_, doFetchSuccessorKey(getsXRPPaysUSDBook, kMAX_SEQ, _))
.WillByDefault(Return(ripple::uint256{kPAYS20_USD_GETS10_XRP_BOOK_DIR})); .WillByDefault(Return(ripple::uint256{kPAYS20_USD_GETS10_XRP_BOOK_DIR}));
@@ -992,13 +992,13 @@ TEST_F(RPCSubscribeHandlerTest, BooksBothUnsetSnapshotSet)
auto const issuer = getAccountIdWithString(kACCOUNT); auto const issuer = getAccountIdWithString(kACCOUNT);
auto const getsXRPPaysUSDBook = getBookBase(std::get<ripple::Book>( auto const getsXRPPaysUSDBook = getBookBase(
rpc::parseBook(ripple::to_currency("USD"), issuer, ripple::xrpCurrency(), ripple::xrpAccount()) rpc::parseBook(ripple::to_currency("USD"), issuer, ripple::xrpCurrency(), ripple::xrpAccount()).value()
)); );
auto const reversedBook = getBookBase(std::get<ripple::Book>( auto const reversedBook = getBookBase(
rpc::parseBook(ripple::xrpCurrency(), ripple::xrpAccount(), ripple::to_currency("USD"), issuer) rpc::parseBook(ripple::xrpCurrency(), ripple::xrpAccount(), ripple::to_currency("USD"), issuer).value()
)); );
ON_CALL(*backend_, doFetchSuccessorKey(getsXRPPaysUSDBook, kMAX_SEQ, _)) ON_CALL(*backend_, doFetchSuccessorKey(getsXRPPaysUSDBook, kMAX_SEQ, _))
.WillByDefault(Return(ripple::uint256{kPAYS20_USD_GETS10_XRP_BOOK_DIR})); .WillByDefault(Return(ripple::uint256{kPAYS20_USD_GETS10_XRP_BOOK_DIR}));

View File

@@ -653,7 +653,7 @@ TEST_F(RPCUnsubscribeTest, Books)
)); ));
auto const parsedBookMaybe = rpc::parseBook(input.as_object().at("books").as_array()[0].as_object()); auto const parsedBookMaybe = rpc::parseBook(input.as_object().at("books").as_array()[0].as_object());
auto const book = std::get<ripple::Book>(parsedBookMaybe); auto const book = parsedBookMaybe.value();
EXPECT_CALL(*mockSubscriptionManagerPtr_, unsubBook(book, _)).Times(1); EXPECT_CALL(*mockSubscriptionManagerPtr_, unsubBook(book, _)).Times(1);
EXPECT_CALL(*mockSubscriptionManagerPtr_, unsubBook(ripple::reversed(book), _)).Times(1); EXPECT_CALL(*mockSubscriptionManagerPtr_, unsubBook(ripple::reversed(book), _)).Times(1);
@@ -686,7 +686,7 @@ TEST_F(RPCUnsubscribeTest, SingleBooks)
)); ));
auto const parsedBookMaybe = rpc::parseBook(input.as_object().at("books").as_array()[0].as_object()); auto const parsedBookMaybe = rpc::parseBook(input.as_object().at("books").as_array()[0].as_object());
auto const book = std::get<ripple::Book>(parsedBookMaybe); auto const book = parsedBookMaybe.value();
EXPECT_CALL(*mockSubscriptionManagerPtr_, unsubBook(book, _)).Times(1); EXPECT_CALL(*mockSubscriptionManagerPtr_, unsubBook(book, _)).Times(1);