TER Taker::cross (Offer const& offer) { assert (!done ()); /* Before we call flow we must set the limit right; for buy semantics we need to clamp the output. And we always want to clamp the input. */ Amounts limit (offer.amount()); if (! m_options.sell) limit = offer.quality ().ceil_out (limit, m_remain.out); limit = offer.quality().ceil_in (limit, m_remain.in); assert (limit.in <= offer.amount().in); assert (limit.out <= offer.amount().out); assert (limit.in <= m_remain.in); Amounts const amount (flow (limit, offer, account ())); m_remain.out -= amount.out; m_remain.in -= amount.in; assert (m_remain.in >= zero); return fill (offer, amount); }
TER Taker::cross (Offer const& offer) { // In direct crossings, at least one leg must not be XRP. if (isXRP (offer.amount ().in) && isXRP (offer.amount ().out)) return tefINTERNAL; auto const amount = do_cross ( offer.amount (), offer.quality (), offer.owner ()); return fill (amount, offer); }
TER Taker::cross (Offer const& leg1, Offer const& leg2) { // In bridged crossings, XRP must can't be the input to the first leg // or the output of the second leg. if (isXRP (leg1.amount ().in) || isXRP (leg2.amount ().out)) return tefINTERNAL; auto ret = do_cross ( leg1.amount (), leg1.quality (), leg1.owner (), leg2.amount (), leg2.quality (), leg2.owner ()); return fill (ret.first, leg1, ret.second, leg2); }
TER Taker::cross (Offer const& offer) { assert (!done ()); Amounts limit (offer.amount()); if (m_options.sell) limit = offer.quality().ceil_in (limit, m_remain.in); else limit = offer.quality ().ceil_out (limit, m_remain.out); assert (limit.out <= offer.amount().out); assert (limit.in <= offer.amount().in); Amounts const amount (flow (limit, offer, account ())); m_remain.out -= amount.out; m_remain.in -= amount.in; assert (m_remain.in >= zero); return fill (offer, amount); }
TER Taker::cross (Offer const& leg1, Offer const& leg2) { assert (!done ()); assert (leg1.amount ().out.isNative ()); assert (leg2.amount ().in.isNative ()); Amounts amount1 (leg1.amount()); Amounts amount2 (leg2.amount()); if (m_options.sell) amount1 = leg1.quality().ceil_in (amount1, m_remain.in); else amount2 = leg2.quality().ceil_out (amount2, m_remain.out); if (amount1.out <= amount2.in) amount2 = leg2.quality().ceil_in (amount2, amount1.out); else amount1 = leg1.quality().ceil_out (amount1, amount2.in); assert (amount1.out == amount2.in); // As written, flow can't handle a 3-party transfer, but this works for // us because the output of leg1 and the input leg2 are XRP. Amounts flow1 (flow (amount1, leg1, m_account)); amount2 = leg2.quality().ceil_in (amount2, flow1.out); Amounts flow2 (flow (amount2, leg2, m_account)); m_remain.out -= amount2.out; m_remain.in -= amount1.in; return fill (leg1, flow1, leg2, flow2); }
// Adjust an offer to indicate that we are consuming some (or all) of it. void Taker::consume (Offer const& offer, Amounts const& consumed) const { Amounts const& remaining (offer.amount ()); assert (remaining.in > zero && remaining.out > zero); assert (remaining.in >= consumed.in && remaining.out >= consumed.out); offer.entry ()->setFieldAmount (sfTakerPays, remaining.in - consumed.in); offer.entry ()->setFieldAmount (sfTakerGets, remaining.out - consumed.out); view ().entryModify (offer.entry()); assert (offer.entry ()->getFieldAmount (sfTakerPays) >= zero); assert (offer.entry ()->getFieldAmount (sfTakerGets) >= zero); }
void Taker::consume_offer (Offer const& offer, Amounts const& order) { if (order.in < zero) Throw<std::logic_error> ("flow with negative input."); if (order.out < zero) Throw<std::logic_error> ("flow with negative output."); if (journal_.debug) journal_.debug << "Consuming from offer " << offer; if (journal_.trace) { auto const& available = offer.amount (); journal_.trace << " in:" << format_amount (available.in); journal_.trace << " out:" << format_amount(available.out); } offer.consume (view_, order); }