本文整理汇总了C++中STAmount::issue方法的典型用法代码示例。如果您正苦于以下问题:C++ STAmount::issue方法的具体用法?C++ STAmount::issue怎么用?C++ STAmount::issue使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类STAmount
的用法示例。
在下文中一共展示了STAmount::issue方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: min
static
STAmount
qual_mul (STAmount const& amount, Quality const& quality, STAmount const& output)
{
auto result = multiply (amount, quality.rate (), output.issue ());
return std::min (result, output);
}
示例2:
std::string
format_amount (STAmount const& amount)
{
std::string txt = amount.getText ();
txt += "/";
txt += to_string (amount.issue().currency);
return txt;
}
示例3: multiply
STAmount
BasicTaker::Rate::multiply (STAmount const& amount) const
{
if (quality_ == QUALITY_ONE)
return amount;
return ripple::multiply (amount, rate_, amount.issue ());
}
示例4: lhs_rate
Quality
composed_quality (Quality const& lhs, Quality const& rhs)
{
STAmount const lhs_rate (lhs.rate ());
assert (lhs_rate != zero);
STAmount const rhs_rate (rhs.rate ());
assert (rhs_rate != zero);
STAmount const rate (mulRound (
lhs_rate, rhs_rate, lhs_rate.issue (), true));
std::uint64_t const stored_exponent (rate.exponent () + 100);
std::uint64_t const stored_mantissa (rate.mantissa());
assert ((stored_exponent > 0) && (stored_exponent <= 255));
return Quality ((stored_exponent << (64 - 8)) | stored_mantissa);
}
示例5: parse_error
void
fill_fee (Json::Value& jv,
ReadView const& view)
{
if (jv.isMember(jss::Fee))
return;
auto fee = view.fees().base;
if (jv.isMember (jss::TransactionType) &&
(jv[jss::TransactionType].asString () == "Payment" ||
jv[jss::TransactionType].asString () == "ActiveAccount"))
{
if (jv.isMember (jss::Amount))
{
STAmount amount;
amountFromJsonNoThrow (amount, jv[jss::Amount]);
if (amount.native ())
fee = std::max (multiply (amount, amountFromRate (Config ().FEE_DEFAULT_RATE_NATIVE),
amount.issue ())
.mantissa (),
Config ().FEE_DEFAULT_MIN_NATIVE);
}
if (jv.isMember (jv[jss::TransactionType].asString () == "ActiveAccount" ?
jss::Reference :
jss::Destination))
{
auto const account =
parseBase58<AccountID> (
jv[jv[jss::TransactionType].asString () == "ActiveAccount" ?
jss::Reference :
jss::Destination]
.asString ());
if (!account)
throw parse_error (
"unexpected invalid Destination");
if (!view.exists (keylet::account (*account)))
fee += Config ().FEE_DEFAULT_CREATE;
}
}
jv[jss::Fee] = std::to_string(
fee);
}
示例6: deliverNodeForward
TER PathCursor::deliverNodeForward (
AccountID const& uInAccountID, // --> Input owner's account.
STAmount const& saInReq, // --> Amount to deliver.
STAmount& saInAct, // <-- Amount delivered, this invocation.
STAmount& saInFees, // <-- Fees charged, this invocation.
bool callerHasLiquidity) const
{
TER resultCode = tesSUCCESS;
// Don't deliver more than wanted.
// Zeroed in reverse pass.
node().directory.restart(multiQuality_);
saInAct.clear (saInReq);
saInFees.clear (saInReq);
int loopCount = 0;
auto viewJ = rippleCalc_.logs_.journal ("View");
// XXX Perhaps make sure do not exceed node().saRevDeliver as another way to
// stop?
while (resultCode == tesSUCCESS && saInAct + saInFees < saInReq)
{
// Did not spend all inbound deliver funds.
if (++loopCount >
(multiQuality_ ?
CALC_NODE_DELIVER_MAX_LOOPS_MQ :
CALC_NODE_DELIVER_MAX_LOOPS))
{
JLOG (j_.warn())
<< "deliverNodeForward: max loops cndf";
return telFAILED_PROCESSING;
}
// Determine values for pass to adjust saInAct, saInFees, and
// node().saFwdDeliver.
advanceNode (saInAct, false, callerHasLiquidity);
// If needed, advance to next funded offer.
if (resultCode != tesSUCCESS)
{
}
else if (!node().offerIndex_)
{
JLOG (j_.warn())
<< "deliverNodeForward: INTERNAL ERROR: Ran out of offers.";
return telFAILED_PROCESSING;
}
else if (resultCode == tesSUCCESS)
{
auto const xferRate = effectiveRate (
previousNode().issue_,
uInAccountID,
node().offerOwnerAccount_,
previousNode().transferRate_);
// First calculate assuming no output fees: saInPassAct,
// saInPassFees, saOutPassAct.
// Offer maximum out - limited by funds with out fees.
auto saOutFunded = std::min (
node().saOfferFunds, node().saTakerGets);
// Offer maximum out - limit by most to deliver.
auto saOutPassFunded = std::min (
saOutFunded,
node().saRevDeliver - node().saFwdDeliver);
// Offer maximum in - Limited by by payout.
auto saInFunded = mulRound (
saOutPassFunded,
node().saOfrRate,
node().saTakerPays.issue (),
true);
// Offer maximum in with fees.
auto saInTotal = multiplyRound (
saInFunded, xferRate, true);
auto saInRemaining = saInReq - saInAct - saInFees;
if (saInRemaining < beast::zero)
saInRemaining.clear();
// In limited by remaining.
auto saInSum = std::min (saInTotal, saInRemaining);
// In without fees.
auto saInPassAct = std::min (
node().saTakerPays,
divideRound (saInSum, xferRate, true));
// Out limited by in remaining.
auto outPass = divRound (
saInPassAct, node().saOfrRate, node().saTakerGets.issue (), true);
STAmount saOutPassMax = std::min (saOutPassFunded, outPass);
STAmount saInPassFeesMax = saInSum - saInPassAct;
// Will be determined by next node().
//.........这里部分代码省略.........
示例7: rippleLiquidity
//.........这里部分代码省略.........
if (qualityIn >= qualityOut)
{
// You're getting better quality than you asked for, so no fee.
JLOG (rippleCalc.j_.trace()) << "rippleLiquidity: No fees";
// Only process if the current rate, 1:1, is not worse than the previous
// rate, uRateMax - otherwise there is no flow.
if (!uRateMax || STAmount::uRateOne <= uRateMax)
{
// Limit amount to transfer if need - the minimum of amount being
// paid and the amount that's wanted.
STAmount saTransfer = bPrvUnlimited ? saCur
: std::min (saPrv, saCur);
// In reverse, we want to propagate the limited cur to prv and set
// actual cur.
//
// In forward, we want to propagate the limited prv to cur and set
// actual prv.
//
// This is the actual flow.
saPrvAct += saTransfer;
saCurAct += saTransfer;
// If no rate limit, set rate limit to avoid combining with
// something with a worse rate.
if (uRateMax == 0)
uRateMax = STAmount::uRateOne;
}
}
else
{
// If the quality is worse than the previous
JLOG (rippleCalc.j_.trace()) << "rippleLiquidity: Fee";
std::uint64_t const uRate = getRate (
STAmount (qualityOut.value),
STAmount (qualityIn.value));
// If the next rate is at least as good as the current rate, process.
if (!uRateMax || uRate <= uRateMax)
{
// current actual = current request * (quality out / quality in).
auto numerator = multiplyRound (saCur, qualityOut, true);
// True means "round up" to get best flow.
STAmount saCurIn = divideRound (numerator, qualityIn, true);
JLOG (rippleCalc.j_.trace())
<< "rippleLiquidity:"
<< " bPrvUnlimited=" << bPrvUnlimited
<< " saPrv=" << saPrv
<< " saCurIn=" << saCurIn;
if (bPrvUnlimited || saCurIn <= saPrv)
{
// All of current. Some amount of previous.
saCurAct += saCur;
saPrvAct += saCurIn;
JLOG (rippleCalc.j_.trace())
<< "rippleLiquidity:3c:"
<< " saCurReq=" << saCurReq
<< " saPrvAct=" << saPrvAct;
}
else
{
// There wasn't enough money to start with - so given the
// limited input, how much could we deliver?
// current actual = previous request
// * (quality in / quality out).
// This is inverted compared to the code above because we're
// going the other way
auto numerator = multiplyRound (saPrv,
qualityIn, saCur.issue(), true);
// A part of current. All of previous. (Cur is the driver
// variable.)
STAmount saCurOut = divideRound (numerator,
qualityOut, saCur.issue(), true);
JLOG (rippleCalc.j_.trace())
<< "rippleLiquidity:4: saCurReq=" << saCurReq;
saCurAct += saCurOut;
saPrvAct = saPrvReq;
}
if (!uRateMax)
uRateMax = uRate;
}
}
JLOG (rippleCalc.j_.trace())
<< "rippleLiquidity<"
<< " qualityIn=" << qualityIn
<< " qualityOut=" << qualityOut
<< " saPrvReq=" << saPrvReq
<< " saCurReq=" << saCurReq
<< " saPrvAct=" << saPrvAct
<< " saCurAct=" << saCurAct;
}
示例8: computeReverseLiquidityForAccount
TER computeReverseLiquidityForAccount (
RippleCalc& rippleCalc,
const unsigned int nodeIndex, PathState& pathState,
const bool bMultiQuality)
{
TER terResult = tesSUCCESS;
auto const lastNodeIndex = pathState.nodes().size () - 1;
auto const isFinalNode = (nodeIndex == lastNodeIndex);
// 0 quality means none has yet been determined.
std::uint64_t uRateMax = 0;
auto& previousNode = pathState.nodes()[nodeIndex ? nodeIndex - 1 : 0];
auto& node = pathState.nodes()[nodeIndex];
auto& nextNode = pathState.nodes()[isFinalNode ? lastNodeIndex : nodeIndex + 1];
// Current is allowed to redeem to next.
const bool previousNodeIsAccount = !nodeIndex || previousNode.isAccount();
const bool nextNodeIsAccount = isFinalNode || nextNode.isAccount();
Account const& previousAccountID = previousNodeIsAccount
? previousNode.account_ : node.account_;
Account const& nextAccountID = nextNodeIsAccount ? nextNode.account_
: node.account_; // Offers are always issue.
// This is the quality from from the previous node to this one.
const std::uint32_t uQualityIn
= (nodeIndex != 0)
? rippleCalc.mActiveLedger.rippleQualityIn (
node.account_, previousAccountID, node.currency_)
: QUALITY_ONE;
// And this is the quality from the next one to this one.
const std::uint32_t uQualityOut
= (nodeIndex != lastNodeIndex)
? rippleCalc.mActiveLedger.rippleQualityOut (
node.account_, nextAccountID, node.currency_)
: QUALITY_ONE;
// For previousNodeIsAccount:
// Previous account is already owed.
const STAmount saPrvOwed = (previousNodeIsAccount && nodeIndex != 0)
? rippleCalc.mActiveLedger.rippleOwed (
node.account_, previousAccountID, node.currency_)
: STAmount ({node.currency_, node.account_});
// The limit amount that the previous account may owe.
const STAmount saPrvLimit = (previousNodeIsAccount && nodeIndex != 0)
? rippleCalc.mActiveLedger.rippleLimit (
node.account_, previousAccountID, node.currency_)
: STAmount ({node.currency_, node.account_});
// Next account is owed.
const STAmount saNxtOwed = (nextNodeIsAccount && nodeIndex != lastNodeIndex)
? rippleCalc.mActiveLedger.rippleOwed (
node.account_, nextAccountID, node.currency_)
: STAmount ({node.currency_, node.account_});
WriteLog (lsTRACE, RippleCalc)
<< "computeReverseLiquidityForAccount>"
<< " nodeIndex=%d/%d" << nodeIndex << "/" << lastNodeIndex
<< " previousAccountID=" << previousAccountID
<< " node.account_=" << node.account_
<< " nextAccountID=" << nextAccountID
<< " currency_=" << node.currency_
<< " uQualityIn=" << uQualityIn
<< " uQualityOut=" << uQualityOut
<< " saPrvOwed=" << saPrvOwed
<< " saPrvLimit=" << saPrvLimit;
// Requests are computed to be the maximum flow possible.
// Previous can redeem the owed IOUs it holds.
const STAmount saPrvRedeemReq = (saPrvOwed > zero)
? saPrvOwed
: STAmount (saPrvOwed.issue ());
// This is the amount we're actually going to be setting for the previous
// node.
STAmount& saPrvRedeemAct = previousNode.saRevRedeem;
// Previous can issue up to limit minus whatever portion of limit already
// used (not including redeemable amount) - another "maximum flow".
const STAmount saPrvIssueReq = (saPrvOwed < zero)
? saPrvLimit + saPrvOwed : saPrvLimit;
STAmount& saPrvIssueAct = previousNode.saRevIssue;
// Precompute these values in case we have an order book.
auto deliverCurrency = previousNode.saRevDeliver.getCurrency ();
const STAmount saPrvDeliverReq (
{deliverCurrency, previousNode.saRevDeliver.getIssuer ()}, -1);
// Unlimited delivery.
STAmount& saPrvDeliverAct = previousNode.saRevDeliver;
// For nextNodeIsAccount
const STAmount& saCurRedeemReq = node.saRevRedeem;
// Set to zero, because we're trying to hit the previous node.
auto saCurRedeemAct = saCurRedeemReq.zeroed();
//.........这里部分代码省略.........
示例9: deliverNodeReverseImpl
// To deliver from an order book, when computing
TER PathCursor::deliverNodeReverseImpl (
AccountID const& uOutAccountID, // --> Output owner's account.
STAmount const& saOutReq, // --> Funds requested to be
// delivered for an increment.
STAmount& saOutAct, // <-- Funds actually delivered for an
// increment
bool callerHasLiquidity
) const
{
TER resultCode = tesSUCCESS;
// Accumulation of what the previous node must deliver.
// Possible optimization: Note this gets zeroed on each increment, ideally
// only on first increment, then it could be a limit on the forward pass.
saOutAct.clear (saOutReq);
JLOG (j_.trace())
<< "deliverNodeReverse>"
<< " saOutAct=" << saOutAct
<< " saOutReq=" << saOutReq
<< " saPrvDlvReq=" << previousNode().saRevDeliver;
assert (saOutReq != zero);
int loopCount = 0;
auto viewJ = rippleCalc_.logs_.journal ("View");
// While we did not deliver as much as requested:
while (saOutAct < saOutReq)
{
if (++loopCount >
(multiQuality_ ?
CALC_NODE_DELIVER_MAX_LOOPS_MQ :
CALC_NODE_DELIVER_MAX_LOOPS))
{
JLOG (j_.warn()) << "loop count exceeded";
return telFAILED_PROCESSING;
}
resultCode = advanceNode (saOutAct, true, callerHasLiquidity);
// If needed, advance to next funded offer.
if (resultCode != tesSUCCESS || !node().offerIndex_)
// Error or out of offers.
break;
auto const hasFee = node().offerOwnerAccount_ == node().issue_.account
|| uOutAccountID == node().issue_.account;
// Issuer sending or receiving.
const STAmount saOutFeeRate = hasFee
? STAmount::saOne // No fee.
: node().transferRate_; // Transfer rate of issuer.
JLOG (j_.trace())
<< "deliverNodeReverse:"
<< " offerOwnerAccount_="
<< node().offerOwnerAccount_
<< " uOutAccountID="
<< uOutAccountID
<< " node().issue_.account="
<< node().issue_.account
<< " node().transferRate_=" << node().transferRate_
<< " saOutFeeRate=" << saOutFeeRate;
if (multiQuality_)
{
// In multi-quality mode, ignore rate.
}
else if (!node().saRateMax)
{
// Set initial rate.
node().saRateMax = saOutFeeRate;
JLOG (j_.trace())
<< "deliverNodeReverse: Set initial rate:"
<< " node().saRateMax=" << node().saRateMax
<< " saOutFeeRate=" << saOutFeeRate;
}
else if (saOutFeeRate > node().saRateMax)
{
// Offer exceeds initial rate.
JLOG (j_.trace())
<< "deliverNodeReverse: Offer exceeds initial rate:"
<< " node().saRateMax=" << node().saRateMax
<< " saOutFeeRate=" << saOutFeeRate;
break; // Done. Don't bother looking for smaller transferRates.
}
else if (saOutFeeRate < node().saRateMax)
{
// Reducing rate. Additional offers will only considered for this
// increment if they are at least this good.
//
// At this point, the overall rate is reducing, while the overall
// rate is not saOutFeeRate, it would be wrong to add anything with
// a rate above saOutFeeRate.
//
// The rate would be reduced if the current offer was from the
//.........这里部分代码省略.........
示例10: reverseLiquidityForAccount
TER PathCursor::reverseLiquidityForAccount () const
{
TER terResult = tesSUCCESS;
auto const lastNodeIndex = nodeSize () - 1;
auto const isFinalNode = (nodeIndex_ == lastNodeIndex);
// 0 quality means none has yet been determined.
std::uint64_t uRateMax = 0;
// Current is allowed to redeem to next.
const bool previousNodeIsAccount = !nodeIndex_ ||
previousNode().isAccount();
const bool nextNodeIsAccount = isFinalNode || nextNode().isAccount();
AccountID const& previousAccountID = previousNodeIsAccount
? previousNode().account_ : node().account_;
AccountID const& nextAccountID = nextNodeIsAccount ? nextNode().account_
: node().account_; // Offers are always issue.
// This is the quality from from the previous node to this one.
auto const qualityIn
= (nodeIndex_ != 0)
? quality_in (view(),
node().account_,
previousAccountID,
node().issue_.currency)
: parityRate;
// And this is the quality from the next one to this one.
auto const qualityOut
= (nodeIndex_ != lastNodeIndex)
? quality_out (view(),
node().account_,
nextAccountID,
node().issue_.currency)
: parityRate;
// For previousNodeIsAccount:
// Previous account is already owed.
const STAmount saPrvOwed = (previousNodeIsAccount && nodeIndex_ != 0)
? creditBalance (view(),
node().account_,
previousAccountID,
node().issue_.currency)
: STAmount (node().issue_);
// The limit amount that the previous account may owe.
const STAmount saPrvLimit = (previousNodeIsAccount && nodeIndex_ != 0)
? creditLimit (view(),
node().account_,
previousAccountID,
node().issue_.currency)
: STAmount (node().issue_);
// Next account is owed.
const STAmount saNxtOwed = (nextNodeIsAccount && nodeIndex_ != lastNodeIndex)
? creditBalance (view(),
node().account_,
nextAccountID,
node().issue_.currency)
: STAmount (node().issue_);
JLOG (j_.trace())
<< "reverseLiquidityForAccount>"
<< " nodeIndex_=" << nodeIndex_ << "/" << lastNodeIndex
<< " previousAccountID=" << previousAccountID
<< " node.account_=" << node().account_
<< " nextAccountID=" << nextAccountID
<< " currency=" << node().issue_.currency
<< " qualityIn=" << qualityIn
<< " qualityOut=" << qualityOut
<< " saPrvOwed=" << saPrvOwed
<< " saPrvLimit=" << saPrvLimit;
// Requests are computed to be the maximum flow possible.
// Previous can redeem the owed IOUs it holds.
const STAmount saPrvRedeemReq = (saPrvOwed > beast::zero)
? saPrvOwed
: STAmount (saPrvOwed.issue ());
// Previous can issue up to limit minus whatever portion of limit already
// used (not including redeemable amount) - another "maximum flow".
const STAmount saPrvIssueReq = (saPrvOwed < beast::zero)
? saPrvLimit + saPrvOwed : saPrvLimit;
// Precompute these values in case we have an order book.
auto deliverCurrency = previousNode().saRevDeliver.getCurrency ();
const STAmount saPrvDeliverReq (
{deliverCurrency, previousNode().saRevDeliver.getIssuer ()}, -1);
// -1 means unlimited delivery.
// Set to zero, because we're trying to hit the previous node.
auto saCurRedeemAct = node().saRevRedeem.zeroed();
// Track the amount we actually redeem.
auto saCurIssueAct = node().saRevIssue.zeroed();
// For !nextNodeIsAccount
auto saCurDeliverAct = node().saRevDeliver.zeroed();
//.........这里部分代码省略.........
示例11: Issue
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));
}
示例12: missing_field_error
static Json::Value signPayment(
Json::Value const& params,
Json::Value& tx_json,
RippleAddress const& raSrcAddressID,
RPCDetail::LedgerFacade& ledgerFacade,
Role role)
{
RippleAddress dstAccountID;
if (!tx_json.isMember ("Amount"))
return RPC::missing_field_error ("tx_json.Amount");
STAmount amount;
if (! amountFromJsonNoThrow (amount, tx_json ["Amount"]))
return RPC::invalid_field_error ("tx_json.Amount");
if (!tx_json.isMember ("Destination"))
return RPC::missing_field_error ("tx_json.Destination");
if (!dstAccountID.setAccountID (tx_json["Destination"].asString ()))
return RPC::invalid_field_error ("tx_json.Destination");
if (tx_json.isMember ("Paths") && params.isMember ("build_path"))
return RPC::make_error (rpcINVALID_PARAMS,
"Cannot specify both 'tx_json.Paths' and 'build_path'");
if (!tx_json.isMember ("Paths")
&& tx_json.isMember ("Amount")
&& params.isMember ("build_path"))
{
// Need a ripple path.
Currency uSrcCurrencyID;
Account uSrcIssuerID;
STAmount saSendMax;
if (tx_json.isMember ("SendMax"))
{
if (! amountFromJsonNoThrow (saSendMax, tx_json ["SendMax"]))
return RPC::invalid_field_error ("tx_json.SendMax");
}
else
{
// If no SendMax, default to Amount with sender as issuer.
saSendMax = amount;
saSendMax.setIssuer (raSrcAddressID.getAccountID ());
}
if (saSendMax.isNative () && amount.isNative ())
return RPC::make_error (rpcINVALID_PARAMS,
"Cannot build XRP to XRP paths.");
{
LegacyPathFind lpf (role == Role::ADMIN);
if (!lpf.isOk ())
return rpcError (rpcTOO_BUSY);
STPathSet spsPaths;
STPath fullLiquidityPath;
bool valid = ledgerFacade.findPathsForOneIssuer (
dstAccountID,
saSendMax.issue (),
amount,
getConfig ().PATH_SEARCH_OLD,
4, // iMaxPaths
spsPaths,
fullLiquidityPath);
if (!valid)
{
WriteLog (lsDEBUG, RPCHandler)
<< "transactionSign: build_path: No paths found.";
return rpcError (rpcNO_PATH);
}
WriteLog (lsDEBUG, RPCHandler)
<< "transactionSign: build_path: "
<< spsPaths.getJson (0);
if (!spsPaths.empty ())
tx_json["Paths"] = spsPaths.getJson (0);
}
}
return Json::Value();
}