mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Add support for transfer fees to RPC book_offers.
This commit is contained in:
@@ -1066,6 +1066,8 @@ STAmount LedgerEntrySet::rippleHolds(const uint160& uAccountID, const uint160& u
|
|||||||
return saBalance;
|
return saBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the amount an account can spend without going into debt.
|
||||||
|
//
|
||||||
// <-- saAmount: amount of uCurrencyID held by uAccountID. May be negative.
|
// <-- saAmount: amount of uCurrencyID held by uAccountID. May be negative.
|
||||||
STAmount LedgerEntrySet::accountHolds(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID)
|
STAmount LedgerEntrySet::accountHolds(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1784,121 +1784,137 @@ void NetworkOPs::getBookPage(Ledger::pointer lpLedger, const uint160& uTakerPays
|
|||||||
STAmount saDirRate;
|
STAmount saDirRate;
|
||||||
|
|
||||||
// unsigned int iLeft = iLimit;
|
// unsigned int iLeft = iLimit;
|
||||||
SLE::pointer sleGetsIssuer = lesActive.entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uTakerGetsIssuerID));
|
|
||||||
|
|
||||||
if (!sleGetsIssuer)
|
uint32 uTransferRate = lesActive.rippleTransferRate(uTakerGetsIssuerID);
|
||||||
{
|
|
||||||
// Order book can not exist if TakerGetsIssuer account does not exist.
|
|
||||||
|
|
||||||
nothing();
|
while (!bDone) {
|
||||||
}
|
if (bDirectAdvance) {
|
||||||
else
|
bDirectAdvance = false;
|
||||||
{
|
|
||||||
while (!bDone) {
|
|
||||||
if (bDirectAdvance) {
|
|
||||||
bDirectAdvance = false;
|
|
||||||
|
|
||||||
cLog(lsTRACE) << boost::str(boost::format("getBookPage: bDirectAdvance"));
|
cLog(lsTRACE) << boost::str(boost::format("getBookPage: bDirectAdvance"));
|
||||||
|
|
||||||
sleOfferDir = lesActive.entryCache(ltDIR_NODE, lpLedger->getNextLedgerIndex(uTipIndex, uBookEnd));
|
sleOfferDir = lesActive.entryCache(ltDIR_NODE, lpLedger->getNextLedgerIndex(uTipIndex, uBookEnd));
|
||||||
if (!sleOfferDir)
|
if (!sleOfferDir)
|
||||||
|
{
|
||||||
|
cLog(lsTRACE) << boost::str(boost::format("getBookPage: bDone"));
|
||||||
|
bDone = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uTipIndex = sleOfferDir->getIndex();
|
||||||
|
saDirRate = STAmount::setRate(Ledger::getQuality(uTipIndex));
|
||||||
|
SLE::pointer sleBookNode;
|
||||||
|
|
||||||
|
lesActive.dirFirst(uTipIndex, sleBookNode, uBookEntry, uOfferIndex);
|
||||||
|
|
||||||
|
cLog(lsTRACE) << boost::str(boost::format("getBookPage: uTipIndex=%s") % uTipIndex);
|
||||||
|
cLog(lsTRACE) << boost::str(boost::format("getBookPage: uOfferIndex=%s") % uOfferIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bDone)
|
||||||
|
{
|
||||||
|
SLE::pointer sleOffer = lesActive.entryCache(ltOFFER, uOfferIndex);
|
||||||
|
const uint160 uOfferOwnerID = sleOffer->getFieldAccount(sfAccount).getAccountID();
|
||||||
|
STAmount saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
|
||||||
|
STAmount saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
|
||||||
|
STAmount saOwnerFunds;
|
||||||
|
|
||||||
|
if (uTakerGetsIssuerID == uOfferOwnerID)
|
||||||
|
{
|
||||||
|
// If offer is selling issuer's own IOUs, it is fully funded.
|
||||||
|
saOwnerFunds = saTakerGets;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boost::unordered_map<uint160, STAmount>::const_iterator umBalanceEntry = umBalance.find(uOfferOwnerID);
|
||||||
|
|
||||||
|
if (umBalanceEntry != umBalance.end())
|
||||||
{
|
{
|
||||||
cLog(lsTRACE) << boost::str(boost::format("getBookPage: bDone"));
|
// Found in running balance table.
|
||||||
bDone = true;
|
|
||||||
|
saOwnerFunds = umBalanceEntry->second;
|
||||||
|
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saOwnerFunds=%s (cached)") % saOwnerFunds.getFullText());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uTipIndex = sleOfferDir->getIndex();
|
// Did not find balance in table.
|
||||||
saDirRate = STAmount::setRate(Ledger::getQuality(uTipIndex));
|
|
||||||
SLE::pointer sleBookNode;
|
|
||||||
|
|
||||||
lesActive.dirFirst(uTipIndex, sleBookNode, uBookEntry, uOfferIndex);
|
saOwnerFunds = lesActive.accountHolds(uOfferOwnerID, uTakerGetsCurrencyID, uTakerGetsIssuerID);
|
||||||
|
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saOwnerFunds=%s (new)") % saOwnerFunds.getFullText());
|
||||||
|
if (saOwnerFunds.isNegative())
|
||||||
|
{
|
||||||
|
// Treat negative funds as zero.
|
||||||
|
|
||||||
cLog(lsTRACE) << boost::str(boost::format("getBookPage: uTipIndex=%s") % uTipIndex);
|
saOwnerFunds.zero();
|
||||||
cLog(lsTRACE) << boost::str(boost::format("getBookPage: uOfferIndex=%s") % uOfferIndex);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bDone)
|
Json::Value jvOffer = sleOffer->getJson(0);
|
||||||
|
|
||||||
|
STAmount saTakerGetsFunded;
|
||||||
|
STAmount saOwnerFundsLimit;
|
||||||
|
uint32 uOfferRate;
|
||||||
|
|
||||||
|
|
||||||
|
if (uTransferRate != QUALITY_ONE // Have a tranfer fee.
|
||||||
|
&& uTakerID != uTakerGetsIssuerID // Not taking offers of own IOUs.
|
||||||
|
&& uTakerGetsIssuerID != uOfferOwnerID) { // Offer owner not issuing ownfunds
|
||||||
|
// Need to charge a transfer fee to offer owner.
|
||||||
|
uOfferRate = uTransferRate;
|
||||||
|
saOwnerFundsLimit = STAmount::divide(saOwnerFunds, STAmount(CURRENCY_ONE, ACCOUNT_ONE, uOfferRate, -9));
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
SLE::pointer sleOffer = lesActive.entryCache(ltOFFER, uOfferIndex);
|
uOfferRate = QUALITY_ONE;
|
||||||
const uint160 uOfferOwnerID = sleOffer->getFieldAccount(sfAccount).getAccountID();
|
saOwnerFundsLimit = saOwnerFunds;
|
||||||
STAmount saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
|
}
|
||||||
STAmount saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
|
|
||||||
STAmount saOwnerFunds;
|
|
||||||
|
|
||||||
if (uTakerGetsIssuerID == uOfferOwnerID)
|
if (saOwnerFundsLimit >= saTakerGets)
|
||||||
{
|
{
|
||||||
// If offer is selling issuer's own IOUs, it is fully funded.
|
// Sufficient funds no shenanigans.
|
||||||
saOwnerFunds = saTakerGets;
|
saTakerGetsFunded = saTakerGets;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
boost::unordered_map<uint160, STAmount>::const_iterator umBalanceEntry = umBalance.find(uOfferOwnerID);
|
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saTakerGets=%s") % saTakerGets.getFullText());
|
||||||
|
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saTakerPays=%s") % saTakerPays.getFullText());
|
||||||
|
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saOwnerFunds=%s") % saOwnerFunds.getFullText());
|
||||||
|
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saDirRate=%s") % saDirRate.getText());
|
||||||
|
// cLog(lsINFO) << boost::str(boost::format("getBookPage: multiply=%s") % STAmount::multiply(saTakerGetsFunded, saDirRate).getFullText());
|
||||||
|
// cLog(lsINFO) << boost::str(boost::format("getBookPage: multiply=%s") % STAmount::multiply(saTakerGetsFunded, saDirRate, saTakerPays).getFullText());
|
||||||
|
STAmount saTakerPaysFunded;
|
||||||
|
|
||||||
if (umBalanceEntry != umBalance.end())
|
saTakerGetsFunded = saOwnerFundsLimit;
|
||||||
{
|
saTakerPaysFunded = std::min(saTakerPays, STAmount::multiply(saTakerGetsFunded, saDirRate, saTakerPays));
|
||||||
// Found in running balance table.
|
|
||||||
|
|
||||||
saOwnerFunds = umBalanceEntry->second;
|
// Only provide, if not fully funded.
|
||||||
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saOwnerFunds=%s (cached)") % saOwnerFunds.getFullText());
|
jvOffer["taker_gets_funded"] = saTakerGetsFunded.getJson(0);
|
||||||
}
|
jvOffer["taker_pays_funded"] = saTakerPaysFunded.getJson(0);
|
||||||
else
|
|
||||||
{
|
|
||||||
// Did not find balance in table.
|
|
||||||
|
|
||||||
saOwnerFunds = lesActive.accountHolds(uOfferOwnerID, uTakerGetsCurrencyID, uTakerGetsIssuerID);
|
}
|
||||||
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saOwnerFunds=%s (new)") % saOwnerFunds.getFullText());
|
STAmount saOwnerPays = QUALITY_ONE == uOfferRate
|
||||||
if (saOwnerFunds.isNegative())
|
? saTakerGetsFunded
|
||||||
saOwnerFunds.zero();
|
: std::min(saOwnerFunds, STAmount::multiply(saTakerGetsFunded, STAmount(CURRENCY_ONE, ACCOUNT_ONE, uOfferRate, -9)));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Json::Value jvOffer = sleOffer->getJson(0);
|
STAmount saOwnerBalance = saOwnerFunds-saOwnerPays;
|
||||||
|
|
||||||
STAmount saTakerGetsFunded;
|
umBalance[uOfferOwnerID] = saOwnerBalance;
|
||||||
|
|
||||||
if (saOwnerFunds >= saTakerGets)
|
if (!saOwnerFunds.isZero() || uOfferOwnerID == uTakerID)
|
||||||
{
|
{
|
||||||
// Sufficient funds no shenanigans.
|
// Only provide funded offers and offers of the taker.
|
||||||
saTakerGetsFunded = saTakerGets;
|
jvOffers.append(jvOffer);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saTakerGets=%s") % saTakerGets.getFullText());
|
|
||||||
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saTakerPays=%s") % saTakerPays.getFullText());
|
|
||||||
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saOwnerFunds=%s") % saOwnerFunds.getFullText());
|
|
||||||
// cLog(lsINFO) << boost::str(boost::format("getBookPage: saDirRate=%s") % saDirRate.getText());
|
|
||||||
// cLog(lsINFO) << boost::str(boost::format("getBookPage: multiply=%s") % STAmount::multiply(saTakerGetsFunded, saDirRate).getFullText());
|
|
||||||
// cLog(lsINFO) << boost::str(boost::format("getBookPage: multiply=%s") % STAmount::multiply(saTakerGetsFunded, saDirRate, saTakerPays).getFullText());
|
|
||||||
STAmount saTakerPaysFunded;
|
|
||||||
|
|
||||||
saTakerGetsFunded = saOwnerFunds;
|
if (!lesActive.dirNext(uTipIndex, sleOfferDir, uBookEntry, uOfferIndex))
|
||||||
saTakerPaysFunded = std::min(saTakerPays, STAmount::multiply(saTakerGetsFunded, saDirRate, saTakerPays));
|
{
|
||||||
|
bDirectAdvance = true;
|
||||||
// Only provide, if not fully funded.
|
}
|
||||||
jvOffer["taker_gets_funded"] = saTakerGetsFunded.getJson(0);
|
else
|
||||||
jvOffer["taker_pays_funded"] = saTakerPaysFunded.getJson(0);
|
{
|
||||||
}
|
cLog(lsTRACE) << boost::str(boost::format("getBookPage: uOfferIndex=%s") % uOfferIndex);
|
||||||
|
|
||||||
STAmount saOwnerBalance = saOwnerFunds-saTakerGetsFunded;
|
|
||||||
|
|
||||||
umBalance[uOfferOwnerID] = saOwnerBalance;
|
|
||||||
|
|
||||||
if (!saOwnerFunds.isZero() || uOfferOwnerID == uTakerID)
|
|
||||||
{
|
|
||||||
// Only provide funded offers and offers of the taker.
|
|
||||||
jvOffers.append(jvOffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lesActive.dirNext(uTipIndex, sleOfferDir, uBookEntry, uOfferIndex))
|
|
||||||
{
|
|
||||||
bDirectAdvance = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cLog(lsTRACE) << boost::str(boost::format("getBookPage: uOfferIndex=%s") % uOfferIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user