1#include <xrpl/basics/Log.h>
2#include <xrpl/basics/base_uint.h>
3#include <xrpl/basics/contract.h>
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/beast/utility/Zero.h>
6#include <xrpl/beast/utility/instrumentation.h>
7#include <xrpl/ledger/ApplyView.h>
8#include <xrpl/ledger/PaymentSandbox.h>
9#include <xrpl/ledger/Sandbox.h>
10#include <xrpl/ledger/helpers/AMMHelpers.h>
11#include <xrpl/ledger/helpers/AccountRootHelpers.h>
12#include <xrpl/ledger/helpers/MPTokenHelpers.h>
13#include <xrpl/ledger/helpers/TokenHelpers.h>
14#include <xrpl/protocol/AccountID.h>
15#include <xrpl/protocol/Asset.h>
16#include <xrpl/protocol/Book.h>
17#include <xrpl/protocol/Concepts.h>
18#include <xrpl/protocol/Feature.h>
19#include <xrpl/protocol/IOUAmount.h>
20#include <xrpl/protocol/Indexes.h>
21#include <xrpl/protocol/Issue.h>
22#include <xrpl/protocol/LedgerFormats.h>
23#include <xrpl/protocol/MPTAmount.h>
24#include <xrpl/protocol/MPTIssue.h>
25#include <xrpl/protocol/Quality.h>
26#include <xrpl/protocol/Rate.h>
27#include <xrpl/protocol/Rules.h>
28#include <xrpl/protocol/SField.h>
29#include <xrpl/protocol/STAmount.h>
30#include <xrpl/protocol/TER.h>
31#include <xrpl/protocol/XRPAmount.h>
32#include <xrpl/tx/paths/AMMLiquidity.h>
33#include <xrpl/tx/paths/AMMOffer.h>
34#include <xrpl/tx/paths/BookTip.h>
35#include <xrpl/tx/paths/OfferStream.h>
36#include <xrpl/tx/paths/detail/EitherAmount.h>
37#include <xrpl/tx/paths/detail/FlatSets.h>
38#include <xrpl/tx/paths/detail/Steps.h>
40#include <boost/container/flat_set.hpp>
56template <
class TIn,
class TOut,
class TDerived>
57class BookStep :
public StepImp<TIn, TOut, BookStep<TIn, TOut, TDerived>>
101 :
book_(in, out, ctx.domainID)
110 ammSle && ammSle->getFieldAmount(sfLPTokenBalance) !=
beast::kZero)
112 ammLiquidity_.emplace(
114 (*ammSle)[sfAccount],
115 getTradingFee(ctx.view, *ammSle, ctx.ammContext.account()),
124 [[nodiscard]]
Book const&
171 boost::container::flat_set<uint256>& ofrsToRm,
178 boost::container::flat_set<uint256>& ofrsToRm,
200 <<
"\ninIss: " <<
book_.in.getIssuer() <<
"\noutIss: " <<
book_.out.getIssuer()
218 return !(lhs == rhs);
229 template <
class Callback>
235 Callback& callback)
const;
238 template <
template <
typename,
typename>
typename Offer>
245 TOut
const& ownerGives)
const;
284template <
class TIn,
class TOut>
299 template <
template <
typename,
typename>
typename Offer>
360 ? this->
rate(v, this->
book_.out, this->strandDst_)
375template <
class TIn,
class TOut>
388 XRPL_ASSERT(limitQuality,
"xrpl::BookOfferCrossingStep::getQuality : nonzero quality");
391 return *limitQuality;
402 template <
template <
typename,
typename>
typename Offer>
410 bool const offerAttempted)
const
442 strandDst == offer.owner())
445 if (
auto const key = offer.
key())
446 offers.permRmOffer(*key);
491 auto const srcAcct = (prevStep !=
nullptr) ? prevStep->
directStepSrcAcct() : std::nullopt;
493 return owner == srcAcct
501 Step const* prevStep,
520 Rules const& rules)
const
532 if (!rules.
enabled(fixAMMv1_1))
536 if (offerType == OfferType::Clob ||
564template <
class TIn,
class TOut,
class TDerived>
569 return book_ == bs->book_;
573template <
class TIn,
class TOut,
class TDerived>
581 return {std::nullopt, dir};
586 Quality const q =
static_cast<TDerived const*
>(
this)->adjustQualityWithFees(
587 v, std::get<Quality>(*res), prevStepDir, waiveFee, std::get<OfferType>(*res), v.
rules());
591template <
class TIn,
class TOut,
class TDerived>
599 return {std::nullopt, dir};
605 auto const q =
static_cast<TDerived const*
>(
this)->adjustQualityWithFees(
615 Quality const q =
static_cast<TDerived const*
>(
this)->adjustQualityWithFees(
626template <
class TIn,
class TOut,
class TDerived>
634template <
class TIn,
class TOut,
class Offer>
645 if (limit < stpAmt.
in)
648 auto const inLmt =
mulRatio(stpAmt.
in, QUALITY_ONE, transferRateIn,
false);
656 ofrAmt = offer.limitIn(ofrAmt, inLmt,
false);
671template <
class TIn,
class TOut,
class Offer>
682 if (limit < stpAmt.
out)
690 ofrAmt = offer.limitOut(
694 stpAmt.
in =
mulRatio(ofrAmt.
in, transferRateIn, QUALITY_ONE,
true);
698template <
class TIn,
class TOut,
class TDerived>
699template <
class Callback>
705 Callback& callback)
const
713 redeems(prevStepDir) ?
rate(sb,
book_.in, this->strandDst_).value : QUALITY_ONE;
722 bool offerAttempted =
false;
724 auto execOffer = [&](
auto& offer) {
729 ofrQ = offer.quality();
731 else if (*ofrQ != offer.quality())
736 if (
static_cast<TDerived const*
>(
this)->limitSelfCrossQuality(
740 Asset const& assetIn = offer.assetIn();
742 auto const& owner = offer.owner();
745 auto const key = offer.
key();
746 if (!logMessage.
empty())
748 JLOG(
j_.trace()) << logMessage << (key ?
" " +
to_string(*key) :
"");
751 offers.permRmOffer(*key);
761 auto& applyView = sb.
rules().
enabled(featureMPTokensV2) ? sb : afView;
778 if (!
static_cast<TDerived const*
>(
this)->checkQualityThreshold(offer.quality()))
781 auto const [ofrInRate, ofrOutRate] = offer.adjustRates(
785 auto ofrAmt = offer.amount();
786 TAmounts stpAmt{ofrAmt.in, ofrAmt.out};
787 auto ownerGives = ofrAmt.
out;
794 stpAmt.
in =
mulRatio(ofrAmt.in, ofrInRate, QUALITY_ONE,
true);
803 auto const funds = offer.isFunded()
805 : offers.ownerFunds();
808 if (funds < ownerGives)
812 stpAmt.
out =
mulRatio(ownerGives, QUALITY_ONE, ofrOutRate,
false);
817 ofrAmt = offer.limitOut(ofrAmt, stpAmt.
out,
false);
819 stpAmt.
in =
mulRatio(ofrAmt.in, ofrInRate, QUALITY_ONE,
true);
825 auto const& issuer = assetIn.
getIssuer();
826 if (isAssetInMPT && !
prevStep_ && offer.owner() != issuer)
836 if (stpAmt.
in > available)
839 offer, ofrAmt, stpAmt, ownerGives, ofrInRate, ofrOutRate, available);
843 offerAttempted =
true;
844 return callback(offer, ofrAmt, stpAmt, ownerGives, ofrInRate, ofrOutRate);
852 "BookStep::forEachOffer removed MPT offer after "
853 "overflow during crossing");
854 removeOffer(
"Removing offer with overflowing amount calculation");
864 "xrpl::BookStep::forEachOffer : overflow implies MPTokensV2");
880 return static_cast<TDerived const*
>(
this)->qualityThreshold(*lobQuality);
884 return !ammOffer || execOffer(*ammOffer);
889 if (tryAMM(offers.tip().quality()))
893 if (!execOffer(offers.tip()))
895 }
while (offers.step());
901 tryAMM(std::nullopt);
904 return {offers.permToRemove(), counter.
count()};
907template <
class TIn,
class TOut,
class TDerived>
908template <
template <
typename,
typename>
typename Offer>
915 TOut
const& ownerGives)
const
917 if (!offer.checkInvariant(ofrAmt,
j_))
943 auto const dr = offer.send(
952 auto const& issuer =
book_.out.getIssuer();
959 if (offer.owner() == issuer)
964 offer.consume(sb, ofrAmt);
967template <
class TIn,
class TOut,
class TDerived>
983template <
class TIn,
class TOut,
class TDerived>
1010 return static_cast<TDerived const*
>(
this)->qualityThreshold(*lobQuality);
1011 return std::nullopt;
1014 if (
auto const ammOffer =
getAMMOffer(view, qualityThreshold);
1015 ammOffer && ((lobQuality && ammOffer->quality() > lobQuality) || !lobQuality))
1021template <
class TIn,
class TOut,
class TDerived>
1026 auto const res =
tip(view);
1029 return std::nullopt;
1039template <
class TIn,
class TOut,
class TDerived>
1043 auto const res =
tip(view);
1046 return std::nullopt;
1053 return std::get<AMMOffer<TIn, TOut>>(*res).getQualityFunc();
1056template <
class TCollection>
1066template <
class TIn,
class TOut,
class TDerived>
1071 boost::container::flat_set<uint256>& ofrsToRm,
1078 auto remainingOut = out;
1080 boost::container::flat_multiset<TIn> savedIns;
1081 savedIns.reserve(64);
1082 boost::container::flat_multiset<TOut> savedOuts;
1083 savedOuts.reserve(64);
1089 auto eachOffer = [&](
auto& offer,
1092 TOut
const& ownerGives,
1098 if (stpAmt.out <= remainingOut)
1100 savedIns.insert(stpAmt.in);
1101 savedOuts.insert(stpAmt.out);
1103 remainingOut = out - result.
out;
1104 this->
consumeOffer(sb, offer, ofrAmt, stpAmt, ownerGives);
1110 auto ofrAdjAmt = ofrAmt;
1111 auto stpAdjAmt = stpAmt;
1112 auto ownerGivesAdj = ownerGives;
1129 savedIns.insert(stpAdjAmt.in);
1130 savedOuts.insert(remainingOut);
1131 result.
in =
sum(savedIns);
1133 this->
consumeOffer(sb, offer, ofrAdjAmt, stpAdjAmt, ownerGivesAdj);
1140 return offer.fullyConsumed();
1144 auto const prevStepDebtDir = [&] {
1149 auto const r =
forEachOffer(sb, afView, prevStepDebtDir, eachOffer);
1150 boost::container::flat_set<uint256>
const toRm = std::move(std::get<0>(r));
1162 switch (remainingOut.signum())
1167 JLOG(
j_.error()) <<
"BookStep remainingOut < 0 " <<
to_string(remainingOut);
1168 UNREACHABLE(
"xrpl::BookStep::revImp : remaining less than zero");
1181 return {result.
in, result.
out};
1184template <
class TIn,
class TOut,
class TDerived>
1189 boost::container::flat_set<uint256>& ofrsToRm,
1192 XRPL_ASSERT(
cache_,
"xrpl::BookStep::fwdImp : cache is set");
1196 auto remainingIn = in;
1198 boost::container::flat_multiset<TIn> savedIns;
1199 savedIns.reserve(64);
1200 boost::container::flat_multiset<TOut> savedOuts;
1201 savedOuts.reserve(64);
1205 auto eachOffer = [&](
auto& offer,
1208 TOut
const& ownerGives,
1211 XRPL_ASSERT(
cache_,
"xrpl::BookStep::fwdImp::eachOffer : cache is set");
1216 bool processMore =
true;
1217 auto ofrAdjAmt = ofrAmt;
1218 auto stpAdjAmt = stpAmt;
1219 auto ownerGivesAdj = ownerGives;
1230 auto savedInsAdj = savedIns;
1231 auto savedOutsAdj = savedOuts;
1232 auto resultAdj = result;
1233 typename boost::container::flat_multiset<TOut>::const_iterator lastOut;
1235 if (stpAmt.in <= remainingIn)
1237 savedInsAdj.insert(stpAmt.in);
1238 lastOut = savedOutsAdj.insert(stpAmt.out);
1253 savedInsAdj.insert(remainingIn);
1254 lastOut = savedOutsAdj.insert(stpAdjAmt.out);
1255 resultAdj.out =
sum(savedOutsAdj);
1258 processMore =
false;
1261 if (resultAdj.out >
cache_->out && resultAdj.in <=
cache_->in)
1270 auto const lastOutAmt = *lastOut;
1271 savedOutsAdj.erase(lastOut);
1272 auto const remainingOut =
cache_->out -
sum(savedOutsAdj);
1273 auto ofrAdjAmtRev = ofrAmt;
1274 auto stpAdjAmtRev = stpAmt;
1275 auto ownerGivesAdjRev = ownerGives;
1285 if (stpAdjAmtRev.in == remainingIn)
1288 resultAdj.out =
cache_->out;
1290 savedInsAdj.clear();
1291 savedInsAdj.insert(resultAdj.in);
1292 savedOutsAdj.clear();
1293 savedOutsAdj.insert(resultAdj.out);
1295 ofrAdjAmt = ofrAdjAmtRev;
1296 stpAdjAmt.in = remainingIn;
1297 stpAdjAmt.out = remainingOut;
1298 ownerGivesAdj = ownerGivesAdjRev;
1304 savedOutsAdj.insert(lastOutAmt);
1310 savedIns = std::move(savedInsAdj);
1311 savedOuts = std::move(savedOutsAdj);
1313 remainingIn = in - result.
in;
1314 this->
consumeOffer(sb, offer, ofrAdjAmt, stpAdjAmt, ownerGivesAdj);
1320 return processMore || offer.fullyConsumed();
1324 auto const prevStepDebtDir = [&] {
1329 auto const r =
forEachOffer(sb, afView, prevStepDebtDir, eachOffer);
1330 boost::container::flat_set<uint256>
const toRm = std::move(std::get<0>(r));
1342 switch (remainingIn.signum())
1347 JLOG(
j_.error()) <<
"BookStep remainingIn < 0 " <<
to_string(remainingIn);
1348 UNREACHABLE(
"xrpl::BookStep::fwdImp : remaining less than zero");
1361 return {result.
in, result.
out};
1364template <
class TIn,
class TOut,
class TDerived>
1373 JLOG(
j_.trace()) <<
"Expected valid cache in validFwd";
1377 auto const savCache = *
cache_;
1381 boost::container::flat_set<uint256> dummy;
1384 catch (FlowException
const&)
1392 JLOG(
j_.warn()) <<
"Strand re-execute check failed."
1393 <<
" ExpectedIn: " <<
to_string(savCache.in)
1395 <<
" ExpectedOut: " <<
to_string(savCache.out)
1403template <
class TIn,
class TOut,
class TDerived>
1409 JLOG(
j_.debug()) <<
"BookStep: Book with same in and out issuer " << *
this;
1414 JLOG(
j_.debug()) <<
"Book: currency is inconsistent with issuer." << *
this;
1423 JLOG(
j_.debug()) <<
"BookStep: loop detected: " << *
this;
1429 JLOG(
j_.debug()) <<
"BookStep: loop detected: " << *
this;
1433 auto issuerExists = [](
ReadView const& view,
Asset const& iss) ->
bool {
1439 JLOG(
j_.debug()) <<
"BookStep: deleted issuer detected: " << *
this;
1447 auto const& view = ctx.
view;
1448 auto const& cur =
book_.in.getIssuer();
1450 auto const err =
book_.in.visit(
1455 if (sle->isFlag((cur > *prev) ? lsfHighNoRipple : lsfLowNoRipple))
1457 return std::nullopt;
1474template <
class TIn,
class TOut,
class TDerived>
1493 if (asset ==
strandDeliver_ && mptIssue.getIssuer() == dstAccount)
1499template <
class TIn,
class TOut,
class TDerived>
1509 auto const& asset =
book_.in;
1514 if (asset.getIssuer() == owner)
1536 auto const& asset =
book_.out;
1541 if (asset.getIssuer() == owner)
1556template <
class TIn,
class TOut,
class TDerived>
1561 return book == bs->book();
1569 [&]<
typename TIn,
typename TOut>(TIn
const&, TOut
const&) {
1570 using TIn_ = TIn::amount_type;
1571 using TOut_ = TOut::amount_type;
1580 UNREACHABLE(
"xrpl::bookStepEqual : invalid book step");
1585 book.in.getAmountType(),
1586 book.out.getAmountType());
1592template <
class TIn,
class TOut>
1601 ter = offerCrossingStep->check(ctx);
1602 r = std::move(offerCrossingStep);
1607 ter = paymentStep->check(ctx);
1608 r = std::move(paymentStep);
1611 return {ter,
nullptr};
A generic endpoint for log messages.
Represents synthetic AMM offer in BookStep.
Quality quality() const noexcept
Writeable view to a ledger, for applying a transaction.
constexpr auto visit(Visitors &&... visitors) const -> decltype(auto)
AccountID const & getIssuer() const
constexpr bool holds() const
std::uint32_t getOfrInRate(Step const *prevStep, AccountID const &owner, std::uint32_t trIn) const
std::string logString() const override
bool checkQualityThreshold(Quality const &quality) const
BookOfferCrossingStep(StrandContext const &ctx, Asset const &in, Asset const &out)
Quality adjustQualityWithFees(ReadView const &v, Quality const &ofrQ, DebtDirection prevStepDir, WaiveTransferFee waiveFee, OfferType offerType, Rules const &rules) const
bool limitSelfCrossQuality(AccountID const &strandSrc, AccountID const &strandDst, Offer< TIn, TOut > const &offer, std::optional< Quality > &ofrQ, FlowOfferStream< TIn, TOut > &offers, bool const offerAttempted) const
static Quality getQuality(std::optional< Quality > const &limitQuality)
std::optional< Quality > qualityThreshold(Quality const &lobQuality) const
Quality const qualityThreshold_
std::uint32_t getOfrOutRate(Step const *prevStep, AccountID const &owner, AccountID const &strandDst, std::uint32_t trOut) const
BookPaymentStep(StrandContext const &ctx, Asset const &in, Asset const &out)
std::optional< Quality > qualityThreshold(Quality const &lobQuality) const
bool limitSelfCrossQuality(AccountID const &, AccountID const &, Offer< TIn, TOut > const &offer, std::optional< Quality > &, FlowOfferStream< TIn, TOut > &, bool) const
Quality adjustQualityWithFees(ReadView const &v, Quality const &ofrQ, DebtDirection prevStepDir, WaiveTransferFee waiveFee, OfferType, Rules const &) const
std::uint32_t getOfrInRate(Step const *, AccountID const &, std::uint32_t trIn) const
std::uint32_t getOfrOutRate(Step const *, AccountID const &, AccountID const &, std::uint32_t trOut) const
std::string logString() const override
BookPaymentStep()=default
bool checkQualityThreshold(Quality const &quality) const
TER check(StrandContext const &ctx) const
Step const *const prevStep_
friend bool operator==(BookStep const &lhs, BookStep const &rhs)
std::pair< boost::container::flat_set< uint256 >, std::uint32_t > forEachOffer(PaymentSandbox &sb, ApplyView &afView, DebtDirection prevStepDebtDir, Callback &callback) const
std::optional< Book > bookStepBook() const override
std::optional< std::variant< Quality, AMMOffer< TIn, TOut > > > tip(ReadView const &view) const
std::optional< QualityFunction > tipOfferQualityF(ReadView const &view) const
Asset const strandDeliver_
std::optional< EitherAmount > cachedIn() const override
std::optional< AMMOffer< TIn, TOut > > getAMMOffer(ReadView const &view, std::optional< Quality > const &clobQuality) const
bool const ownerPaysTransferFee_
DebtDirection debtDirection(ReadView const &sb, StrandDirection dir) const override
BookStep(StrandContext const &ctx, Asset const &in, Asset const &out)
void consumeOffer(PaymentSandbox &sb, Offer< TIn, TOut > &offer, TAmounts< TIn, TOut > const &ofrAmt, TAmounts< TIn, TOut > const &stepAmt, TOut const &ownerGives) const
std::pair< TIn, TOut > fwdImp(PaymentSandbox &sb, ApplyView &afView, boost::container::flat_set< uint256 > &ofrsToRm, TIn const &in)
bool equal(Step const &rhs) const override
std::optional< Cache > cache_
std::uint32_t offersUsed_
Number of offers consumed or partially consumed the last time the step ran, including expired and unf...
std::optional< EitherAmount > cachedOut() const override
std::pair< TIn, TOut > revImp(PaymentSandbox &sb, ApplyView &afView, boost::container::flat_set< uint256 > &ofrsToRm, TOut const &out)
std::pair< std::optional< Quality >, DebtDirection > qualityUpperBound(ReadView const &v, DebtDirection prevStepDir) const override
bool inactive() const override
friend bool operator!=(BookStep const &lhs, BookStep const &rhs)
std::uint32_t offersUsed() const override
std::pair< std::optional< QualityFunction >, DebtDirection > getQualityFunc(ReadView const &v, DebtDirection prevStepDir) const override
std::optional< AMMLiquidity< TIn, TOut > > ammLiquidity_
Rate rate(ReadView const &view, Asset const &asset, AccountID const &dstAccount) const
Book const & book() const
static constexpr uint32_t kMaxOffersToConsume
std::optional< std::pair< Quality, OfferType > > tipOfferQuality(ReadView const &view) const
std::string logStringImpl(char const *name) const
bool checkMPTDEX(ReadView const &view, AccountID const &owner) const
std::pair< bool, EitherAmount > validFwd(PaymentSandbox &sb, ApplyView &afView, EitherAmount const &in) override
Iterates and consumes raw offers in an order book.
bool step(beast::Journal j)
Erases the current offer and advance to the next offer.
Quality const & quality() const noexcept
Presents and consumes the offers in an order book.
A currency issued by an account.
A wrapper which makes credits unavailable to balances.
Average quality of a path as a function of out: q(out) = m * out + b, where m = -1 / poolGets,...
void combine(QualityFunction const &qf)
Combines QF with the next step QF.
Represents the logical ratio of output currency to input currency.
virtual Rules const & rules() const =0
Returns the tx processing rules.
NetClock::time_point parentCloseTime() const
Returns the close time of the previous ledger.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
Rules controlling protocol behavior.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
static std::uint64_t const kURateOne
Discardable, editable view to a ledger.
A step in a payment path.
virtual std::optional< AccountID > directStepSrcAcct() const
If this step is DirectStepI (IOU->IOU direct step), return the src account.
virtual std::optional< Book > bookStepBook() const
If this step is a BookStep, return the book.
std::uint32_t count() const
Rules const & rules() const override
Returns the tx processing rules.
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
bool bookStepEqual(Step const &step, xrpl::Book const &book)
static bool equalHelper(Step const &step, xrpl::Book const &book)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
static auto sum(TCollection const &col)
TER checkCreateMPT(xrpl::ApplyView &view, xrpl::MPTIssue const &mptIssue, xrpl::AccountID const &holder, SLE::ref sponsorSle, std::uint32_t flags, beast::Journal j)
std::pair< TER, std::unique_ptr< Step > > makeBookStepIi(StrandContext const &ctx, Issue const &in, Issue const &out)
bool isXRP(AccountID const &c)
static void limitStepOut(Offer const &offer, TAmounts< TIn, TOut > &ofrAmt, TAmounts< TIn, TOut > &stpAmt, TOut &ownerGives, std::uint32_t transferRateIn, std::uint32_t transferRateOut, TOut const &limit)
T get(Section const §ion, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
std::pair< TER, std::unique_ptr< Step > > makeBookStepMx(StrandContext const &ctx, MPTIssue const &in)
void setUnion(boost::container::flat_set< T > &dst, boost::container::flat_set< T > const &src)
Given two flat sets dst and src, compute dst = dst union src.
std::pair< TER, std::unique_ptr< Step > > makeBookStepMi(StrandContext const &ctx, MPTIssue const &in, Issue const &out)
static void limitStepIn(Offer const &offer, TAmounts< TIn, TOut > &ofrAmt, TAmounts< TIn, TOut > &stpAmt, TOut &ownerGives, std::uint32_t transferRateIn, std::uint32_t transferRateOut, TIn const &limit)
TER canTransfer(ReadView const &view, MPTIssue const &mptIssue, AccountID const &from, AccountID const &to, WaiveMPTCanTransfer waive=WaiveMPTCanTransfer::No, std::uint8_t depth=0)
Check whether to may receive the given MPT from from.
std::pair< TER, std::unique_ptr< Step > > makeBookStepIx(StrandContext const &ctx, Issue const &in)
std::string to_string(BaseUInt< Bits, Tag > const &a)
TER canTrade(ReadView const &view, Asset const &asset, std::uint8_t depth=0)
Check whether asset may be traded on the DEX.
T toAmount(STAmount const &amt)=delete
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
static bool isDefaultPath(STPath const &path)
std::pair< TER, std::unique_ptr< Step > > makeBookStepXm(StrandContext const &ctx, MPTIssue const &out)
IOUAmount mulRatio(IOUAmount const &amt, std::uint32_t num, std::uint32_t den, bool roundUp)
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
Rate const kParityRate
A transfer rate signifying a 1:1 exchange.
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
std::pair< TER, std::unique_ptr< Step > > makeBookStepXi(StrandContext const &ctx, Issue const &out)
bool checkNear(IOUAmount const &expected, IOUAmount const &actual)
bool isFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptIssue, std::uint8_t depth=0)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
std::pair< TER, std::unique_ptr< Step > > makeBookStepIm(StrandContext const &ctx, Issue const &in, MPTIssue const &out)
bool isTesSuccess(TER x) noexcept
TERSubset< CanCvtToTER > TER
bool isConsistent(Asset const &asset)
TER requireAuth(ReadView const &view, MPTIssue const &mptIssue, AccountID const &account, AuthType authType=AuthType::Legacy, std::uint8_t depth=0)
Check if the account lacks required authorization for MPT.
void issuerSelfDebitHookMPT(ApplyView &view, MPTIssue const &issue, std::uint64_t amount)
Facilitate tracking of MPT sold by an issuer owning MPT sell offer.
bool redeems(DebtDirection dir)
static std::pair< TER, std::unique_ptr< Step > > makeBookStepHelper(StrandContext const &ctx, Asset const &in, Asset const &out)
std::pair< TER, std::unique_ptr< Step > > makeBookStepMm(StrandContext const &ctx, MPTIssue const &in, MPTIssue const &out)
Quality composedQuality(Quality const &lhs, Quality const &rhs)
Calculate the quality of a two-hop path given the two hops.
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
STAmount toSTAmount(IOUAmount const &iou, Asset const &asset)
Cache(TIn const &in, TOut const &out)
Represents a transfer rate.
Context needed to build Strand Steps and for error checking.
ReadView const & view
Current ReadView.
std::array< boost::container::flat_set< Asset >, 2 > & seenDirectAssets
A strand may not include the same account node more than once in the same currency.
boost::container::flat_set< Asset > & seenBookOuts
A strand may not include an offer that output the same issue more than once.
Step const *const prevStep
The previous step in the strand.
OfferCrossing const offerCrossing
Yes/Sell if offer crossing, not payment.
Represents a pair of input and output currencies.