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>
54template <
class TIn,
class TOut,
class TDerived>
55class BookStep :
public StepImp<TIn, TOut, BookStep<TIn, TOut, TDerived>>
98 :
book_(in, out, ctx.domainID)
107 ammSle && ammSle->getFieldAmount(sfLPTokenBalance) != beast::kZero)
109 ammLiquidity_.emplace(
111 (*ammSle)[sfAccount],
112 getTradingFee(ctx.view, *ammSle, ctx.ammContext.account()),
121 [[nodiscard]]
Book const&
168 boost::container::flat_set<uint256>& ofrsToRm,
175 boost::container::flat_set<uint256>& ofrsToRm,
197 <<
"\ninIss: " <<
book_.in.getIssuer() <<
"\noutIss: " <<
book_.out.getIssuer()
215 return !(lhs == rhs);
226 template <
class Callback>
232 Callback& callback)
const;
235 template <
template <
typename,
typename>
typename Offer>
242 TOut
const& ownerGives)
const;
281template <
class TIn,
class TOut>
296 template <
template <
typename,
typename>
typename Offer>
357 ? this->
rate(v, this->
book_.out, this->strandDst_)
372template <
class TIn,
class TOut>
385 XRPL_ASSERT(limitQuality,
"xrpl::BookOfferCrossingStep::getQuality : nonzero quality");
388 return *limitQuality;
399 template <
template <
typename,
typename>
typename Offer>
407 bool const offerAttempted)
const
439 strandDst == offer.owner())
442 if (
auto const key = offer.
key())
443 offers.permRmOffer(*key);
488 auto const srcAcct = (prevStep !=
nullptr) ? prevStep->
directStepSrcAcct() : std::nullopt;
490 return owner == srcAcct
498 Step const* prevStep,
517 Rules const& rules)
const
529 if (!rules.
enabled(fixAMMv1_1))
533 if (offerType == OfferType::Clob ||
561template <
class TIn,
class TOut,
class TDerived>
566 return book_ == bs->book_;
570template <
class TIn,
class TOut,
class TDerived>
578 return {std::nullopt, dir};
583 Quality const q =
static_cast<TDerived const*
>(
this)->adjustQualityWithFees(
584 v, std::get<Quality>(*res), prevStepDir, waiveFee, std::get<OfferType>(*res), v.
rules());
588template <
class TIn,
class TOut,
class TDerived>
596 return {std::nullopt, dir};
602 auto const q =
static_cast<TDerived const*
>(
this)->adjustQualityWithFees(
612 Quality const q =
static_cast<TDerived const*
>(
this)->adjustQualityWithFees(
623template <
class TIn,
class TOut,
class TDerived>
631template <
class TIn,
class TOut,
class Offer>
642 if (limit < stpAmt.
in)
645 auto const inLmt =
mulRatio(stpAmt.
in, QUALITY_ONE, transferRateIn,
false);
653 ofrAmt = offer.limitIn(ofrAmt, inLmt,
false);
655 ownerGives =
mulRatio(ofrAmt.
out, transferRateOut, QUALITY_ONE,
false);
660template <
class TIn,
class TOut,
class Offer>
671 if (limit < stpAmt.
out)
674 ownerGives =
mulRatio(stpAmt.
out, transferRateOut, QUALITY_ONE,
false);
675 ofrAmt = offer.limitOut(
679 stpAmt.
in =
mulRatio(ofrAmt.
in, transferRateIn, QUALITY_ONE,
true);
683template <
class TIn,
class TOut,
class TDerived>
684template <
class Callback>
690 Callback& callback)
const
698 redeems(prevStepDir) ?
rate(sb,
book_.in, this->strandDst_).value : QUALITY_ONE;
707 bool offerAttempted =
false;
709 auto execOffer = [&](
auto& offer) {
714 ofrQ = offer.quality();
716 else if (*ofrQ != offer.quality())
721 if (
static_cast<TDerived const*
>(
this)->limitSelfCrossQuality(
725 Asset const& assetIn = offer.assetIn();
727 auto const& owner = offer.owner();
743 auto& applyView = sb.
rules().
enabled(featureMPTokensV2) ? sb : afView;
751 if (
auto const key = offer.
key())
752 offers.permRmOffer(*key);
762 if (!
static_cast<TDerived const*
>(
this)->checkQualityThreshold(offer.quality()))
765 auto const [ofrInRate, ofrOutRate] = offer.adjustRates(
769 auto ofrAmt = offer.amount();
770 TAmounts stpAmt{
mulRatio(ofrAmt.in, ofrInRate, QUALITY_ONE,
true), ofrAmt.out};
773 auto ownerGives =
mulRatio(ofrAmt.out, ofrOutRate, QUALITY_ONE,
false);
775 auto const funds = offer.isFunded()
777 : offers.ownerFunds();
780 if (funds < ownerGives)
784 stpAmt.
out =
mulRatio(ownerGives, QUALITY_ONE, ofrOutRate,
false);
789 ofrAmt = offer.limitOut(ofrAmt, stpAmt.
out,
false);
791 stpAmt.
in =
mulRatio(ofrAmt.in, ofrInRate, QUALITY_ONE,
true);
797 auto const& issuer = assetIn.
getIssuer();
798 if (isAssetInMPT && !
prevStep_ && offer.owner() != issuer)
808 if (stpAmt.
in > available)
810 limitStepIn(offer, ofrAmt, stpAmt, ownerGives, ofrInRate, ofrOutRate, available);
814 offerAttempted =
true;
815 return callback(offer, ofrAmt, stpAmt, ownerGives, ofrInRate, ofrOutRate);
828 return static_cast<TDerived const*
>(
this)->qualityThreshold(*lobQuality);
832 return !ammOffer || execOffer(*ammOffer);
837 if (tryAMM(offers.tip().quality()))
841 if (!execOffer(offers.tip()))
843 }
while (offers.step());
849 tryAMM(std::nullopt);
852 return {offers.permToRemove(), counter.
count()};
855template <
class TIn,
class TOut,
class TDerived>
856template <
template <
typename,
typename>
typename Offer>
863 TOut
const& ownerGives)
const
865 if (!offer.checkInvariant(ofrAmt,
j_))
878 auto const dr = offer.send(
887 auto const& issuer =
book_.out.getIssuer();
894 if (offer.owner() == issuer)
899 offer.consume(sb, ofrAmt);
902template <
class TIn,
class TOut,
class TDerived>
918template <
class TIn,
class TOut,
class TDerived>
945 return static_cast<TDerived const*
>(
this)->qualityThreshold(*lobQuality);
949 if (
auto const ammOffer =
getAMMOffer(view, qualityThreshold);
950 ammOffer && ((lobQuality && ammOffer->quality() > lobQuality) || !lobQuality))
956template <
class TIn,
class TOut,
class TDerived>
961 auto const res =
tip(view);
974template <
class TIn,
class TOut,
class TDerived>
978 auto const res =
tip(view);
988 return std::get<AMMOffer<TIn, TOut>>(*res).getQualityFunc();
991template <
class TCollection>
993sum(TCollection
const& col)
997 return TResult{beast::kZero};
1001template <
class TIn,
class TOut,
class TDerived>
1006 boost::container::flat_set<uint256>& ofrsToRm,
1013 auto remainingOut = out;
1015 boost::container::flat_multiset<TIn> savedIns;
1016 savedIns.reserve(64);
1017 boost::container::flat_multiset<TOut> savedOuts;
1018 savedOuts.reserve(64);
1024 auto eachOffer = [&](
auto& offer,
1027 TOut
const& ownerGives,
1030 if (remainingOut <= beast::kZero)
1033 if (stpAmt.out <= remainingOut)
1035 savedIns.insert(stpAmt.in);
1036 savedOuts.insert(stpAmt.out);
1038 remainingOut = out - result.
out;
1039 this->
consumeOffer(sb, offer, ofrAmt, stpAmt, ownerGives);
1045 auto ofrAdjAmt = ofrAmt;
1046 auto stpAdjAmt = stpAmt;
1047 auto ownerGivesAdj = ownerGives;
1056 remainingOut = beast::kZero;
1057 savedIns.insert(stpAdjAmt.in);
1058 savedOuts.insert(remainingOut);
1059 result.
in =
sum(savedIns);
1061 this->
consumeOffer(sb, offer, ofrAdjAmt, stpAdjAmt, ownerGivesAdj);
1068 return offer.fullyConsumed();
1072 auto const prevStepDebtDir = [&] {
1077 auto const r =
forEachOffer(sb, afView, prevStepDebtDir, eachOffer);
1078 boost::container::flat_set<uint256>
const toRm = std::move(std::get<0>(r));
1090 switch (remainingOut.signum())
1095 JLOG(
j_.error()) <<
"BookStep remainingOut < 0 " <<
to_string(remainingOut);
1096 UNREACHABLE(
"xrpl::BookStep::revImp : remaining less than zero");
1097 cache_.emplace(beast::kZero, beast::kZero);
1098 return {beast::kZero, beast::kZero};
1109 return {result.
in, result.
out};
1112template <
class TIn,
class TOut,
class TDerived>
1117 boost::container::flat_set<uint256>& ofrsToRm,
1120 XRPL_ASSERT(
cache_,
"xrpl::BookStep::fwdImp : cache is set");
1124 auto remainingIn = in;
1126 boost::container::flat_multiset<TIn> savedIns;
1127 savedIns.reserve(64);
1128 boost::container::flat_multiset<TOut> savedOuts;
1129 savedOuts.reserve(64);
1133 auto eachOffer = [&](
auto& offer,
1136 TOut
const& ownerGives,
1139 XRPL_ASSERT(
cache_,
"xrpl::BookStep::fwdImp::eachOffer : cache is set");
1141 if (remainingIn <= beast::kZero)
1144 bool processMore =
true;
1145 auto ofrAdjAmt = ofrAmt;
1146 auto stpAdjAmt = stpAmt;
1147 auto ownerGivesAdj = ownerGives;
1149 typename boost::container::flat_multiset<TOut>::const_iterator lastOut;
1150 if (stpAmt.in <= remainingIn)
1152 savedIns.insert(stpAmt.in);
1153 lastOut = savedOuts.insert(stpAmt.out);
1168 savedIns.insert(remainingIn);
1169 lastOut = savedOuts.insert(stpAdjAmt.out);
1170 result.
out =
sum(savedOuts);
1173 processMore =
false;
1185 auto const lastOutAmt = *lastOut;
1186 savedOuts.erase(lastOut);
1187 auto const remainingOut =
cache_->out -
sum(savedOuts);
1188 auto ofrAdjAmtRev = ofrAmt;
1189 auto stpAdjAmtRev = stpAmt;
1190 auto ownerGivesAdjRev = ownerGives;
1200 if (stpAdjAmtRev.in == remainingIn)
1206 savedIns.insert(result.
in);
1208 savedOuts.insert(result.
out);
1210 ofrAdjAmt = ofrAdjAmtRev;
1211 stpAdjAmt.in = remainingIn;
1212 stpAdjAmt.out = remainingOut;
1213 ownerGivesAdj = ownerGivesAdjRev;
1219 savedOuts.insert(lastOutAmt);
1223 remainingIn = in - result.
in;
1224 this->
consumeOffer(sb, offer, ofrAdjAmt, stpAdjAmt, ownerGivesAdj);
1230 return processMore || offer.fullyConsumed();
1234 auto const prevStepDebtDir = [&] {
1239 auto const r =
forEachOffer(sb, afView, prevStepDebtDir, eachOffer);
1240 boost::container::flat_set<uint256>
const toRm = std::move(std::get<0>(r));
1252 switch (remainingIn.signum())
1257 JLOG(
j_.error()) <<
"BookStep remainingIn < 0 " <<
to_string(remainingIn);
1258 UNREACHABLE(
"xrpl::BookStep::fwdImp : remaining less than zero");
1259 cache_.emplace(beast::kZero, beast::kZero);
1260 return {beast::kZero, beast::kZero};
1271 return {result.
in, result.
out};
1274template <
class TIn,
class TOut,
class TDerived>
1283 JLOG(
j_.trace()) <<
"Expected valid cache in validFwd";
1287 auto const savCache = *
cache_;
1291 boost::container::flat_set<uint256> dummy;
1294 catch (FlowException
const&)
1302 JLOG(
j_.warn()) <<
"Strand re-execute check failed."
1303 <<
" ExpectedIn: " <<
to_string(savCache.in)
1305 <<
" ExpectedOut: " <<
to_string(savCache.out)
1313template <
class TIn,
class TOut,
class TDerived>
1319 JLOG(
j_.debug()) <<
"BookStep: Book with same in and out issuer " << *
this;
1324 JLOG(
j_.debug()) <<
"Book: currency is inconsistent with issuer." << *
this;
1333 JLOG(
j_.debug()) <<
"BookStep: loop detected: " << *
this;
1339 JLOG(
j_.debug()) <<
"BookStep: loop detected: " << *
this;
1343 auto issuerExists = [](
ReadView const& view,
Asset const& iss) ->
bool {
1349 JLOG(
j_.debug()) <<
"BookStep: deleted issuer detected: " << *
this;
1357 auto const& view = ctx.
view;
1358 auto const& cur =
book_.in.getIssuer();
1360 auto const err =
book_.in.visit(
1365 if (sle->isFlag((cur > *prev) ? lsfHighNoRipple : lsfLowNoRipple))
1367 return std::nullopt;
1384template <
class TIn,
class TOut,
class TDerived>
1403 if (asset ==
strandDeliver_ && mptIssue.getIssuer() == dstAccount)
1409template <
class TIn,
class TOut,
class TDerived>
1419 auto const& asset =
book_.in;
1424 if (asset.getIssuer() == owner)
1446 auto const& asset =
book_.out;
1451 if (asset.getIssuer() == owner)
1466template <
class TIn,
class TOut,
class TDerived>
1471 return book == bs->book();
1479 [&]<
typename TIn,
typename TOut>(TIn
const&, TOut
const&) {
1480 using TIn_ = TIn::amount_type;
1481 using TOut_ = TOut::amount_type;
1490 UNREACHABLE(
"xrpl::bookStepEqual : invalid book step");
1495 book.in.getAmountType(),
1496 book.out.getAmountType());
1502template <
class TIn,
class TOut>
1511 ter = offerCrossingStep->check(ctx);
1512 r = std::move(offerCrossingStep);
1517 ter = paymentStep->check(ctx);
1518 r = std::move(paymentStep);
1521 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)
constexpr TIss const & get() const
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)
std::pair< TER, std::unique_ptr< Step > > makeBookStepIi(StrandContext const &ctx, Issue const &in, Issue const &out)
bool isXRP(AccountID const &c)
TER checkCreateMPT(xrpl::ApplyView &view, xrpl::MPTIssue const &mptIssue, xrpl::AccountID const &holder, beast::Journal j)
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.