20#include <xrpld/app/tx/detail/Taker.h>
21#include <xrpl/basics/Log.h>
22#include <xrpl/basics/contract.h>
38 Amounts
const& amount,
39 Quality
const& quality,
46 , threshold_(quality_)
50 , issue_in_(remaining_.
in.issue())
51 , issue_out_(remaining_.
out.issue())
53 , m_rate_out(rate_out)
54 , cross_type_(cross_type)
59 "ripple::BasicTaker::BasicTaker : positive remaining in");
62 "ripple::BasicTaker::BasicTaker : positive remaining out");
65 m_rate_in.
value,
"ripple::BasicTaker::BasicTaker : nonzero rate in");
74 "ripple::BasicTaker::BasicTaker : valid cross to IOU");
79 "ripple::BasicTaker::BasicTaker : valid cross to XRP");
84 "ripple::BasicTaker::BasicTaker : not crossing XRP for XRP");
117 JLOG(
journal_.
debug()) <<
"Unfunded: taker is out of funds.";
128 <<
"Done: all the input currency has been consumed.";
136 JLOG(
journal_.
debug()) <<
"Done: the desired amount has been received.";
165 "ripple::BasicTaker::remaining_offer : positive remaining in");
175 "ripple::BasicTaker::remaining_offer : positive remaining out");
194 auto result =
divide(amount, quality.rate(), output.
issue());
201 auto result =
multiply(amount, quality.rate(), output.
issue());
212 stream << description;
229 Amounts
const& order,
233 Rate const& rate_out)
242 if (owner_funds < f.
issuers.out)
247 log_flow(
"(clamped on owner balance)", f);
256 log_flow(
"(clamped on taker output)", f);
260 if (taker_funds < f.
order.in)
262 f.
order.in = taker_funds;
265 log_flow(
"(clamped on taker funds)", f);
275 log_flow(
"(clamped on taker input)", f);
283 Amounts
const& order,
296 if (owner_funds < f.
order.out)
298 f.
order.out = owner_funds;
301 log_flow(
"(clamped on owner funds)", f);
313 log_flow(
"(clamped on taker output)", f);
323 log_flow(
"(clamped on taker input)", f);
327 if (taker_funds < f.
issuers.in)
332 log_flow(
"(clamped on taker funds)", f);
340 Amounts
const& order,
345 Rate const& rate_out)
355 if (owner_funds < f.
issuers.out)
361 log_flow(
"(clamped on owner funds)", f);
371 log_flow(
"(clamped on taker output)", f);
381 log_flow(
"(clamped on taker input)", f);
385 if (taker_funds < f.
issuers.in)
391 log_flow(
"(clamped on taker funds)", f);
401 auto const owner_funds =
get_funds(owner, offer.out);
436 Throw<std::logic_error>(
"Computed flow fails sanity check.");
443 "ripple::BasicTaker::do_cross : minimum remaining in");
460 "ripple::BasicTaker::do_cross : offer1 in is not XRP");
463 "ripple::BasicTaker::do_cross : offer1 out is XRP");
465 offer2.in.native(),
"ripple::BasicTaker::do_cross : offer2 in is XRP");
467 !offer2.out.native(),
468 "ripple::BasicTaker::do_cross : offer2 out is not XRP");
476 JLOG(
journal_.
trace()) <<
"The taker owns the first leg of a bridge.";
477 leg1_in_funds =
std::max(leg1_in_funds, offer1.in);
482 auto leg2_out_funds =
get_funds(owner2, offer2.out);
486 JLOG(
journal_.
trace()) <<
"The taker owns the second leg of a bridge.";
487 leg2_out_funds =
std::max(leg2_out_funds, offer2.out);
498 auto xrp_funds =
get_funds(owner1, offer1.out);
500 if (owner1 == owner2)
503 <<
"The bridge endpoints are owned by the same account.";
504 xrp_funds =
std::max(offer1.out, offer2.in);
509 stream <<
"Available bridge funds:";
521 flow_iou_to_xrp(offer1, quality1, xrp_funds, leg1_in_funds, leg1_rate);
523 if (!flow1.sanity_check())
524 Throw<std::logic_error>(
"Computed flow1 fails sanity check.");
527 flow_xrp_to_iou(offer2, quality2, leg2_out_funds, xrp_funds, leg2_rate);
529 if (!flow2.sanity_check())
530 Throw<std::logic_error>(
"Computed flow2 fails sanity check.");
536 if (flow1.order.out < flow2.order.in)
539 flow2.order.in = flow1.order.out;
540 flow2.order.out =
qual_div(flow2.order.in, quality2, flow2.order.out);
541 flow2.issuers.out =
multiply(flow2.order.out, leg2_rate);
542 log_flow(
"Balancing: adjusted second leg down", flow2);
544 else if (flow1.order.out > flow2.order.in)
547 flow1.order.out = flow2.order.in;
548 flow1.order.in =
qual_mul(flow1.order.out, quality1, flow1.order.in);
549 flow1.issuers.in =
multiply(flow1.order.in, leg1_rate);
550 log_flow(
"Balancing: adjusted first leg down", flow2);
553 if (flow1.order.out != flow2.order.in)
554 Throw<std::logic_error>(
"Bridged flow is out of balance.");
568 Amounts
const& offer,
577 calculateRate(view, offer.
in.getIssuer(), account),
578 calculateRate(view, offer.
out.getIssuer(), account),
582 , direct_crossings_(0)
583 , bridge_crossings_(0)
587 "ripple::Taker::Taker : issue in is a match");
590 "ripple::Taker::Taker : issue out is a match");
608 stream <<
" Balance: "
616 if (order.in < beast::zero)
617 Throw<std::logic_error>(
"flow with negative input.");
619 if (order.out < beast::zero)
620 Throw<std::logic_error>(
"flow with negative output.");
632 offer.consume(
view_, order);
648 Throw<std::logic_error>(
"Using transferXRP with IOU");
654 if (amount == beast::zero)
667 Throw<std::logic_error>(
"Using redeemIOU with XRP");
673 if (amount == beast::zero)
679 Throw<std::logic_error>(
"redeemIOU has no funds to redeem");
684 Throw<std::logic_error>(
"redeemIOU redeemed more funds than available");
696 Throw<std::logic_error>(
"Using issueIOU with XRP");
702 if (amount == beast::zero)
720 !
isXRP(
flow.order.in),
"ripple::Taker::fill : order in is not XRP");
733 isXRP(
flow.order.in),
"ripple::Taker::fill : order in is XRP");
744 "ripple::Taker::fill : order out is not XRP");
748 offer.owner(),
flow.issuers.out,
flow.issuers.out.issue());
757 isXRP(
flow.order.out),
"ripple::Taker::fill : order out is XRP");
824 if (
isXRP(offer.amount().in) &&
isXRP(offer.amount().out))
828 do_cross(offer.amount(), offer.quality(), offer.owner());
830 return fill(amount, offer);
849 return fill(ret.first, leg1, ret.second, leg2);
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
Writeable view to a ledger, for applying a transaction.
State for the active party during order book or payment operations.
Flow flow_iou_to_iou(Amounts const &offer, Quality quality, STAmount const &owner_funds, STAmount const &taker_funds, Rate const &rate_in, Rate const &rate_out)
bool done() const
Returns true if order crossing should not continue.
Rate in_rate(AccountID const &from, AccountID const &to) const
Flow flow_iou_to_xrp(Amounts const &offer, Quality quality, STAmount const &owner_funds, STAmount const &taker_funds, Rate const &rate_in)
Flow flow_xrp_to_iou(Amounts const &offer, Quality quality, STAmount const &owner_funds, STAmount const &taker_funds, Rate const &rate_out)
beast::Journal const journal_
CrossType cross_type() const
Returns the type of crossing that is being performed.
AccountID const & account() const noexcept
Returns the account identifier of the taker.
void log_flow(char const *description, Flow const &flow)
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.
Rate out_rate(AccountID const &from, AccountID const &to) const
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.
virtual STAmount get_funds(AccountID const &account, STAmount const &funds) const =0
static Rate effective_rate(Rate const &rate, Issue const &issue, AccountID const &from, AccountID const &to)
BasicTaker::Flow do_cross(Amounts offer, Quality quality, AccountID const &owner)
Perform direct crossing through given offer.
bool unfunded() const
Returns true if the taker has run out of funds.
A currency issued by an account.
std::string getText() const override
Issue const & issue() const
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.
STAmount get_funds(AccountID const &account, STAmount const &funds) const override
TER issueIOU(AccountID const &account, STAmount const &amount, Issue const &issue)
static Rate calculateRate(ApplyView const &view, AccountID const &issuer, AccountID const &account)
std::uint32_t direct_crossings_
TER redeemIOU(AccountID const &account, STAmount const &amount, Issue const &issue)
std::uint32_t bridge_crossings_
TER fill(BasicTaker::Flow const &flow, Offer &offer)
TER transferXRP(AccountID const &from, AccountID const &to, STAmount const &amount)
void consume_offer(Offer &offer, Amounts const &order)
TER cross(Offer &offer)
Perform a direct or bridged offer crossing as appropriate.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
STAmount divide(STAmount const &amount, Rate const &rate)
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
bool isXRP(AccountID const &c)
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
TER redeemIOU(ApplyView &view, AccountID const &account, STAmount const &amount, Issue const &issue, beast::Journal j)
STAmount multiply(STAmount const &amount, Rate const &rate)
TER transferXRP(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &amount, beast::Journal j)
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
static STAmount qual_mul(STAmount const &amount, Quality const &quality, STAmount const &output)
TER issueIOU(ApplyView &view, AccountID const &account, STAmount const &amount, Issue const &issue, beast::Journal j)
static std::string format_amount(STAmount const &amount)
static STAmount qual_div(STAmount const &amount, Quality const &quality, STAmount const &output)
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)
constexpr std::uint32_t tfSell
CrossType
The flavor of an offer crossing.
Rate const parityRate
A transfer rate signifying a 1:1 exchange.
bool sanity_check() const
Represents a transfer rate.