Files
rippled/src/libxrpl/tx/paths/Flow.cpp
Alex Kremer 57e4cbbcd9 refactor: Add simple clang-tidy readability checks (#6556)
This change enables the following clang-tidy checks:
-  readability-avoid-nested-conditional-operator,
-  readability-avoid-return-with-void-value,
-  readability-braces-around-statements,
-  readability-const-return-type,
-  readability-container-contains,
-  readability-container-size-empty,
-  readability-else-after-return,
-  readability-make-member-function-const,
-  readability-redundant-casting,
-  readability-redundant-inline-specifier,
-  readability-redundant-member-init,
-  readability-redundant-string-init,
-  readability-reference-to-constructed-temporary,
-  readability-static-definition
2026-03-18 16:41:49 +00:00

193 lines
4.9 KiB
C++

#include <xrpl/basics/Log.h>
#include <xrpl/ledger/Credit.h>
#include <xrpl/protocol/IOUAmount.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/paths/Flow.h>
#include <xrpl/tx/paths/detail/AmountSpec.h>
#include <xrpl/tx/paths/detail/Steps.h>
#include <xrpl/tx/paths/detail/StrandFlow.h>
#include <xrpl/tx/transactors/dex/AMMContext.h>
namespace xrpl {
template <class FlowResult>
static auto
finishFlow(PaymentSandbox& sb, Issue const& srcIssue, Issue const& dstIssue, FlowResult&& f)
{
path::RippleCalc::Output result;
if (isTesSuccess(f.ter))
{
f.sandbox->apply(sb);
}
else
{
result.removableOffers = std::move(f.removableOffers);
}
result.setResult(f.ter);
result.actualAmountIn = toSTAmount(f.in, srcIssue);
result.actualAmountOut = toSTAmount(f.out, dstIssue);
return result;
};
path::RippleCalc::Output
flow(
PaymentSandbox& sb,
STAmount const& deliver,
AccountID const& src,
AccountID const& dst,
STPathSet const& paths,
bool defaultPaths,
bool partialPayment,
bool ownerPaysTransferFee,
OfferCrossing offerCrossing,
std::optional<Quality> const& limitQuality,
std::optional<STAmount> const& sendMax,
std::optional<uint256> const& domainID,
beast::Journal j,
path::detail::FlowDebugInfo* flowDebugInfo)
{
Issue const srcIssue = [&] {
if (sendMax)
return sendMax->issue();
if (!isXRP(deliver.issue().currency))
return Issue(deliver.issue().currency, src);
return xrpIssue();
}();
Issue const dstIssue = deliver.issue();
std::optional<Issue> sendMaxIssue;
if (sendMax)
sendMaxIssue = sendMax->issue();
AMMContext ammContext(src, false);
// convert the paths to a collection of strands. Each strand is the
// collection of account->account steps and book steps that may be used in
// this payment.
auto [toStrandsTer, strands] = toStrands(
sb,
src,
dst,
dstIssue,
limitQuality,
sendMaxIssue,
paths,
defaultPaths,
ownerPaysTransferFee,
offerCrossing,
ammContext,
domainID,
j);
if (!isTesSuccess(toStrandsTer))
{
path::RippleCalc::Output result;
result.setResult(toStrandsTer);
return result;
}
ammContext.setMultiPath(strands.size() > 1);
if (j.trace())
{
j.trace() << "\nsrc: " << src << "\ndst: " << dst << "\nsrcIssue: " << srcIssue
<< "\ndstIssue: " << dstIssue;
j.trace() << "\nNumStrands: " << strands.size();
for (auto const& curStrand : strands)
{
j.trace() << "NumSteps: " << curStrand.size();
for (auto const& step : curStrand)
{
j.trace() << '\n' << *step << '\n';
}
}
}
bool const srcIsXRP = isXRP(srcIssue.currency);
bool const dstIsXRP = isXRP(dstIssue.currency);
auto const asDeliver = toAmountSpec(deliver);
// The src account may send either xrp or iou. The dst account may receive
// either xrp or iou. Since XRP and IOU amounts are represented by different
// types, use templates to tell `flow` about the amount types.
if (srcIsXRP && dstIsXRP)
{
return finishFlow(
sb,
srcIssue,
dstIssue,
flow<XRPAmount, XRPAmount>(
sb,
strands,
asDeliver.xrp,
partialPayment,
offerCrossing,
limitQuality,
sendMax,
j,
ammContext,
flowDebugInfo));
}
if (srcIsXRP && !dstIsXRP)
{
return finishFlow(
sb,
srcIssue,
dstIssue,
flow<XRPAmount, IOUAmount>(
sb,
strands,
asDeliver.iou,
partialPayment,
offerCrossing,
limitQuality,
sendMax,
j,
ammContext,
flowDebugInfo));
}
if (!srcIsXRP && dstIsXRP)
{
return finishFlow(
sb,
srcIssue,
dstIssue,
flow<IOUAmount, XRPAmount>(
sb,
strands,
asDeliver.xrp,
partialPayment,
offerCrossing,
limitQuality,
sendMax,
j,
ammContext,
flowDebugInfo));
}
XRPL_ASSERT(!srcIsXRP && !dstIsXRP, "xrpl::flow : neither is XRP");
return finishFlow(
sb,
srcIssue,
dstIssue,
flow<IOUAmount, IOUAmount>(
sb,
strands,
asDeliver.iou,
partialPayment,
offerCrossing,
limitQuality,
sendMax,
j,
ammContext,
flowDebugInfo));
}
} // namespace xrpl