Add transfer support to offer taking.

This commit is contained in:
Arthur Britto
2012-10-03 14:44:59 -07:00
parent fa712549ea
commit 5b1ac0b1e5
5 changed files with 83 additions and 33 deletions

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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,

View File

@@ -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);

View File

@@ -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;
}