1#include <xrpl/ledger/helpers/TokenHelpers.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/beast/utility/Zero.h>
6#include <xrpl/beast/utility/instrumentation.h>
7#include <xrpl/ledger/ApplyView.h>
8#include <xrpl/ledger/ReadView.h>
9#include <xrpl/ledger/View.h>
10#include <xrpl/ledger/helpers/AccountRootHelpers.h>
11#include <xrpl/ledger/helpers/MPTokenHelpers.h>
12#include <xrpl/ledger/helpers/RippleStateHelpers.h>
13#include <xrpl/protocol/AccountID.h>
14#include <xrpl/protocol/Asset.h>
15#include <xrpl/protocol/Concepts.h>
16#include <xrpl/protocol/Feature.h>
17#include <xrpl/protocol/Indexes.h>
18#include <xrpl/protocol/Issue.h>
19#include <xrpl/protocol/LedgerFormats.h>
20#include <xrpl/protocol/MPTIssue.h>
21#include <xrpl/protocol/Protocol.h>
22#include <xrpl/protocol/Rate.h>
23#include <xrpl/protocol/SField.h>
24#include <xrpl/protocol/STAmount.h>
25#include <xrpl/protocol/STLedgerEntry.h>
26#include <xrpl/protocol/TER.h>
27#include <xrpl/protocol/UintTypes.h>
28#include <xrpl/protocol/XRPAmount.h>
79 [&](
auto const& issue) {
return isFrozen(view, account, issue, depth); }, asset.
value());
98 [&](
auto const& issue) {
return checkFrozen(view, account, issue); }, asset.
value());
107 for (
auto const& account : accounts)
136 return isFrozen(view, account, mptIssue, depth);
143 [&](
auto const& issue) {
return isDeepFrozen(view, account, issue, depth); },
169 isPseudoAccount(view, srcAcct),
"xrpl::checkWithdrawFreeze : source is a pseudo-account");
172 "xrpl::checkWithdrawFreeze : submitter is not a pseudo-account");
175 "xrpl::checkWithdrawFreeze : destination is not a pseudo-account");
199 if (submitterAcct != dstAcct)
218 "xrpl::checkDepositFreeze : destination is a pseudo-account");
221 "xrpl::checkDepositFreeze : source is not a pseudo-account");
268 if (
isFrozen(view, account, currency, issuer) ||
283 if (sleIssuer->isFieldPresent(sfAMMID))
288 isLPTokenFrozen(view, account, (*sleAmm)[sfAsset], (*sleAmm)[sfAsset2]))
306 bool includeOppositeLimit,
312 amount = sle->getFieldAmount(sfBalance);
313 bool const accountHigh = account > issuer;
314 auto const& oppositeField = accountHigh ? sfLowLimit : sfHighLimit;
320 if (includeOppositeLimit)
322 amount += sle->getFieldAmount(oppositeField);
324 amount.
get<
Issue>().account = issuer;
331 JLOG(j.
trace()) <<
"getTrustLineBalance:" <<
" account=" <<
to_string(account)
354 if (returnSpendable && account == issuer)
378 view, account, issue.
currency, issue.
account, zeroIfFrozen, j, includeFullBalance);
393 auto const& issuer = mptIssue.
getIssuer();
394 bool const mptokensV2 = view.
rules().
enabled(featureMPTokensV2);
396 if (returnSpendable && account == mptIssue.
getIssuer())
408 return STAmount{mptIssue, available};
417 amount.
clear(mptIssue);
421 amount =
STAmount{mptIssue, sleMpt->getFieldU64(sfMPTAmount)};
431 amount.
clear(mptIssue);
439 if (sleIssuance && sleIssuance->isFlag(lsfMPTRequireAuth) &&
440 !sleMpt->isFlag(lsfMPTAuthorized))
441 amount.
clear(mptIssue);
450[[nodiscard]] STAmount
461 [&](
Issue const& issue) {
462 return accountHolds(view, account, issue, zeroIfFrozen, j, includeFullBalance);
466 view, account, issue, zeroIfFrozen, zeroIfUnauthorized, j, includeFullBalance);
478 XRPL_ASSERT(saDefault.
holds<
Issue>(),
"xrpl::accountFunds: saDefault holds Issue");
497 [&](
Issue const&) {
return accountFunds(view,
id, saDefault, freezeHandling, j); },
537 if (!issuer->isFlag(lsfDefaultRipple))
593 return requireAuth(view, issue, account, authType);
609 return canTransfer(view, issue, from, to, waive, depth);
638 !bCheckIssuer || uSenderID == issuer || uReceiverID == issuer,
639 "xrpl::directSendNoFeeIOU : matching issuer or don't care");
643 XRPL_ASSERT(uSenderID != uReceiverID,
"xrpl::directSendNoFeeIOU : sender is not receiver");
645 bool const bSenderHigh = uSenderID > uReceiverID;
650 "xrpl::directSendNoFeeIOU : sender is not XRP");
653 "xrpl::directSendNoFeeIOU : receiver is not XRP");
656 if (
auto const sleRippleState = view.
peek(index))
658 STAmount saBalance = sleRippleState->getFieldAmount(sfBalance);
663 view.
creditHookIOU(uSenderID, uReceiverID, saAmount, saBalance);
665 STAmount const saBefore = saBalance;
667 saBalance -= saAmount;
669 JLOG(j.
trace()) <<
"directSendNoFeeIOU: " <<
to_string(uSenderID) <<
" -> "
674 bool bDelete =
false;
676 auto const senderReserveFlag = bSenderHigh ? lsfHighReserve : lsfLowReserve;
677 auto const senderNoRippleFlag = bSenderHigh ? lsfHighNoRipple : lsfLowNoRipple;
678 auto const senderFreezeFlag = bSenderHigh ? lsfHighFreeze : lsfLowFreeze;
679 auto const receiverReserveFlag = bSenderHigh ? lsfLowReserve : lsfHighReserve;
683 if (saBefore > beast::kZero
685 && saBalance <= beast::kZero
687 && sleRippleState->isFlag(senderReserveFlag)
689 && sleRippleState->isFlag(senderNoRippleFlag) !=
691 !sleRippleState->isFlag(senderFreezeFlag) &&
692 !sleRippleState->getFieldAmount(bSenderHigh ? sfHighLimit : sfLowLimit)
694 && (sleRippleState->getFieldU32(bSenderHigh ? sfHighQualityIn : sfLowQualityIn) == 0u)
697 (sleRippleState->getFieldU32(bSenderHigh ? sfHighQualityOut : sfLowQualityOut) == 0u))
704 sleRippleState->clearFlag(senderReserveFlag);
708 && !sleRippleState->isFlag(receiverReserveFlag);
716 sleRippleState->setFieldAmount(sfBalance, saBalance);
724 bSenderHigh ? uReceiverID : uSenderID,
725 bSenderHigh ? uSenderID : uReceiverID,
729 view.
update(sleRippleState);
733 STAmount const saReceiverLimit(
Issue{currency, uReceiverID});
738 JLOG(j.
debug()) <<
"directSendNoFeeIOU: "
747 bool const noRipple = !sleAccount->isFlag(lsfDefaultRipple);
780 auto const& issuer = saAmount.
getIssuer();
784 "xrpl::directSendNoLimitIOU : neither sender nor receiver is XRP");
785 XRPL_ASSERT(uSenderID != uReceiverID,
"xrpl::directSendNoLimitIOU : sender is not receiver");
787 if (uSenderID == issuer || uReceiverID == issuer || issuer ==
noAccount())
790 auto const ter =
directSendNoFeeIOU(view, uSenderID, uReceiverID, saAmount,
false, j);
804 JLOG(j.
debug()) <<
"directSendNoLimitIOU> " <<
to_string(uSenderID) <<
" - > "
831 XRPL_ASSERT(!
isXRP(senderID),
"xrpl::directSendNoLimitMultiIOU : sender is not XRP");
835 actual = takeFromSender;
838 for (
auto const& r : receivers)
840 auto const& receiverID = r.first;
841 STAmount const amount{issue, r.second};
846 if (!amount || (senderID == receiverID))
849 XRPL_ASSERT(!
isXRP(receiverID),
"xrpl::directSendNoLimitMultiIOU : receiver is not XRP");
851 if (senderID == issuer || receiverID == issuer || issuer ==
noAccount())
854 if (
auto const ter =
directSendNoFeeIOU(view, senderID, receiverID, amount,
false, j);
871 actual += actualSend;
872 takeFromSender += actualSend;
874 JLOG(j.
debug()) <<
"directSendNoLimitMultiIOU> " <<
to_string(senderID) <<
" - > "
882 if (senderID != issuer && takeFromSender)
884 if (
TER const terResult =
913 "xrpl::accountSendIOU : minimum amount and not MPT");
920 if (!saAmount || (uSenderID == uReceiverID))
927 JLOG(j.
trace()) <<
"accountSendIOU: " <<
to_string(uSenderID) <<
" -> "
945 if (
auto stream = j.
trace())
956 stream <<
"accountSendIOU> " <<
to_string(uSenderID) <<
" (" << senderBal <<
") -> "
991 if (
auto stream = j.
trace())
1002 stream <<
"accountSendIOU< " <<
to_string(uSenderID) <<
" (" << senderBal <<
") -> "
1019 receivers.
size() > 1,
"xrpl::accountSendMultiIOU",
"multiple recipients provided");
1024 JLOG(j.
trace()) <<
"accountSendMultiIOU: " <<
to_string(senderID) <<
" sending "
1025 << receivers.
size() <<
" IOUs";
1039 if (
auto stream = j.
trace())
1046 stream <<
"accountSendMultiIOU> " <<
to_string(senderID) <<
" (" << senderBal <<
") -> "
1047 << receivers.
size() <<
" receivers.";
1052 for (
auto const& r : receivers)
1054 auto const& receiverID = r.first;
1055 STAmount const amount{issue, r.second};
1057 if (amount < beast::kZero)
1065 if (!amount || (senderID == receiverID))
1071 if (
auto stream = j.
trace())
1078 stream <<
"accountSendMultiIOU> " <<
to_string(senderID) <<
" -> "
1079 <<
to_string(receiverID) <<
" (" << receiverBal
1093 takeFromSender += amount;
1096 if (
auto stream = j.
trace())
1103 stream <<
"accountSendMultiIOU< " <<
to_string(senderID) <<
" -> "
1104 <<
to_string(receiverID) <<
" (" << receiverBal
1123 if (
auto stream = j.
trace())
1130 stream <<
"accountSendMultiIOU< " <<
to_string(senderID) <<
" (" << senderBal <<
") -> "
1131 << receivers.
size() <<
" receivers.";
1146 auto const& issuer = saAmount.
getIssuer();
1147 auto sleIssuance = view.
peek(mptID);
1152 auto const outstanding = sleIssuance->getFieldU64(sfOutstandingAmount);
1154 auto const amt = saAmount.
mpt().
value();
1156 if (uSenderID == issuer)
1163 (*sleIssuance)[sfOutstandingAmount] += amt;
1164 view.
update(sleIssuance);
1169 if (
auto sle = view.
peek(mptokenID))
1171 auto const senderBalance = sle->getFieldU64(sfMPTAmount);
1172 if (senderBalance < amt)
1174 view.
creditHookMPT(uSenderID, uReceiverID, saAmount, (*sle)[sfMPTAmount], available);
1175 (*sle)[sfMPTAmount] = senderBalance - amt;
1184 if (uReceiverID == issuer)
1186 if (outstanding >= amt)
1188 sleIssuance->setFieldU64(sfOutstandingAmount, outstanding - amt);
1189 view.
update(sleIssuance);
1199 if (
auto sle = view.
peek(mptokenID))
1208 view.
creditHookMPT(uSenderID, uReceiverID, saAmount, (*sle)[sfMPTAmount], available);
1209 (*sle)[sfMPTAmount] += amt;
1232 XRPL_ASSERT(uSenderID != uReceiverID,
"xrpl::directSendNoLimitMPT : sender is not receiver");
1235 auto const& issuer = saAmount.
getIssuer();
1241 if (uSenderID == issuer || uReceiverID == issuer)
1245 if (uSenderID == issuer)
1247 auto const sendAmount = saAmount.
mpt().
value();
1249 auto const outstanding = sle->getFieldU64(sfOutstandingAmount);
1250 auto const mptokensV2 = view.
rules().
enabled(featureMPTokensV2);
1254 if (
isMPTOverflow(sendAmount, outstanding, maxAmount, allowOverflow))
1262 saActual = saAmount;
1271 JLOG(j.
debug()) <<
"directSendNoLimitMPT> " <<
to_string(uSenderID) <<
" - > "
1275 if (
auto const terResult =
directSendNoFeeMPT(view, issuer, uReceiverID, saAmount, j);
1292 auto const& issuer = mptIssue.
getIssuer();
1307 std::uint64_t const outstandingAmount = sle->getFieldU64(sfOutstandingAmount);
1314 actual = takeFromSender;
1316 for (
auto const& [receiverID, amt] : receivers)
1318 STAmount const amount{mptIssue, amt};
1320 if (amount < beast::kZero)
1323 if (!amount || senderID == receiverID)
1326 if (senderID == issuer || receiverID == issuer)
1328 if (senderID == issuer)
1331 takeFromSender == beast::kZero,
1332 "xrpl::directSendNoLimitMultiMPT",
1333 "sender == issuer, takeFromSender == zero");
1343 bool const exceedsMaximumAmount =
1345 sendAmount > maximumAmount ||
1347 totalSendAmount > maximumAmount - sendAmount ||
1349 outstandingAmount > maximumAmount - sendAmount - totalSendAmount;
1351 if (exceedsMaximumAmount)
1353 totalSendAmount += sendAmount;
1361 if (sendAmount > maximumAmount ||
1362 outstandingAmount > maximumAmount - sendAmount)
1381 actual += actualSend;
1382 takeFromSender += actualSend;
1384 JLOG(j.
debug()) <<
"directSendNoLimitMultiMPT> " <<
to_string(senderID) <<
" - > "
1392 if (senderID != issuer && takeFromSender)
1414 "xrpl::accountSendMPT : minimum amount and MPT");
1419 if (!saAmount || (uSenderID == uReceiverID))
1425 view, uSenderID, uReceiverID, saAmount, saActual, j, waiveFee, allowOverflow);
1462 XRPL_ASSERT(!bCheckIssuer,
"xrpl::directSendNoFee : not checking issuer");
1479 return accountSendIOU(view, uSenderID, uReceiverID, saAmount, j, waiveFee);
1483 view, uSenderID, uReceiverID, saAmount, j, waiveFee, allowOverflow);
1497 receivers.
size() > 1,
"xrpl::accountSendMulti",
"multiple recipients provided");
1499 [&](
Issue const& issue) {
1515 XRPL_ASSERT(from != beast::kZero,
"xrpl::transferXRP : nonzero from account");
1516 XRPL_ASSERT(to != beast::kZero,
"xrpl::transferXRP : nonzero to account");
1517 XRPL_ASSERT(from != to,
"xrpl::transferXRP : sender is not receiver");
1518 XRPL_ASSERT(amount.
native(),
"xrpl::transferXRP : amount is XRP");
1522 if (!sender || !receiver)
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
Writeable view to a ledger, for applying a transaction.
virtual SLE::pointer peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void creditHookIOU(AccountID const &from, AccountID const &to, STAmount const &amount, STAmount const &preCreditBalance)
virtual void creditHookMPT(AccountID const &from, AccountID const &to, STAmount const &amount, std::uint64_t preCreditBalanceHolder, std::int64_t preCreditBalanceIssuer)
virtual void update(SLE::ref sle)=0
Indicate changes to a peeked SLE.
constexpr auto visit(Visitors &&... visitors) const -> decltype(auto)
constexpr TIss const & get() const
AccountID const & getIssuer() const
constexpr bool holds() const
constexpr value_type const & value() const
A currency issued by an account.
AccountID const & getIssuer() const
constexpr value_type value() const
Returns the underlying value.
constexpr MPTID const & getMptID() const
AccountID const & getIssuer() const
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual STAmount balanceHookMPT(AccountID const &account, MPTIssue const &issue, std::int64_t amount) const
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
virtual bool open() const =0
Returns true if this reflects an open ledger.
virtual STAmount balanceHookIOU(AccountID const &account, AccountID const &issuer, STAmount const &amount) const
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
constexpr bool holds() const noexcept
constexpr TIss const & get() const
std::string getFullText() const override
bool native() const noexcept
Asset const & asset() const
AccountID const & getIssuer() const
static constexpr std::uint64_t kMaxValue
static constexpr int kMaxOffset
std::shared_ptr< STLedgerEntry > pointer
std::shared_ptr< STLedgerEntry const > const & const_ref
std::shared_ptr< STLedgerEntry const > const_pointer
void setFieldAmount(SField const &field, STAmount const &)
STAmount const & getFieldAmount(SField const &field) const
Keylet mptokenIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Keylet mptoken(MPTID const &issuanceID, AccountID const &holder) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet trustLine(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
TER checkDeepFrozen(ReadView const &view, AccountID const &account, Issue const &issue)
std::int64_t maxMPTAmount(SLE const &sleIssuance)
XRPAmount xrpLiquid(ReadView const &view, AccountID const &id, std::int32_t ownerCountAdj, beast::Journal j)
FreezeHandling
Controls the treatment of frozen account balances.
static TER directSendNoLimitMultiIOU(ApplyView &view, AccountID const &senderID, Issue const &issue, MultiplePaymentDestinations const &receivers, STAmount &actual, beast::Journal j, WaiveTransferFee waiveFee)
SpendableHandling
Controls whether to include the account's full spendable balance.
TER checkIndividualFrozen(ReadView const &view, AccountID const &account, Asset const &asset)
bool isXRP(AccountID const &c)
bool isIndividualFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptIssue)
AllowMPTOverflow
Controls whether accountSend is allowed to overflow OutstandingAmount.
TER trustCreate(ApplyView &view, bool const bSrcHigh, AccountID const &uSrcAccountID, AccountID const &uDstAccountID, uint256 const &uIndex, SLE::ref sleAccount, bool const bAuth, bool const bNoRipple, bool const bFreeze, bool bDeepFreeze, STAmount const &saBalance, STAmount const &saLimit, std::uint32_t uQualityIn, std::uint32_t uQualityOut, beast::Journal j)
Create a trust line.
static TER accountSendMultiIOU(ApplyView &view, AccountID const &senderID, Issue const &issue, MultiplePaymentDestinations const &receivers, beast::Journal j, WaiveTransferFee waiveFee)
TER addEmptyHolding(ApplyView &view, AccountID const &accountID, XRPAmount priorBalance, MPTIssue const &mptIssue, beast::Journal journal)
TER checkFrozen(ReadView const &view, AccountID const &account, Issue const &issue)
static TER directSendNoFeeIOU(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, bool bCheckIssuer, beast::Journal j)
BaseUInt< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
TER trustDelete(ApplyView &view, SLE::ref sleRippleState, AccountID const &uLowAccountID, AccountID const &uHighAccountID, beast::Journal j)
TER canTransfer(ReadView const &view, MPTIssue const &mptIssue, AccountID const &from, AccountID const &to, WaiveMPTCanTransfer waive=WaiveMPTCanTransfer::No, std::uint8_t depth=0)
Check whether to may receive the given MPT from from.
bool isDeepFrozen(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer)
std::string to_string(BaseUInt< Bits, Tag > const &a)
bool isVaultPseudoAccountFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptShare, std::uint8_t depth)
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
bool isGlobalFrozen(ReadView const &view, AccountID const &issuer)
Check if the issuer has the global freeze flag set.
TER canAddHolding(ReadView const &view, MPTIssue const &mptIssue)
static STAmount getTrustLineBalance(ReadView const &view, SLE::const_ref sle, AccountID const &account, Currency const ¤cy, AccountID const &issuer, bool includeOppositeLimit, beast::Journal j)
AuthHandling
Controls the treatment of unauthorized MPT balances.
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
static SLE::const_pointer getLineIfUsable(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
TER checkWithdrawFreeze(ReadView const &view, AccountID const &srcAcct, AccountID const &submitterAcct, AccountID const &dstAcct, Asset const &asset)
Checks freeze compliance for withdrawing an asset from a pseudo-account (e.g.
TER directSendNoFee(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, bool bCheckIssuer, beast::Journal j)
Calls static directSendNoFeeIOU if saAmount represents Issue.
std::int64_t availableMPTAmount(SLE const &sleIssuance)
void adjustOwnerCount(ApplyView &view, SLE::ref sle, std::int32_t amount, beast::Journal j)
Adjust the owner count up or down.
TER transferXRP(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &amount, beast::Journal j)
WaiveMPTCanTransfer
Controls whether canTransfer enforces lsfMPTCanTransfer on MPTs.
bool isFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptIssue, std::uint8_t depth=0)
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No, AllowMPTOverflow allowOverflow=AllowMPTOverflow::No)
Calls static accountSendIOU if saAmount represents Issue.
TER checkGlobalFrozen(ReadView const &view, Asset const &asset)
static TER directSendNoLimitIOU(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, STAmount &saActual, beast::Journal j, WaiveTransferFee waiveFee)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
TER checkDepositFreeze(ReadView const &view, AccountID const &srcAcct, AccountID const &dstAcct, Asset const &asset)
Checks freeze compliance for depositing an asset into a pseudo-account (e.g.
AccountID const & noAccount()
A placeholder for empty accounts.
static TER directSendNoLimitMPT(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, STAmount &saActual, beast::Journal j, WaiveTransferFee waiveFee, AllowMPTOverflow allowOverflow)
static TER accountSendIOU(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee)
static TER accountSendMPT(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee, AllowMPTOverflow allowOverflow)
bool isTesSuccess(TER x) noexcept
bool isAnyFrozen(ReadView const &view, std::initializer_list< AccountID > const &accounts, MPTIssue const &mptIssue, std::uint8_t depth=0)
TERSubset< CanCvtToTER > TER
bool isLPTokenFrozen(ReadView const &view, AccountID const &account, Asset const &asset, Asset const &asset2)
TER requireAuth(ReadView const &view, MPTIssue const &mptIssue, AccountID const &account, AuthType authType=AuthType::Legacy, std::uint8_t depth=0)
Check if the account lacks required authorization for MPT.
static TER directSendNoLimitMultiMPT(ApplyView &view, AccountID const &senderID, MPTIssue const &mptIssue, MultiplePaymentDestinations const &receivers, STAmount &actual, beast::Journal j, WaiveTransferFee waiveFee)
AccountID const & xrpAccount()
Compute AccountID from public key.
STAmount multiply(STAmount const &amount, Number const &frac, Number::RoundingMode rm)
static TER accountSendMultiMPT(ApplyView &view, AccountID const &senderID, MPTIssue const &mptIssue, MultiplePaymentDestinations const &receivers, beast::Journal j, WaiveTransferFee waiveFee)
std::vector< std::pair< AccountID, Number > > MultiplePaymentDestinations
bool isPseudoAccount(SLE::const_pointer sleAcct, std::set< SField const * > const &pseudoFieldFilter={})
Returns true if and only if sleAcct is a pseudo-account or specific pseudo-accounts in pseudoFieldFil...
TER accountSendMulti(ApplyView &view, AccountID const &senderID, Asset const &asset, MultiplePaymentDestinations const &receivers, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No)
Like accountSend, except one account is sending multiple payments (with the same asset!...
constexpr std::uint64_t kMaxMpTokenAmount
The maximum amount of MPTokenIssuance.
TER removeEmptyHolding(ApplyView &view, AccountID const &accountID, MPTIssue const &mptIssue, beast::Journal journal)
bool isMPTOverflow(std::int64_t sendAmount, std::uint64_t outstandingAmount, std::int64_t maximumAmount, AllowMPTOverflow allowOverflow)
Checks for two types of OutstandingAmount overflow during a send operation.
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=SpendableHandling::SimpleBalance)
static TER directSendNoFeeMPT(ApplyView &view, AccountID const &uSenderID, AccountID const &uReceiverID, STAmount const &saAmount, beast::Journal j)