mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-24 07:30:30 +00:00
152 lines
4.3 KiB
C++
152 lines
4.3 KiB
C++
#include <xrpl/tx/paths/Flow.h>
|
|
|
|
#include <xrpl/basics/base_uint.h>
|
|
#include <xrpl/beast/utility/Journal.h>
|
|
#include <xrpl/protocol/AccountID.h>
|
|
#include <xrpl/protocol/Asset.h>
|
|
#include <xrpl/protocol/Issue.h>
|
|
#include <xrpl/protocol/MPTIssue.h>
|
|
#include <xrpl/protocol/Quality.h>
|
|
#include <xrpl/protocol/STAmount.h>
|
|
#include <xrpl/protocol/STPathSet.h>
|
|
#include <xrpl/tx/paths/RippleCalc.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>
|
|
|
|
#include <optional>
|
|
#include <variant>
|
|
|
|
namespace xrpl {
|
|
|
|
template <class FlowResult>
|
|
static auto
|
|
finishFlow(PaymentSandbox& sb, Asset const& srcAsset, Asset const& dstAsset, FlowResult&& f)
|
|
{
|
|
path::RippleCalc::Output result;
|
|
if (isTesSuccess(f.ter))
|
|
{
|
|
f.sandbox->apply(sb); // NOLINT(bugprone-unchecked-optional-access) sandbox set on success
|
|
}
|
|
else
|
|
{
|
|
result.removableOffers = std::move(f.removableOffers);
|
|
}
|
|
|
|
result.setResult(f.ter);
|
|
result.actualAmountIn = toSTAmount(f.in, srcAsset);
|
|
result.actualAmountOut = toSTAmount(f.out, dstAsset);
|
|
|
|
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)
|
|
{
|
|
Asset const srcAsset = [&]() -> Asset {
|
|
if (sendMax)
|
|
return sendMax->asset();
|
|
return deliver.asset().visit(
|
|
[&](Issue const& issue) -> Asset {
|
|
if (isXRP(issue))
|
|
return xrpIssue();
|
|
return Issue(issue.currency, src);
|
|
},
|
|
[&](MPTIssue const&) { return deliver.asset(); });
|
|
}();
|
|
|
|
Asset const dstAsset = deliver.asset();
|
|
|
|
std::optional<Asset> sendMaxAsset;
|
|
if (sendMax)
|
|
sendMaxAsset = sendMax->asset();
|
|
|
|
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,
|
|
dstAsset,
|
|
limitQuality,
|
|
sendMaxAsset,
|
|
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 << "\nsrcAsset: " << srcAsset
|
|
<< "\ndstAsset: " << dstAsset;
|
|
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';
|
|
}
|
|
}
|
|
}
|
|
|
|
// The src account may send either xrp,iou,or mpt. The dst account may
|
|
// receive either xrp,iou, or mpt. Since XRP, IOU, and MPT amounts are
|
|
// represented by different types, use templates to tell `flow` about the
|
|
// amount types.
|
|
return std::visit(
|
|
[&, &strands = strands]<typename TIn, typename TOut>(TIn const&, TOut const&) {
|
|
using TIn_ = typename TIn::amount_type;
|
|
using TOut_ = typename TOut::amount_type;
|
|
return finishFlow(
|
|
sb,
|
|
srcAsset,
|
|
dstAsset,
|
|
flow<TIn_, TOut_>(
|
|
sb,
|
|
strands,
|
|
get<TOut_>(deliver),
|
|
partialPayment,
|
|
offerCrossing,
|
|
limitQuality,
|
|
sendMax,
|
|
j,
|
|
ammContext,
|
|
flowDebugInfo));
|
|
},
|
|
srcAsset.getAmountType(),
|
|
dstAsset.getAmountType());
|
|
}
|
|
|
|
} // namespace xrpl
|