20 #include <ripple/app/tx/impl/Taker.h>
21 #include <ripple/basics/Log.h>
22 #include <ripple/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)
107 JLOG(
journal_.
debug()) <<
"Unfunded: taker is out of funds.";
118 <<
"Done: all the input currency has been consumed.";
126 JLOG(
journal_.
debug()) <<
"Done: the desired amount has been received.";
180 auto result =
divide(amount, quality.rate(), output.
issue());
187 auto result =
multiply(amount, quality.rate(), output.
issue());
198 stream << description;
215 Amounts
const& order,
219 Rate const& rate_out)
228 if (owner_funds < f.
issuers.out)
233 log_flow(
"(clamped on owner balance)", f);
242 log_flow(
"(clamped on taker output)", f);
246 if (taker_funds < f.
order.in)
248 f.
order.in = taker_funds;
251 log_flow(
"(clamped on taker funds)", f);
261 log_flow(
"(clamped on taker input)", f);
269 Amounts
const& order,
282 if (owner_funds < f.
order.out)
284 f.
order.out = owner_funds;
287 log_flow(
"(clamped on owner funds)", f);
299 log_flow(
"(clamped on taker output)", f);
309 log_flow(
"(clamped on taker input)", f);
313 if (taker_funds < f.
issuers.in)
318 log_flow(
"(clamped on taker funds)", f);
326 Amounts
const& order,
331 Rate const& rate_out)
341 if (owner_funds < f.
issuers.out)
347 log_flow(
"(clamped on owner funds)", f);
357 log_flow(
"(clamped on taker output)", f);
367 log_flow(
"(clamped on taker input)", f);
371 if (taker_funds < f.
issuers.in)
377 log_flow(
"(clamped on taker funds)", f);
387 auto const owner_funds =
get_funds(owner, offer.out);
422 Throw<std::logic_error>(
"Computed flow fails sanity check.");
442 assert(!offer1.in.native());
443 assert(offer1.out.native());
444 assert(offer2.in.native());
445 assert(!offer2.out.native());
453 JLOG(
journal_.
trace()) <<
"The taker owns the first leg of a bridge.";
454 leg1_in_funds =
std::max(leg1_in_funds, offer1.in);
459 auto leg2_out_funds =
get_funds(owner2, offer2.out);
463 JLOG(
journal_.
trace()) <<
"The taker owns the second leg of a bridge.";
464 leg2_out_funds =
std::max(leg2_out_funds, offer2.out);
475 auto xrp_funds =
get_funds(owner1, offer1.out);
477 if (owner1 == owner2)
480 <<
"The bridge endpoints are owned by the same account.";
481 xrp_funds =
std::max(offer1.out, offer2.in);
486 stream <<
"Available bridge funds:";
498 flow_iou_to_xrp(offer1, quality1, xrp_funds, leg1_in_funds, leg1_rate);
500 if (!flow1.sanity_check())
501 Throw<std::logic_error>(
"Computed flow1 fails sanity check.");
504 flow_xrp_to_iou(offer2, quality2, leg2_out_funds, xrp_funds, leg2_rate);
506 if (!flow2.sanity_check())
507 Throw<std::logic_error>(
"Computed flow2 fails sanity check.");
513 if (flow1.order.out < flow2.order.in)
516 flow2.order.in = flow1.order.out;
517 flow2.order.out =
qual_div(flow2.order.in, quality2, flow2.order.out);
518 flow2.issuers.out =
multiply(flow2.order.out, leg2_rate);
519 log_flow(
"Balancing: adjusted second leg down", flow2);
521 else if (flow1.order.out > flow2.order.in)
524 flow1.order.out = flow2.order.in;
525 flow1.order.in =
qual_mul(flow1.order.out, quality1, flow1.order.in);
526 flow1.issuers.in =
multiply(flow1.order.in, leg1_rate);
527 log_flow(
"Balancing: adjusted first leg down", flow2);
530 if (flow1.order.out != flow2.order.in)
531 Throw<std::logic_error>(
"Bridged flow is out of balance.");
545 Amounts
const& offer,
554 calculateRate(view, offer.
in.getIssuer(), account),
555 calculateRate(view, offer.
out.getIssuer(), account),
559 , direct_crossings_(0)
560 , bridge_crossings_(0)
562 assert(
issue_in() == offer.in.issue());
563 assert(
issue_out() == offer.out.issue());
581 stream <<
" Balance: "
589 if (order.in < beast::zero)
590 Throw<std::logic_error>(
"flow with negative input.");
592 if (order.out < beast::zero)
593 Throw<std::logic_error>(
"flow with negative output.");
605 offer.consume(
view_, order);
621 Throw<std::logic_error>(
"Using transferXRP with IOU");
627 if (amount == beast::zero)
640 Throw<std::logic_error>(
"Using redeemIOU with XRP");
646 if (amount == beast::zero)
652 Throw<std::logic_error>(
"redeemIOU has no funds to redeem");
657 Throw<std::logic_error>(
"redeemIOU redeemed more funds than available");
669 Throw<std::logic_error>(
"Using issueIOU with XRP");
675 if (amount == beast::zero)
717 offer.owner(),
flow.issuers.out,
flow.issuers.out.issue());
792 if (
isXRP(offer.amount().in) &&
isXRP(offer.amount().out))
796 do_cross(offer.amount(), offer.quality(), offer.owner());
798 return fill(amount, offer);
817 return fill(ret.first, leg1, ret.second, leg2);
STAmount get_funds(AccountID const &account, STAmount const &funds) const override
Rate transferRate(ReadView const &view, AccountID const &issuer)
A currency issued by an account.
Represents a transfer rate.
TER fill(BasicTaker::Flow const &flow, Offer &offer)
Stream trace() const
Severity stream access functions.
Issue const & issue() const
bool unfunded() const
Returns true if the taker has run out of funds.
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)
static STAmount qual_div(STAmount const &amount, Quality const &quality, STAmount const &output)
BasicTaker::Flow do_cross(Amounts offer, Quality quality, AccountID const &owner)
Perform direct crossing through given offer.
static STAmount qual_mul(STAmount const &amount, Quality const &quality, STAmount const &output)
Amounts remaining_offer() const
Returns the amount remaining on the offer.
Rate in_rate(AccountID const &from, AccountID const &to) const
std::string getText() const override
std::uint32_t direct_crossings_
void log_flow(char const *description, Flow const &flow)
static std::string format_amount(STAmount const &amount)
Issue const & issue_in() const
Returns the Issue associated with the input of the offer.
Flow flow_xrp_to_iou(Amounts const &offer, Quality quality, STAmount const &owner_funds, STAmount const &taker_funds, Rate const &rate_out)
State for the active party during order book or payment operations.
constexpr std::uint32_t tfPassive
CrossType cross_type() const
Returns the type of crossing that is being performed.
const beast::Journal journal_
const Rate parityRate(QUALITY_ONE)
A transfer rate signifying a 1:1 exchange.
Writeable view to a ledger, for applying a transaction.
TER redeemIOU(AccountID const &account, STAmount const &amount, Issue const &issue)
STAmount mulRound(STAmount const &v1, STAmount const &v2, Issue const &issue, bool roundUp)
const Quality quality() const noexcept
Returns the quality of the offer.
TAmounts< TIn, TOut > const & amount() const
Returns the in and out amounts.
Flow flow_iou_to_xrp(Amounts const &offer, Quality quality, STAmount const &owner_funds, STAmount const &taker_funds, Rate const &rate_in)
static Rate calculateRate(ApplyView const &view, AccountID const &issuer, AccountID const &account)
STAmount divide(STAmount const &amount, Rate const &rate)
Issue const & issue_out() const
Returns the Issue associated with the output of the offer.
path::RippleCalc::Output flow(PaymentSandbox &view, STAmount const &deliver, AccountID const &src, AccountID const &dst, STPathSet const &paths, bool defaultPaths, bool partialPayment, bool ownerPaysTransferFee, bool offerCrossing, std::optional< Quality > const &limitQuality, std::optional< STAmount > const &sendMax, beast::Journal j, path::detail::FlowDebugInfo *flowDebugInfo=nullptr)
Make a payment from the src account to the dst account.
CrossType
The flavor of an offer crossing.
STAmount divRound(STAmount const &num, STAmount const &den, Issue const &issue, bool roundUp)
TER issueIOU(AccountID const &account, STAmount const &amount, Issue const &issue)
AccountID const & owner() const
Returns the account id of the offer's owner.
Amounts const & original_offer() const
Returns the amount that the offer was originally placed at.
bool isXRP(AccountID const &c)
void consume_offer(Offer &offer, Amounts const &order)
A generic endpoint for log messages.
std::uint32_t bridge_crossings_
bool sanity_check() const
static Rate effective_rate(Rate const &rate, Issue const &issue, AccountID const &from, AccountID const &to)
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
TER transferXRP(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &amount, beast::Journal j)
STAmount multiply(STAmount const &amount, Rate const &rate)
virtual STAmount get_funds(AccountID const &account, STAmount const &funds) const =0
TER issueIOU(ApplyView &view, AccountID const &account, STAmount const &amount, Issue const &issue, beast::Journal j)
bool done() const
Returns true if order crossing should not continue.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
constexpr std::uint32_t tfSell
TER redeemIOU(ApplyView &view, AccountID const &account, STAmount const &amount, Issue const &issue, beast::Journal j)
TER transferXRP(AccountID const &from, AccountID const &to, STAmount const &amount)
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
AccountID const & account() const noexcept
Returns the account identifier of the taker.
TER cross(Offer &offer)
Perform a direct or bridged offer crossing as appropriate.
Rate out_rate(AccountID const &from, AccountID const &to) const