mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Add transfer support to offer taking.
This commit is contained in:
@@ -883,40 +883,56 @@ STAmount STAmount::setRate(uint64 rate)
|
||||
}
|
||||
|
||||
// Taker gets all taker can pay for with saTakerFunds, limited by saOfferPays and saOfferFunds.
|
||||
// --> saOfferFunds: Limit for saOfferPays
|
||||
// --> saTakerFunds: Limit for saOfferGets : How much taker really wants. : Driver
|
||||
// --> saOfferPays: Request : this should be reduced as the offer is fullfilled.
|
||||
// --> saOfferGets: Request : this should be reduced as the offer is fullfilled.
|
||||
// --> saTakerPays: Total : Used to know the approximate ratio of the exchange.
|
||||
// --> saTakerGets: Total : Used to know the approximate ratio of the exchange.
|
||||
// <-- saTakerPaid: Actual
|
||||
// <-- saTakerGot: Actual
|
||||
// <-- bRemove: remove offer it is either fullfilled or unfunded
|
||||
// --> uTakerPaysRate: >= QUALITY_ONE
|
||||
// --> uOfferPaysRate: >= QUALITY_ONE
|
||||
// --> saOfferFunds: Limit for saOfferPays
|
||||
// --> saTakerFunds: Limit for saOfferGets : How much taker really wants. : Driver
|
||||
// --> saOfferPays: Request : this should be reduced as the offer is fullfilled.
|
||||
// --> saOfferGets: Request : this should be reduced as the offer is fullfilled.
|
||||
// --> saTakerPays: Total : Used to know the approximate ratio of the exchange.
|
||||
// --> saTakerGets: Total : Used to know the approximate ratio of the exchange.
|
||||
// <-- saTakerPaid: Actual
|
||||
// <-- saTakerGot: Actual
|
||||
// <-- saTakerIssuerFee: Actual
|
||||
// <-- saOfferIssuerFee: Actual
|
||||
// <-- bRemove: remove offer it is either fullfilled or unfunded
|
||||
bool STAmount::applyOffer(
|
||||
const uint32 uTakerPaysRate, const uint32 uOfferPaysRate,
|
||||
const STAmount& saOfferFunds, const STAmount& saTakerFunds,
|
||||
const STAmount& saOfferPays, const STAmount& saOfferGets,
|
||||
const STAmount& saTakerPays, const STAmount& saTakerGets,
|
||||
STAmount& saTakerPaid, STAmount& saTakerGot)
|
||||
STAmount& saTakerPaid, STAmount& saTakerGot,
|
||||
STAmount& saTakerIssuerFee, STAmount& saOfferIssuerFee)
|
||||
{
|
||||
saOfferGets.throwComparable(saTakerPays);
|
||||
|
||||
assert(!saOfferFunds.isZero() && !saTakerFunds.isZero()); // Must have funds.
|
||||
assert(!saOfferGets.isZero() && !saOfferPays.isZero()); // Must not be a null offer.
|
||||
|
||||
// Amount offer can pay out, limited by funds and fees.
|
||||
STAmount saOfferFundsAvailable = QUALITY_ONE == uOfferPaysRate
|
||||
? saOfferFunds
|
||||
: STAmount::divide(saOfferFunds, STAmount(CURRENCY_ONE, uOfferPaysRate, -9));
|
||||
|
||||
// Amount offer can pay out, limited by offer and funds.
|
||||
STAmount saOfferPaysAvailable = saOfferFunds < saOfferPays ? saOfferFunds : saOfferPays;
|
||||
STAmount saOfferPaysAvailable = std::min(saOfferFundsAvailable, saOfferPays);
|
||||
|
||||
// Amount offer can get in proportion, limited by offer funds.
|
||||
STAmount saOfferGetsAvailable =
|
||||
saOfferFunds == saOfferPays
|
||||
saOfferFundsAvailable == saOfferPays
|
||||
? saOfferGets // Offer was fully funded, avoid shenanigans.
|
||||
: divide(multiply(saTakerPays, saOfferPaysAvailable, CURRENCY_ONE, ACCOUNT_ONE), saTakerGets, saOfferGets.getCurrency(), saOfferGets.getIssuer());
|
||||
|
||||
if (saOfferGets == saOfferGetsAvailable && saTakerFunds >= saOfferGets)
|
||||
// Amount taker can spend, limited by funds and fees.
|
||||
STAmount saTakerFundsAvailable = QUALITY_ONE == uTakerPaysRate
|
||||
? saTakerFunds
|
||||
: STAmount::divide(saTakerFunds, STAmount(CURRENCY_ONE, uTakerPaysRate, -9));
|
||||
|
||||
if (saOfferGets == saOfferGetsAvailable && saTakerFundsAvailable >= saOfferGets)
|
||||
{
|
||||
// Taker gets all of offer available.
|
||||
saTakerPaid = saOfferGets; // Taker paid what offer could get.
|
||||
saTakerGot = saOfferPays; // Taker got what offer could pay.
|
||||
saTakerPaid = saOfferGets; // Taker paid what offer could get.
|
||||
saTakerGot = saOfferPays; // Taker got what offer could pay.
|
||||
|
||||
Log(lsINFO) << "applyOffer: took all outright";
|
||||
}
|
||||
@@ -934,8 +950,32 @@ bool STAmount::applyOffer(
|
||||
saTakerPaid = saTakerFunds; // Taker paid all he had.
|
||||
saTakerGot = divide(multiply(saTakerFunds, saOfferPaysAvailable, CURRENCY_ONE, ACCOUNT_ONE), saOfferGetsAvailable, saOfferPays.getCurrency(), saOfferPays.getIssuer());
|
||||
|
||||
Log(lsINFO) << "applyOffer: saTakerGot=" << saTakerGot;
|
||||
Log(lsINFO) << "applyOffer: saOfferPaysAvailable=" << saOfferPaysAvailable;
|
||||
Log(lsINFO) << "applyOffer: saTakerGot=" << saTakerGot.getFullText();
|
||||
Log(lsINFO) << "applyOffer: saOfferPaysAvailable=" << saOfferPaysAvailable.getFullText();
|
||||
}
|
||||
|
||||
if (uTakerPaysRate == QUALITY_ONE)
|
||||
{
|
||||
saTakerIssuerFee = STAmount(saTakerPaid.getCurrency(), saTakerPaid.getIssuer());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute fees in a rounding safe way.
|
||||
STAmount saTotal = STAmount::multiply(saTakerPaid, STAmount(CURRENCY_ONE, uTakerPaysRate, -9));
|
||||
|
||||
saTakerIssuerFee = (saTotal > saTakerFunds) ? saTakerFunds-saTakerPaid : saTotal - saTakerPaid;
|
||||
}
|
||||
|
||||
if (uOfferPaysRate == QUALITY_ONE)
|
||||
{
|
||||
saOfferIssuerFee = STAmount(saTakerGot.getCurrency(), saTakerGot.getIssuer());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute fees in a rounding safe way.
|
||||
STAmount saTotal = STAmount::multiply(saTakerPaid, STAmount(CURRENCY_ONE, uTakerPaysRate, -9));
|
||||
|
||||
saOfferIssuerFee = (saTotal > saOfferFunds) ? saOfferFunds-saTakerGot : saTotal - saTakerGot;
|
||||
}
|
||||
|
||||
return saTakerGot >= saOfferPays;
|
||||
|
||||
@@ -875,6 +875,15 @@ uint32 LedgerEntrySet::rippleTransferRate(const uint160& uIssuerID)
|
||||
return uQuality;
|
||||
}
|
||||
|
||||
uint32 LedgerEntrySet::rippleTransferRate(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID)
|
||||
{
|
||||
uint32 uQuality;
|
||||
|
||||
return uSenderID == uIssuerID || uReceiverID == uIssuerID
|
||||
? QUALITY_ONE
|
||||
: rippleTransferRate(uIssuerID);
|
||||
}
|
||||
|
||||
// XXX Might not need this, might store in nodes on calc reverse.
|
||||
uint32 LedgerEntrySet::rippleQualityIn(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID, SField::ref sfLow, SField::ref sfHigh)
|
||||
{
|
||||
|
||||
@@ -102,6 +102,7 @@ public:
|
||||
|
||||
// Balance functions.
|
||||
uint32 rippleTransferRate(const uint160& uIssuerID);
|
||||
uint32 rippleTransferRate(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID);
|
||||
STAmount rippleOwed(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID);
|
||||
STAmount rippleLimit(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID);
|
||||
uint32 rippleQualityIn(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID,
|
||||
|
||||
@@ -343,10 +343,12 @@ public:
|
||||
// Someone is offering X for Y, I try to pay Z, how much do I get?
|
||||
// And what's left of the offer? And how much do I actually pay?
|
||||
static bool applyOffer(
|
||||
const uint32 uTakerPaysRate, const uint32 uOfferPaysRate,
|
||||
const STAmount& saOfferFunds, const STAmount& saTakerFunds,
|
||||
const STAmount& saOfferPays, const STAmount& saOfferGets,
|
||||
const STAmount& saTakerPays, const STAmount& saTakerGets,
|
||||
STAmount& saTakerPaid, STAmount& saTakerGot);
|
||||
STAmount& saTakerPaid, STAmount& saTakerGot,
|
||||
STAmount& saTakerIssuerFee, STAmount& saOfferIssuerFee);
|
||||
|
||||
// Someone is offering X for Y, I need Z, how much do I pay
|
||||
static STAmount getPay(const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed);
|
||||
|
||||
@@ -822,6 +822,8 @@ TER TransactionEngine::takeOffers(
|
||||
saPay = saTakerFunds;
|
||||
STAmount saSubTakerPaid;
|
||||
STAmount saSubTakerGot;
|
||||
STAmount saTakerIssuerFee;
|
||||
STAmount saOfferIssuerFee;
|
||||
|
||||
Log(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText();
|
||||
Log(lsINFO) << "takeOffers: applyOffer: saTakerPaid: " << saTakerPaid.getFullText();
|
||||
@@ -832,20 +834,10 @@ TER TransactionEngine::takeOffers(
|
||||
Log(lsINFO) << "takeOffers: applyOffer: saOfferGets: " << saOfferGets.getFullText();
|
||||
Log(lsINFO) << "takeOffers: applyOffer: saTakerPays: " << saTakerPays.getFullText();
|
||||
Log(lsINFO) << "takeOffers: applyOffer: saTakerGets: " << saTakerGets.getFullText();
|
||||
#if 0
|
||||
STAmount saTakerPaysRate =
|
||||
uTakerPaysAccountID == uTakerAccountID // Taker is issuing, no fee.
|
||||
|| uTakerPaysAccountID == uOfferAccountID // Taker is redeeming, no fee.
|
||||
? 0.0
|
||||
: getRate(uTakerPaysAccountID);
|
||||
|
||||
STAmount saOfferPaysRate =
|
||||
uTakerGetsAccountID == uTakerGetsAccountID // Offerer is redeeming, no fee.
|
||||
|| uTakerGetsAccountID == uOfferAccountID // Offerer is issuing, no fee.
|
||||
? 0.0
|
||||
: getRate(uTakerGetsAccountID);
|
||||
#endif
|
||||
bool bOfferDelete = STAmount::applyOffer(
|
||||
mNodes.rippleTransferRate(uTakerAccountID, uOfferOwnerID, uTakerPaysAccountID),
|
||||
mNodes.rippleTransferRate(uOfferOwnerID, uTakerAccountID, uTakerGetsAccountID),
|
||||
saOfferFunds,
|
||||
saPay, // Driver XXX need to account for fees.
|
||||
saOfferPays,
|
||||
@@ -853,7 +845,9 @@ TER TransactionEngine::takeOffers(
|
||||
saTakerPays,
|
||||
saTakerGets,
|
||||
saSubTakerPaid,
|
||||
saSubTakerGot);
|
||||
saSubTakerGot,
|
||||
saTakerIssuerFee,
|
||||
saOfferIssuerFee);
|
||||
|
||||
Log(lsINFO) << "takeOffers: applyOffer: saSubTakerPaid: " << saSubTakerPaid.getFullText();
|
||||
Log(lsINFO) << "takeOffers: applyOffer: saSubTakerGot: " << saSubTakerGot.getFullText();
|
||||
@@ -884,16 +878,20 @@ TER TransactionEngine::takeOffers(
|
||||
}
|
||||
|
||||
// Offer owner pays taker.
|
||||
saSubTakerGot.setIssuer(uTakerGetsAccountID); // XXX Move this earlier?
|
||||
// saSubTakerGot.setIssuer(uTakerGetsAccountID); // XXX Move this earlier?
|
||||
assert(!!saSubTakerGot.getIssuer());
|
||||
|
||||
mNodes.accountSend(uOfferOwnerID, uTakerAccountID, saSubTakerGot);
|
||||
mNodes.accountSend(uOfferOwnerID, uTakerGetsAccountID, saOfferIssuerFee);
|
||||
|
||||
saTakerGot += saSubTakerGot;
|
||||
|
||||
// Taker pays offer owner.
|
||||
saSubTakerPaid.setIssuer(uTakerPaysAccountID);
|
||||
// saSubTakerPaid.setIssuer(uTakerPaysAccountID);
|
||||
assert(!!saSubTakerPaid.getIssuer());
|
||||
|
||||
mNodes.accountSend(uTakerAccountID, uOfferOwnerID, saSubTakerPaid);
|
||||
mNodes.accountSend(uTakerAccountID, uTakerPaysAccountID, saTakerIssuerFee);
|
||||
|
||||
saTakerPaid += saSubTakerPaid;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user