path::RippleCalc::Output flow ( PaymentSandbox& sb, STAmount const& deliver, AccountID const& src, AccountID const& dst, STPathSet const& paths, bool defaultPaths, bool partialPayment, bool ownerPaysTransferFee, boost::optional<Quality> const& limitQuality, boost::optional<STAmount> const& sendMax, beast::Journal j, path::detail::FlowDebugInfo* flowDebugInfo) { Issue const srcIssue = [&] { if (sendMax) return sendMax->issue (); if (!isXRP (deliver.issue ().currency)) return Issue (deliver.issue ().currency, src); return xrpIssue (); }(); Issue const dstIssue = deliver.issue (); boost::optional<Issue> sendMaxIssue; if (sendMax) sendMaxIssue = sendMax->issue (); // convert the paths to a collection of strands. Each strand is the collection // of account->account steps and book steps that may be used in this payment. auto sr = toStrands (sb, src, dst, dstIssue, sendMaxIssue, paths, defaultPaths, ownerPaysTransferFee, j); if (sr.first != tesSUCCESS) { path::RippleCalc::Output result; result.setResult (sr.first); return result; } auto& strands = sr.second; if (j.trace()) { j.trace() << "\nsrc: " << src << "\ndst: " << dst << "\nsrcIssue: " << srcIssue << "\ndstIssue: " << dstIssue; j.trace() << "\nNumStrands: " << strands.size (); for (auto const& curStrand : strands) { j.trace() << "NumSteps: " << curStrand.size (); for (auto const& step : curStrand) { j.trace() << '\n' << *step << '\n'; } } } const bool srcIsXRP = isXRP (srcIssue.currency); const bool dstIsXRP = isXRP (dstIssue.currency); auto const asDeliver = toAmountSpec (deliver); // The src account may send either xrp or iou. The dst account may receive // either xrp or iou. Since XRP and IOU amounts are represented by different // types, use templates to tell `flow` about the amount types. if (srcIsXRP && dstIsXRP) { return finishFlow (sb, srcIssue, dstIssue, flow<XRPAmount, XRPAmount> ( sb, strands, asDeliver.xrp, defaultPaths, partialPayment, limitQuality, sendMax, j, flowDebugInfo)); } if (srcIsXRP && !dstIsXRP) { return finishFlow (sb, srcIssue, dstIssue, flow<XRPAmount, IOUAmount> ( sb, strands, asDeliver.iou, defaultPaths, partialPayment, limitQuality, sendMax, j, flowDebugInfo)); } if (!srcIsXRP && dstIsXRP) { return finishFlow (sb, srcIssue, dstIssue, flow<IOUAmount, XRPAmount> ( sb, strands, asDeliver.xrp, defaultPaths, partialPayment, limitQuality, sendMax, j, flowDebugInfo)); } assert (!srcIsXRP && !dstIsXRP); return finishFlow (sb, srcIssue, dstIssue, flow<IOUAmount, IOUAmount> ( sb, strands, asDeliver.iou, defaultPaths, partialPayment, limitQuality, sendMax, j, flowDebugInfo)); }