20#include <xrpld/app/ledger/OrderBookDB.h>
21#include <xrpld/app/misc/PermissionedDEXHelpers.h>
22#include <xrpld/app/paths/Flow.h>
23#include <xrpld/app/tx/detail/CreateOffer.h>
24#include <xrpld/ledger/PaymentSandbox.h>
26#include <xrpl/basics/base_uint.h>
27#include <xrpl/beast/utility/WrappedSink.h>
28#include <xrpl/protocol/Feature.h>
29#include <xrpl/protocol/Quality.h>
30#include <xrpl/protocol/STAmount.h>
31#include <xrpl/protocol/TER.h>
32#include <xrpl/protocol/st.h>
39 auto const& amount{tx[sfTakerGets]};
40 return amount.native() ? amount.xrp() : beast::zero;
69 JLOG(j.debug()) <<
"Malformed transaction: Invalid flags set.";
76 if (tx.isFlag(
tfHybrid) && !tx.isFieldPresent(sfDomainID))
82 if (bImmediateOrCancel && bFillOrKill)
84 JLOG(j.debug()) <<
"Malformed transaction: both IoC and FoK set.";
88 bool const bHaveExpiration(tx.isFieldPresent(sfExpiration));
90 if (bHaveExpiration && (tx.getFieldU32(sfExpiration) == 0))
92 JLOG(j.debug()) <<
"Malformed offer: bad expiration";
96 if (
auto const cancelSequence = tx[~sfOfferSequence];
97 cancelSequence && *cancelSequence == 0)
99 JLOG(j.debug()) <<
"Malformed offer: bad cancel sequence";
103 STAmount saTakerPays = tx[sfTakerPays];
104 STAmount saTakerGets = tx[sfTakerGets];
111 JLOG(j.debug()) <<
"Malformed offer: redundant (XRP for XRP)";
114 if (saTakerPays <= beast::zero || saTakerGets <= beast::zero)
116 JLOG(j.debug()) <<
"Malformed offer: bad amount";
120 auto const& uPaysIssuerID = saTakerPays.
getIssuer();
121 auto const& uPaysCurrency = saTakerPays.
getCurrency();
123 auto const& uGetsIssuerID = saTakerGets.
getIssuer();
124 auto const& uGetsCurrency = saTakerGets.
getCurrency();
126 if (uPaysCurrency == uGetsCurrency && uPaysIssuerID == uGetsIssuerID)
128 JLOG(j.debug()) <<
"Malformed offer: redundant (IOU for IOU)";
134 JLOG(j.debug()) <<
"Malformed offer: bad currency";
138 if (saTakerPays.
native() != !uPaysIssuerID ||
139 saTakerGets.
native() != !uGetsIssuerID)
141 JLOG(j.debug()) <<
"Malformed offer: bad issuer";
151 auto const id = ctx.
tx[sfAccount];
153 auto saTakerPays = ctx.
tx[sfTakerPays];
154 auto saTakerGets = ctx.
tx[sfTakerGets];
156 auto const& uPaysIssuerID = saTakerPays.getIssuer();
157 auto const& uPaysCurrency = saTakerPays.getCurrency();
159 auto const& uGetsIssuerID = saTakerGets.getIssuer();
161 auto const cancelSequence = ctx.
tx[~sfOfferSequence];
167 std::uint32_t const uAccountSequence = sleCreator->getFieldU32(sfSequence);
174 JLOG(ctx.
j.
debug()) <<
"Offer involves frozen asset";
182 <<
"delay: Offers must be at least partially funded.";
188 if (cancelSequence && (uAccountSequence <= *cancelSequence))
190 JLOG(ctx.
j.
debug()) <<
"uAccountSequenceNext=" << uAccountSequence
191 <<
" uOfferSequence=" << *cancelSequence;
209 if (!saTakerPays.native())
216 Issue(uPaysCurrency, uPaysIssuerID));
226 ctx.
view,
id, ctx.
tx[sfDomainID]))
244 "ripple::CreateOffer::checkAcceptAsset : input is not XRP");
251 <<
"delay: can't receive IOUs from non-existent issuer: "
266 auto const trustLine =
277 bool const canonical_gt(
id > issue.
account);
279 bool const is_authorized(
285 <<
"delay: can't receive IOUs from issuer without auth.";
299 auto const trustLine =
309 bool const deepFrozen =
323 if (offer.fully_consumed())
331 return (amount <= beast::zero);
344 have_direct || have_bridge,
345 "ripple::CreateOffer::select_path : valid inputs");
351 Quality
const bridged_quality(
358 Quality
const direct_quality(direct.
tip().
quality());
360 if (bridged_quality < direct_quality)
372 auto const crossings =
377 return crossings >= 850;
390 !
isXRP(takerAmount.in) && !
isXRP(takerAmount.out),
391 "ripple::CreateOffer::bridged_cross : neither is XRP");
393 if (
isXRP(takerAmount.in) ||
isXRP(takerAmount.out))
394 Throw<std::logic_error>(
"Bridging with XRP and an endpoint.");
425 bool have_bridge = offers_leg1.
step() && offers_leg2.
step();
433 while (have_direct || have_bridge)
435 bool leg1_consumed =
false;
436 bool leg2_consumed =
false;
437 bool direct_consumed =
false;
440 have_direct, offers_direct, have_bridge, offers_leg1, offers_leg2);
444 if (taker.
reject(quality))
453 stream << count <<
" Direct:";
454 stream <<
" offer: " << offers_direct.
tip();
455 stream <<
" in: " << offers_direct.
tip().
amount().in;
456 stream <<
" out: " << offers_direct.
tip().
amount().out;
457 stream <<
" owner: " << offers_direct.
tip().
owner();
467 cross_result = taker.
cross(offers_direct.
tip());
473 direct_consumed =
true;
495 stream << count <<
" Bridge:";
496 stream <<
" offer1: " << offers_leg1.
tip();
497 stream <<
" in: " << offers_leg1.
tip().
amount().in;
498 stream <<
" out: " << offers_leg1.
tip().
amount().out;
499 stream <<
" owner: " << offers_leg1.
tip().
owner();
500 stream <<
" funds: " << owner1_funds_before;
501 stream <<
" offer2: " << offers_leg2.
tip();
502 stream <<
" in: " << offers_leg2.
tip().
amount().in;
503 stream <<
" out: " << offers_leg2.
tip().
amount().out;
504 stream <<
" owner: " << offers_leg2.
tip().
owner();
505 stream <<
" funds: " << owner2_funds_before;
508 cross_result = taker.
cross(offers_leg1.
tip(), offers_leg2.
tip());
518 have_bridge &= offers_leg1.
step();
522 have_bridge &= offers_leg2.
step();
530 leg1_consumed =
true;
531 have_bridge = (have_bridge && offers_leg1.
step());
535 leg2_consumed =
true;
536 have_bridge = (have_bridge && offers_leg2.
step());
549 JLOG(
j_.
debug()) <<
"The taker reports he's done during crossing!";
555 JLOG(
j_.
debug()) <<
"The offer crossing limit has been exceeded!";
562 direct_consumed || leg1_consumed || leg2_consumed,
563 "ripple::CreateOffer::bridged_cross : consumed an offer");
565 if (!direct_consumed && !leg1_consumed && !leg2_consumed)
566 Throw<std::logic_error>(
567 "bridged crossing: nothing was fully consumed.");
597 bool direct_consumed =
false;
598 auto& offer(offers.tip());
601 if (taker.
reject(offer.quality()))
608 stream << count <<
" Direct:";
609 stream <<
" offer: " << offer;
610 stream <<
" in: " << offer.amount().in;
611 stream <<
" out: " << offer.amount().out;
612 stream <<
"quality: " << offer.quality();
613 stream <<
" owner: " << offer.owner();
623 cross_result = taker.
cross(offer);
629 direct_consumed =
true;
641 JLOG(
j_.
debug()) <<
"The taker reports he's done during crossing!";
647 JLOG(
j_.
debug()) <<
"The offer crossing limit has been exceeded!";
655 "ripple::CreateOffer::direct_cross : consumed an offer");
657 if (!direct_consumed)
658 Throw<std::logic_error>(
659 "direct crossing: nothing was fully consumed.");
671 while (stream.step())
673 auto const& offer = stream.tip();
676 if (taker.
reject(offer.quality()))
680 if (offer.owner() != taker.
account())
695 Amounts
const& takerAmount)
718 JLOG(
j_.
debug()) <<
"Not crossing: taker is unfunded.";
731 JLOG(
j_.
error()) <<
"Exception during offer crossing: " << e.
what();
740 Amounts
const& takerAmount,
753 if (inStartBalance <= beast::zero)
756 JLOG(
j_.
debug()) <<
"Not crossing: taker is unfunded.";
763 Rate gatewayXferRate{QUALITY_ONE};
768 if (gatewayXferRate.value != QUALITY_ONE)
773 takerAmount.in.issue(),
780 Quality threshold{takerAmount.out, sendMax};
789 if (sendMax > inStartBalance)
790 sendMax = inStartBalance;
797 if (!takerAmount.in.native() && !takerAmount.out.native())
800 path.emplace_back(std::nullopt,
xrpCurrency(), std::nullopt);
820 takerAmount.out.
issue(),
826 auto const result =
flow(
842 for (
auto const& toRemove : result.removableOffers)
851 auto afterCross = takerAmount;
857 if (takerInBalance <= beast::zero)
861 afterCross.in.clear();
862 afterCross.out.clear();
867 Quality{takerAmount.out, takerAmount.in}.rate()};
879 STAmount nonGatewayAmountIn = result.actualAmountIn;
880 if (gatewayXferRate.value != QUALITY_ONE)
882 result.actualAmountIn,
884 takerAmount.in.issue(),
887 afterCross.in -= nonGatewayAmountIn;
891 if (afterCross.in < beast::zero)
894 afterCross.in.
clear();
896 afterCross.out = [&]() {
906 takerAmount.out.issue(),
910 afterCross.in, rate, takerAmount.out.issue(),
true);
918 afterCross.out -= result.actualAmountOut;
920 afterCross.out >= beast::zero,
921 "ripple::CreateOffer::flowCross : minimum offer");
922 if (afterCross.out < beast::zero)
923 afterCross.out.clear();
925 afterCross.out, rate, takerAmount.in.issue(),
true);
935 JLOG(
j_.
error()) <<
"Exception during offer crossing: " << e.
what();
944 Amounts
const& takerAmount,
952 flowCross(psbFlow, psbCancelFlow, takerAmount, domainID);
954 psbCancelFlow.apply(sbCancel);
959 Sandbox sbCancelTaker{&sbCancel};
960 auto const ret =
takerCross(sbTaker, sbCancelTaker, takerAmount);
962 sbCancelTaker.apply(sbCancel);
981 if (pays_xrp && !gets_xrp)
983 else if (gets_xrp && !pays_xrp)
998 if (!sleOffer->isFieldPresent(sfDomainID))
1005 Book const book{saTakerPays.
issue(), saTakerGets.
issue(), std::nullopt};
1009 bool const bookExists = sb.
exists(dir);
1014 setDir(sle, std::nullopt);
1020 <<
"final result: failed to add hybrid offer to open book";
1024 STArray bookArr(sfAdditionalBooks, 1);
1026 bookInfo.setFieldH256(sfBookDirectory, dir.key);
1027 bookInfo.setFieldU64(sfBookNode, *bookNode);
1033 sleOffer->setFieldArray(sfAdditionalBooks, bookArr);
1044 bool const bPassive(uTxFlags &
tfPassive);
1047 bool const bSell(uTxFlags &
tfSell);
1048 bool const bHybrid(uTxFlags &
tfHybrid);
1050 auto saTakerPays =
ctx_.
tx[sfTakerPays];
1051 auto saTakerGets =
ctx_.
tx[sfTakerGets];
1052 auto const domainID =
ctx_.
tx[~sfDomainID];
1054 auto const cancelSequence =
ctx_.
tx[~sfOfferSequence];
1063 auto uRate =
getRate(saTakerGets, saTakerPays);
1072 auto const sleCancel =
1080 JLOG(
j_.
debug()) <<
"Create cancels order " << *cancelSequence;
1085 auto const expiration =
ctx_.
tx[~sfExpiration];
1100 bool const bOpenLedger = sb.
open();
1101 bool crossed =
false;
1106 auto const& uPaysIssuerID = saTakerPays.
getIssuer();
1107 auto const& uGetsIssuerID = saTakerGets.
getIssuer();
1110 if (!
isXRP(uPaysIssuerID))
1113 if (sle && sle->isFieldPresent(sfTickSize))
1114 uTickSize =
std::min(uTickSize, (*sle)[sfTickSize]);
1116 if (!
isXRP(uGetsIssuerID))
1119 if (sle && sle->isFieldPresent(sfTickSize))
1120 uTickSize =
std::min(uTickSize, (*sle)[sfTickSize]);
1122 if (uTickSize < Quality::maxTickSize)
1125 Quality{saTakerGets, saTakerPays}.round(uTickSize).rate();
1133 saTakerPays =
multiply(saTakerGets, rate, saTakerPays.
issue());
1138 saTakerGets =
divide(saTakerPays, rate, saTakerGets.
issue());
1140 if (!saTakerGets || !saTakerPays)
1142 JLOG(
j_.
debug()) <<
"Offer rounded to zero";
1143 return {result,
true};
1146 uRate =
getRate(saTakerGets, saTakerPays);
1150 Amounts
const takerAmount(saTakerGets, saTakerPays);
1155 Amounts place_offer;
1157 JLOG(
j_.
debug()) <<
"Attempting cross: "
1158 <<
to_string(takerAmount.in.issue()) <<
" -> "
1163 stream <<
" mode: " << (bPassive ?
"passive " :
"")
1164 << (bSell ?
"sell" :
"buy");
1170 cross(sb, sbCancel, takerAmount, domainID);
1176 "ripple::CreateOffer::applyGuts : result is tesSUCCESS or "
1181 stream <<
"Cross result: " <<
transToken(result);
1192 return {result,
true};
1196 saTakerGets.
issue() == place_offer.in.issue(),
1197 "ripple::CreateOffer::applyGuts : taker gets issue match");
1199 saTakerPays.
issue() == place_offer.out.issue(),
1200 "ripple::CreateOffer::applyGuts : taker pays issue match");
1202 if (takerAmount != place_offer)
1207 if (place_offer.in < zero || place_offer.out < zero)
1209 JLOG(
j_.
fatal()) <<
"Cross left offer negative!"
1215 if (place_offer.in == zero || place_offer.out == zero)
1217 JLOG(
j_.
debug()) <<
"Offer fully crossed!";
1218 return {result,
true};
1224 saTakerPays = place_offer.out;
1225 saTakerGets = place_offer.in;
1229 saTakerPays > zero && saTakerGets > zero,
1230 "ripple::CreateOffer::applyGuts : taker pays and gets positive");
1235 return {result,
true};
1240 stream <<
"Place" << (crossed ?
" remaining " :
" ") <<
"offer:";
1249 JLOG(
j_.
trace()) <<
"Fill or Kill: offer killed";
1257 if (bImmediateOrCancel)
1259 JLOG(
j_.
trace()) <<
"Immediate or cancel: offer canceled";
1260 if (!crossed && sb.
rules().
enabled(featureImmediateOfferKilled))
1290 return {result,
true};
1304 <<
"final result: failed to add offer to owner's directory";
1313 << (domainID ? (
" : " +
to_string(*domainID)) :
"");
1315 Book const book{saTakerPays.
issue(), saTakerGets.
issue(), domainID};
1329 bool const bookExisted =
static_cast<bool>(sb.
peek(dir));
1331 auto setBookDir = [&](
SLE::ref sle,
1333 sle->setFieldH160(sfTakerPaysCurrency, saTakerPays.
issue().
currency);
1334 sle->setFieldH160(sfTakerPaysIssuer, saTakerPays.
issue().
account);
1335 sle->setFieldH160(sfTakerGetsCurrency, saTakerGets.
issue().
currency);
1336 sle->setFieldH160(sfTakerGetsIssuer, saTakerGets.
issue().
account);
1337 sle->setFieldU64(sfExchangeRate, uRate);
1339 sle->setFieldH256(sfDomainID, *maybeDomain);
1344 setBookDir(sle, domainID);
1349 JLOG(
j_.
debug()) <<
"final result: failed to add offer to book";
1353 auto sleOffer = std::make_shared<SLE>(offer_index);
1354 sleOffer->setAccountID(sfAccount,
account_);
1355 sleOffer->setFieldU32(sfSequence, offerSequence);
1356 sleOffer->setFieldH256(sfBookDirectory, dir.key);
1357 sleOffer->setFieldAmount(sfTakerPays, saTakerPays);
1358 sleOffer->setFieldAmount(sfTakerGets, saTakerGets);
1359 sleOffer->setFieldU64(sfOwnerNode, *ownerNode);
1360 sleOffer->setFieldU64(sfBookNode, *bookNode);
1362 sleOffer->setFieldU32(sfExpiration, *expiration);
1368 sleOffer->setFieldH256(sfDomainID, *domainID);
1374 sb, sleOffer, offer_index, saTakerPays, saTakerGets, setBookDir);
1384 JLOG(
j_.
debug()) <<
"final result: success";
1401 auto const result =
applyGuts(sb, sbCancel);
1406 return result.first;
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
Wraps a Journal::Sink to prefix its output with a string.
virtual beast::Journal journal(std::string const &name)=0
virtual OrderBookDB & getOrderBookDB()=0
Writeable view to a ledger, for applying a transaction.
std::optional< std::uint64_t > dirAppend(Keylet const &directory, Keylet const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Append an entry to a directory.
std::optional< std::uint64_t > dirInsert(Keylet const &directory, uint256 const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Insert an entry to a directory.
bool done() const
Returns true if order crossing should not continue.
AccountID const & account() const noexcept
Returns the account identifier of the taker.
bool reject(Quality const &quality) const noexcept
Returns true if the quality does not meet the taker's requirements.
Issue const & issue_in() const
Returns the Issue associated with the input of the offer.
Amounts remaining_offer() const
Returns the amount remaining on the offer.
Amounts const & original_offer() const
Returns the amount that the offer was originally placed at.
Issue const & issue_out() const
Returns the Issue associated with the output of the offer.
bool unfunded() const
Returns true if the taker has run out of funds.
std::pair< TER, Amounts > flowCross(PaymentSandbox &psb, PaymentSandbox &psbCancel, Amounts const &takerAmount, std::optional< uint256 > const &domainID)
std::pair< TER, Amounts > bridged_cross(Taker &taker, ApplyView &view, ApplyView &view_cancel, NetClock::time_point const when)
OfferStream::StepCounter stepCounter_
static TER checkAcceptAsset(ReadView const &view, ApplyFlags const flags, AccountID const id, beast::Journal const j, Issue const &issue)
void preCompute() override
Gather information beyond what the Transactor base class gathers.
bool dry_offer(ApplyView &view, Offer const &offer)
static TER preclaim(PreclaimContext const &ctx)
Enforce constraints beyond those of the Transactor base class.
static bool step_account(OfferStream &stream, Taker const &taker)
static std::string format_amount(STAmount const &amount)
bool reachedOfferCrossingLimit(Taker const &taker) const
std::pair< TER, Amounts > takerCross(Sandbox &sb, Sandbox &sbCancel, Amounts const &takerAmount)
std::pair< TER, Amounts > direct_cross(Taker &taker, ApplyView &view, ApplyView &view_cancel, NetClock::time_point const when)
static NotTEC preflight(PreflightContext const &ctx)
Enforce constraints beyond those of the Transactor base class.
static TxConsequences makeTxConsequences(PreflightContext const &ctx)
TER applyHybrid(Sandbox &sb, std::shared_ptr< STLedgerEntry > sleOffer, Keylet const &offer_index, STAmount const &saTakerPays, STAmount const &saTakerGets, std::function< void(SLE::ref, std::optional< uint256 >)> const &setDir)
TER doApply() override
Precondition: fee collection is likely.
std::pair< TER, bool > applyGuts(Sandbox &view, Sandbox &view_cancel)
static std::pair< bool, Quality > select_path(bool have_direct, OfferStream const &direct, bool have_bridge, OfferStream const &leg1, OfferStream const &leg2)
std::pair< TER, Amounts > cross(Sandbox &sb, Sandbox &sbCancel, Amounts const &takerAmount, std::optional< uint256 > const &domainID)
A currency issued by an account.
Presents and consumes the offers in an order book.
void addOrderBook(Book const &)
A wrapper which makes credits unavailable to balances.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
NetClock::time_point parentCloseTime() const
Returns the close time of the previous ledger.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
static int const cMaxOffset
Currency const & getCurrency() const
static std::uint64_t const cMaxValue
std::string getText() const override
AccountID const & getIssuer() const
Issue const & issue() const
static std::uint64_t const cMaxNative
std::string getFullText() const override
bool native() const noexcept
void push_back(STObject const &object)
STAmount const & getFieldAmount(SField const &field) const
bool isFieldPresent(SField const &field) const
static STObject makeInnerObject(SField const &name)
std::uint32_t getFlags() const
void emplace_back(Args &&... args)
std::uint32_t getSeqValue() const
Returns the first non-zero value of (Sequence, TicketSequence).
Discardable, editable view to a ledger.
bool step()
Advance to the next valid offer.
TOffer< TIn, TOut > & tip() const
Returns the offer at the tip of the order book.
Quality quality() const noexcept
Returns the quality of the offer.
AccountID const & owner() const
Returns the account id of the offer's owner.
TAmounts< TIn, TOut > const & amount() const
Returns the in and out amounts.
std::uint32_t get_bridge_crossings() const
std::uint32_t get_direct_crossings() const
TER cross(Offer &offer)
Perform a direct or bridged offer crossing as appropriate.
virtual void preCompute()
Class describing the consequences to the account of applying a transaction if the transaction consume...
Fees const & fees() const override
Returns the fees for the base ledger.
bool open() const override
Returns true if this reflects an open ledger.
void insert(std::shared_ptr< SLE > const &sle) override
Insert a new state SLE.
bool exists(Keylet const &k) const override
Determine if a state item exists.
std::shared_ptr< SLE const > read(Keylet const &k) const override
Return the state item associated with a key.
Rules const & rules() const override
Returns the tx processing rules.
std::shared_ptr< SLE > peek(Keylet const &k) override
Prepare to modify the SLE associated with key.
Keylet quality(Keylet const &k, std::uint64_t q) noexcept
The initial directory page for a specific quality.
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
bool accountInDomain(ReadView const &view, AccountID const &account, Domain const &domainID)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
STAmount divide(STAmount const &amount, Rate const &rate)
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
bool isXRP(AccountID const &c)
constexpr std::uint32_t tfOfferCreateMask
STAmount divRoundStrict(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
bool isLegalNet(STAmount const &value)
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
constexpr std::uint32_t tfHybrid
STAmount multiply(STAmount const &amount, Rate const &rate)
std::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
constexpr std::uint32_t tfFillOrKill
NotTEC preflight1(PreflightContext const &ctx)
Performs early sanity checks on the account and fee fields.
STAmount divideRound(STAmount const &amount, Rate const &rate, bool roundUp)
StrandResult< TInAmt, TOutAmt > flow(PaymentSandbox const &baseView, Strand const &strand, std::optional< TInAmt > const &maxIn, TOutAmt const &out, beast::Journal j)
Request out amount from a strand.
constexpr std::uint32_t tfPassive
constexpr std::uint32_t tfImmediateOrCancel
TER offerDelete(ApplyView &view, std::shared_ptr< SLE > const &sle, beast::Journal j)
Delete an offer.
std::uint64_t getRate(STAmount const &offerOut, STAmount const &offerIn)
Quality composed_quality(Quality const &lhs, Quality const &rhs)
static bool adjustOwnerCount(ApplyContext &ctx, int count)
std::string transToken(TER code)
NotTEC preflight2(PreflightContext const &ctx)
Checks whether the signature appears valid.
Currency const & xrpCurrency()
XRP currency.
bool isTesSuccess(TER x) noexcept
STAmount divRound(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
std::string to_string(base_uint< Bits, Tag > const &a)
STAmount mulRound(STAmount const &v1, STAmount const &v2, Asset const &asset, bool roundUp)
STAmount multiplyRound(STAmount const &amount, Rate const &rate, bool roundUp)
constexpr std::uint32_t tfSell
bool hasExpired(ReadView const &view, std::optional< std::uint32_t > const &exp)
Determines whether the given expiration time has passed.
bool isTecClaim(TER x) noexcept
bool isGlobalFrozen(ReadView const &view, AccountID const &issuer)
XRPAmount accountReserve(std::size_t ownerCount) const
Returns the account reserve given the owner count, in drops.
A pair of SHAMap key and LedgerEntryType.
State information when determining if a tx is likely to claim a fee.
State information when preflighting a tx.
Represents a transfer rate.