mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -4,7 +4,53 @@ SETUP_LOG();
|
||||
|
||||
TER AccountSetTransactor::doApply()
|
||||
{
|
||||
cLog(lsINFO) << "doAccountSet>";
|
||||
cLog(lsINFO) << "AccountSet>";
|
||||
|
||||
const uint32 uTxFlags = mTxn.getFlags();
|
||||
|
||||
#if ENABLE_REQUIRE_DEST_TAG
|
||||
const uint32 uFlagsIn = mTxnAccount->getFieldU32(sfFlags);
|
||||
uint32 uFlagsOut = uFlagsIn;
|
||||
|
||||
if (uTxFlags & tfAccountSetMask)
|
||||
#else
|
||||
if (uTxFlags)
|
||||
#endif
|
||||
{
|
||||
cLog(lsINFO) << "AccountSet: Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
#if ENABLE_REQUIRE_DEST_TAG
|
||||
//
|
||||
// RequireDestTag
|
||||
//
|
||||
|
||||
if ((tfRequireDestTag|tfOptionalDestTag) == (uTxFlags & (tfRequireDestTag|tfOptionalDestTag)))
|
||||
{
|
||||
cLog(lsINFO) << "AccountSet: Malformed transaction: Contradictory flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (uTxFlags & tfRequireDestTag)
|
||||
{
|
||||
cLog(lsINFO) << "AccountSet: Set RequireDestTag.";
|
||||
|
||||
uFlagsOut |= lsfRequireDestTag;
|
||||
}
|
||||
|
||||
if (uTxFlags & tfOptionalDestTag)
|
||||
{
|
||||
cLog(lsINFO) << "AccountSet: Clear RequireDestTag.";
|
||||
|
||||
uFlagsOut &= ~lsfRequireDestTag;
|
||||
}
|
||||
|
||||
if (uFlagsIn != uFlagsOut)
|
||||
mTxnAccount->setFieldU32(sfFlags, uFlagsOut);
|
||||
#endif
|
||||
|
||||
//
|
||||
// EmailHash
|
||||
@@ -16,13 +62,13 @@ TER AccountSetTransactor::doApply()
|
||||
|
||||
if (!uHash)
|
||||
{
|
||||
cLog(lsINFO) << "doAccountSet: unset email hash";
|
||||
cLog(lsINFO) << "AccountSet: unset email hash";
|
||||
|
||||
mTxnAccount->makeFieldAbsent(sfEmailHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
cLog(lsINFO) << "doAccountSet: set email hash";
|
||||
cLog(lsINFO) << "AccountSet: set email hash";
|
||||
|
||||
mTxnAccount->setFieldH128(sfEmailHash, uHash);
|
||||
}
|
||||
@@ -38,13 +84,13 @@ TER AccountSetTransactor::doApply()
|
||||
|
||||
if (!uHash)
|
||||
{
|
||||
cLog(lsINFO) << "doAccountSet: unset wallet locator";
|
||||
cLog(lsINFO) << "AccountSet: unset wallet locator";
|
||||
|
||||
mTxnAccount->makeFieldAbsent(sfEmailHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
cLog(lsINFO) << "doAccountSet: set wallet locator";
|
||||
cLog(lsINFO) << "AccountSet: set wallet locator";
|
||||
|
||||
mTxnAccount->setFieldH256(sfWalletLocator, uHash);
|
||||
}
|
||||
@@ -60,7 +106,7 @@ TER AccountSetTransactor::doApply()
|
||||
}
|
||||
else
|
||||
{
|
||||
cLog(lsINFO) << "doAccountSet: set message key";
|
||||
cLog(lsINFO) << "AccountSet: set message key";
|
||||
|
||||
mTxnAccount->setFieldVL(sfMessageKey, mTxn.getFieldVL(sfMessageKey));
|
||||
}
|
||||
@@ -75,13 +121,13 @@ TER AccountSetTransactor::doApply()
|
||||
|
||||
if (vucDomain.empty())
|
||||
{
|
||||
cLog(lsINFO) << "doAccountSet: unset domain";
|
||||
cLog(lsINFO) << "AccountSet: unset domain";
|
||||
|
||||
mTxnAccount->makeFieldAbsent(sfDomain);
|
||||
}
|
||||
else
|
||||
{
|
||||
cLog(lsINFO) << "doAccountSet: set domain";
|
||||
cLog(lsINFO) << "AccountSet: set domain";
|
||||
|
||||
mTxnAccount->setFieldVL(sfDomain, vucDomain);
|
||||
}
|
||||
@@ -97,25 +143,27 @@ TER AccountSetTransactor::doApply()
|
||||
|
||||
if (!uRate || uRate == QUALITY_ONE)
|
||||
{
|
||||
cLog(lsINFO) << "doAccountSet: unset transfer rate";
|
||||
cLog(lsINFO) << "AccountSet: unset transfer rate";
|
||||
|
||||
mTxnAccount->makeFieldAbsent(sfTransferRate);
|
||||
}
|
||||
else if (uRate > QUALITY_ONE)
|
||||
{
|
||||
cLog(lsINFO) << "doAccountSet: set transfer rate";
|
||||
cLog(lsINFO) << "AccountSet: set transfer rate";
|
||||
|
||||
mTxnAccount->setFieldU32(sfTransferRate, uRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
cLog(lsINFO) << "doAccountSet: bad transfer rate";
|
||||
cLog(lsINFO) << "AccountSet: bad transfer rate";
|
||||
|
||||
return temBAD_TRANSFER_RATE;
|
||||
}
|
||||
}
|
||||
|
||||
cLog(lsINFO) << "doAccountSet<";
|
||||
cLog(lsINFO) << "AccountSet<";
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "SerializedObject.h"
|
||||
|
||||
#define ENABLE_REQUIRE_DEST_TAG 0
|
||||
|
||||
// Used as the type of a transaction or the type of a ledger entry.
|
||||
enum LedgerEntryType
|
||||
{
|
||||
@@ -40,6 +42,9 @@ enum LedgerSpecificFlags
|
||||
{
|
||||
// ltACCOUNT_ROOT
|
||||
lsfPasswordSpent = 0x00010000, // True, if password set fee is spent.
|
||||
#if ENABLE_REQUIRE_DEST_TAG
|
||||
lsfRequireDestTag = 0x00020000, // True, to require a DestinationTag for payments.
|
||||
#endif
|
||||
|
||||
// ltOFFER
|
||||
lsfPassive = 0x00010000,
|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
#include "OfferCancelTransactor.h"
|
||||
#include "Log.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
TER OfferCancelTransactor::doApply()
|
||||
{
|
||||
TER terResult;
|
||||
const uint32 uOfferSequence = mTxn.getFieldU32(sfOfferSequence);
|
||||
const uint32 uAccountSequenceNext = mTxnAccount->getFieldU32(sfSequence);
|
||||
|
||||
Log(lsDEBUG) << "doOfferCancel: uAccountSequenceNext=" << uAccountSequenceNext << " uOfferSequence=" << uOfferSequence;
|
||||
cLog(lsDEBUG) << "OfferCancel: uAccountSequenceNext=" << uAccountSequenceNext << " uOfferSequence=" << uOfferSequence;
|
||||
|
||||
const uint32 uTxFlags = mTxn.getFlags();
|
||||
|
||||
if (uTxFlags)
|
||||
{
|
||||
cLog(lsINFO) << "OfferCancel: Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (!uOfferSequence || uAccountSequenceNext-1 <= uOfferSequence)
|
||||
{
|
||||
Log(lsINFO) << "doOfferCancel: uAccountSequenceNext=" << uAccountSequenceNext << " uOfferSequence=" << uOfferSequence;
|
||||
cLog(lsINFO) << "OfferCancel: uAccountSequenceNext=" << uAccountSequenceNext << " uOfferSequence=" << uOfferSequence;
|
||||
|
||||
terResult = temBAD_SEQUENCE;
|
||||
}
|
||||
@@ -22,13 +33,13 @@ TER OfferCancelTransactor::doApply()
|
||||
|
||||
if (sleOffer)
|
||||
{
|
||||
Log(lsWARNING) << "doOfferCancel: uOfferSequence=" << uOfferSequence;
|
||||
cLog(lsWARNING) << "OfferCancel: uOfferSequence=" << uOfferSequence;
|
||||
|
||||
terResult = mEngine->getNodes().offerDelete(sleOffer, uOfferIndex, mTxnAccountID);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsWARNING) << "doOfferCancel: offer not found: "
|
||||
cLog(lsWARNING) << "OfferCancel: offer not found: "
|
||||
<< RippleAddress::createHumanAccountID(mTxnAccountID)
|
||||
<< " : " << uOfferSequence
|
||||
<< " : " << uOfferIndex.ToString();
|
||||
|
||||
@@ -256,13 +256,13 @@ TER OfferCreateTransactor::takeOffers(
|
||||
|
||||
TER OfferCreateTransactor::doApply()
|
||||
{
|
||||
cLog(lsWARNING) << "doOfferCreate> " << mTxn.getJson(0);
|
||||
cLog(lsWARNING) << "OfferCreate> " << mTxn.getJson(0);
|
||||
const uint32 uTxFlags = mTxn.getFlags();
|
||||
const bool bPassive = isSetBit(uTxFlags, tfPassive);
|
||||
STAmount saTakerPays = mTxn.getFieldAmount(sfTakerPays);
|
||||
STAmount saTakerGets = mTxn.getFieldAmount(sfTakerGets);
|
||||
|
||||
cLog(lsINFO) << boost::str(boost::format("doOfferCreate: saTakerPays=%s saTakerGets=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("OfferCreate: saTakerPays=%s saTakerGets=%s")
|
||||
% saTakerPays.getFullText()
|
||||
% saTakerGets.getFullText());
|
||||
|
||||
@@ -274,7 +274,7 @@ TER OfferCreateTransactor::doApply()
|
||||
|
||||
const uint256 uLedgerIndex = Ledger::getOfferIndex(mTxnAccountID, uSequence);
|
||||
|
||||
cLog(lsINFO) << "doOfferCreate: Creating offer node: " << uLedgerIndex.ToString() << " uSequence=" << uSequence;
|
||||
cLog(lsINFO) << "OfferCreate: Creating offer node: " << uLedgerIndex.ToString() << " uSequence=" << uSequence;
|
||||
|
||||
const uint160 uPaysCurrency = saTakerPays.getCurrency();
|
||||
const uint160 uGetsCurrency = saTakerGets.getCurrency();
|
||||
@@ -287,49 +287,49 @@ TER OfferCreateTransactor::doApply()
|
||||
|
||||
if (uTxFlags & tfOfferCreateMask)
|
||||
{
|
||||
cLog(lsINFO) << "doOfferCreate: Malformed transaction: Invalid flags set.";
|
||||
cLog(lsINFO) << "OfferCreate: Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
else if (bHaveExpiration && !uExpiration)
|
||||
{
|
||||
cLog(lsWARNING) << "doOfferCreate: Malformed offer: bad expiration";
|
||||
cLog(lsWARNING) << "OfferCreate: Malformed offer: bad expiration";
|
||||
|
||||
terResult = temBAD_EXPIRATION;
|
||||
}
|
||||
else if (bHaveExpiration && mEngine->getLedger()->getParentCloseTimeNC() >= uExpiration)
|
||||
{
|
||||
cLog(lsWARNING) << "doOfferCreate: Expired transaction: offer expired";
|
||||
cLog(lsWARNING) << "OfferCreate: Expired transaction: offer expired";
|
||||
|
||||
terResult = tesSUCCESS; // Only charged fee.
|
||||
}
|
||||
else if (saTakerPays.isNative() && saTakerGets.isNative())
|
||||
{
|
||||
cLog(lsWARNING) << "doOfferCreate: Malformed offer: XRP for XRP";
|
||||
cLog(lsWARNING) << "OfferCreate: Malformed offer: XRP for XRP";
|
||||
|
||||
terResult = temBAD_OFFER;
|
||||
}
|
||||
else if (!saTakerPays.isPositive() || !saTakerGets.isPositive())
|
||||
{
|
||||
cLog(lsWARNING) << "doOfferCreate: Malformed offer: bad amount";
|
||||
cLog(lsWARNING) << "OfferCreate: Malformed offer: bad amount";
|
||||
|
||||
terResult = temBAD_OFFER;
|
||||
}
|
||||
else if (uPaysCurrency == uGetsCurrency && uPaysIssuerID == uGetsIssuerID)
|
||||
{
|
||||
cLog(lsWARNING) << "doOfferCreate: Malformed offer: redundant offer";
|
||||
cLog(lsWARNING) << "OfferCreate: Malformed offer: redundant offer";
|
||||
|
||||
terResult = temREDUNDANT;
|
||||
}
|
||||
else if (saTakerPays.isNative() != !uPaysIssuerID || saTakerGets.isNative() != !uGetsIssuerID)
|
||||
{
|
||||
cLog(lsWARNING) << "doOfferCreate: Malformed offer: bad issuer";
|
||||
cLog(lsWARNING) << "OfferCreate: Malformed offer: bad issuer";
|
||||
|
||||
terResult = temBAD_ISSUER;
|
||||
}
|
||||
else if (!mEngine->getNodes().accountFunds(mTxnAccountID, saTakerGets).isPositive())
|
||||
{
|
||||
cLog(lsWARNING) << "doOfferCreate: delay: Offers must be at least partially funded.";
|
||||
cLog(lsWARNING) << "OfferCreate: delay: Offers must be at least partially funded.";
|
||||
|
||||
terResult = tecUNFUNDED;
|
||||
}
|
||||
@@ -340,7 +340,7 @@ TER OfferCreateTransactor::doApply()
|
||||
|
||||
if (!sleTakerPays)
|
||||
{
|
||||
cLog(lsWARNING) << "doOfferCreate: delay: can't receive IOUs from non-existent issuer: " << RippleAddress::createHumanAccountID(uPaysIssuerID);
|
||||
cLog(lsWARNING) << "OfferCreate: delay: can't receive IOUs from non-existent issuer: " << RippleAddress::createHumanAccountID(uPaysIssuerID);
|
||||
|
||||
terResult = terNO_ACCOUNT;
|
||||
}
|
||||
@@ -353,13 +353,13 @@ TER OfferCreateTransactor::doApply()
|
||||
{
|
||||
const uint256 uTakeBookBase = Ledger::getBookBase(uGetsCurrency, uGetsIssuerID, uPaysCurrency, uPaysIssuerID);
|
||||
|
||||
cLog(lsINFO) << boost::str(boost::format("doOfferCreate: take against book: %s for %s -> %s")
|
||||
cLog(lsINFO) << boost::str(boost::format("OfferCreate: take against book: %s for %s -> %s")
|
||||
% uTakeBookBase.ToString()
|
||||
% saTakerGets.getFullText()
|
||||
% saTakerPays.getFullText());
|
||||
|
||||
// Take using the parameters of the offer.
|
||||
cLog(lsWARNING) << "doOfferCreate: takeOffers: BEFORE saTakerGets=" << saTakerGets.getFullText();
|
||||
cLog(lsWARNING) << "OfferCreate: takeOffers: BEFORE saTakerGets=" << saTakerGets.getFullText();
|
||||
terResult = takeOffers(
|
||||
bPassive,
|
||||
uTakeBookBase,
|
||||
@@ -371,11 +371,11 @@ TER OfferCreateTransactor::doApply()
|
||||
saOfferGot // How much was got.
|
||||
);
|
||||
|
||||
cLog(lsWARNING) << "doOfferCreate: takeOffers=" << terResult;
|
||||
cLog(lsWARNING) << "doOfferCreate: takeOffers: saOfferPaid=" << saOfferPaid.getFullText();
|
||||
cLog(lsWARNING) << "doOfferCreate: takeOffers: saOfferGot=" << saOfferGot.getFullText();
|
||||
cLog(lsWARNING) << "doOfferCreate: takeOffers: saTakerPays=" << saTakerPays.getFullText();
|
||||
cLog(lsWARNING) << "doOfferCreate: takeOffers: AFTER saTakerGets=" << saTakerGets.getFullText();
|
||||
cLog(lsWARNING) << "OfferCreate: takeOffers=" << terResult;
|
||||
cLog(lsWARNING) << "OfferCreate: takeOffers: saOfferPaid=" << saOfferPaid.getFullText();
|
||||
cLog(lsWARNING) << "OfferCreate: takeOffers: saOfferGot=" << saOfferGot.getFullText();
|
||||
cLog(lsWARNING) << "OfferCreate: takeOffers: saTakerPays=" << saTakerPays.getFullText();
|
||||
cLog(lsWARNING) << "OfferCreate: takeOffers: AFTER saTakerGets=" << saTakerGets.getFullText();
|
||||
|
||||
if (tesSUCCESS == terResult)
|
||||
{
|
||||
@@ -384,13 +384,13 @@ TER OfferCreateTransactor::doApply()
|
||||
}
|
||||
}
|
||||
|
||||
cLog(lsWARNING) << "doOfferCreate: takeOffers: saTakerPays=" << saTakerPays.getFullText();
|
||||
cLog(lsWARNING) << "doOfferCreate: takeOffers: saTakerGets=" << saTakerGets.getFullText();
|
||||
cLog(lsWARNING) << "doOfferCreate: takeOffers: mTxnAccountID=" << RippleAddress::createHumanAccountID(mTxnAccountID);
|
||||
cLog(lsWARNING) << "doOfferCreate: takeOffers: FUNDS=" << mEngine->getNodes().accountFunds(mTxnAccountID, saTakerGets).getFullText();
|
||||
cLog(lsWARNING) << "OfferCreate: takeOffers: saTakerPays=" << saTakerPays.getFullText();
|
||||
cLog(lsWARNING) << "OfferCreate: takeOffers: saTakerGets=" << saTakerGets.getFullText();
|
||||
cLog(lsWARNING) << "OfferCreate: takeOffers: mTxnAccountID=" << RippleAddress::createHumanAccountID(mTxnAccountID);
|
||||
cLog(lsWARNING) << "OfferCreate: takeOffers: FUNDS=" << mEngine->getNodes().accountFunds(mTxnAccountID, saTakerGets).getFullText();
|
||||
|
||||
// cLog(lsWARNING) << "doOfferCreate: takeOffers: uPaysIssuerID=" << RippleAddress::createHumanAccountID(uPaysIssuerID);
|
||||
// cLog(lsWARNING) << "doOfferCreate: takeOffers: uGetsIssuerID=" << RippleAddress::createHumanAccountID(uGetsIssuerID);
|
||||
// cLog(lsWARNING) << "OfferCreate: takeOffers: uPaysIssuerID=" << RippleAddress::createHumanAccountID(uPaysIssuerID);
|
||||
// cLog(lsWARNING) << "OfferCreate: takeOffers: uGetsIssuerID=" << RippleAddress::createHumanAccountID(uGetsIssuerID);
|
||||
|
||||
if (tesSUCCESS != terResult
|
||||
|| !saTakerPays // Wants nothing more.
|
||||
@@ -424,7 +424,7 @@ TER OfferCreateTransactor::doApply()
|
||||
else
|
||||
{
|
||||
// We need to place the remainder of the offer into its order book.
|
||||
cLog(lsINFO) << boost::str(boost::format("doOfferCreate: offer not fully consumed: saTakerPays=%s saTakerGets=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("OfferCreate: offer not fully consumed: saTakerPays=%s saTakerGets=%s")
|
||||
% saTakerPays.getFullText()
|
||||
% saTakerGets.getFullText());
|
||||
|
||||
@@ -440,7 +440,7 @@ TER OfferCreateTransactor::doApply()
|
||||
|
||||
uint256 uBookBase = Ledger::getBookBase(uPaysCurrency, uPaysIssuerID, uGetsCurrency, uGetsIssuerID);
|
||||
|
||||
cLog(lsINFO) << boost::str(boost::format("doOfferCreate: adding to book: %s : %s/%s -> %s/%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("OfferCreate: adding to book: %s : %s/%s -> %s/%s")
|
||||
% uBookBase.ToString()
|
||||
% saTakerPays.getHumanCurrency()
|
||||
% RippleAddress::createHumanAccountID(saTakerPays.getIssuer())
|
||||
@@ -457,13 +457,13 @@ TER OfferCreateTransactor::doApply()
|
||||
|
||||
if (tesSUCCESS == terResult)
|
||||
{
|
||||
cLog(lsWARNING) << "doOfferCreate: sfAccount=" << RippleAddress::createHumanAccountID(mTxnAccountID);
|
||||
cLog(lsWARNING) << "doOfferCreate: uPaysIssuerID=" << RippleAddress::createHumanAccountID(uPaysIssuerID);
|
||||
cLog(lsWARNING) << "doOfferCreate: uGetsIssuerID=" << RippleAddress::createHumanAccountID(uGetsIssuerID);
|
||||
cLog(lsWARNING) << "doOfferCreate: saTakerPays.isNative()=" << saTakerPays.isNative();
|
||||
cLog(lsWARNING) << "doOfferCreate: saTakerGets.isNative()=" << saTakerGets.isNative();
|
||||
cLog(lsWARNING) << "doOfferCreate: uPaysCurrency=" << saTakerPays.getHumanCurrency();
|
||||
cLog(lsWARNING) << "doOfferCreate: uGetsCurrency=" << saTakerGets.getHumanCurrency();
|
||||
cLog(lsWARNING) << "OfferCreate: sfAccount=" << RippleAddress::createHumanAccountID(mTxnAccountID);
|
||||
cLog(lsWARNING) << "OfferCreate: uPaysIssuerID=" << RippleAddress::createHumanAccountID(uPaysIssuerID);
|
||||
cLog(lsWARNING) << "OfferCreate: uGetsIssuerID=" << RippleAddress::createHumanAccountID(uGetsIssuerID);
|
||||
cLog(lsWARNING) << "OfferCreate: saTakerPays.isNative()=" << saTakerPays.isNative();
|
||||
cLog(lsWARNING) << "OfferCreate: saTakerGets.isNative()=" << saTakerGets.isNative();
|
||||
cLog(lsWARNING) << "OfferCreate: uPaysCurrency=" << saTakerPays.getHumanCurrency();
|
||||
cLog(lsWARNING) << "OfferCreate: uGetsCurrency=" << saTakerGets.getHumanCurrency();
|
||||
|
||||
SLE::pointer sleOffer = mEngine->entryCreate(ltOFFER, uLedgerIndex);
|
||||
|
||||
@@ -481,13 +481,13 @@ TER OfferCreateTransactor::doApply()
|
||||
if (bPassive)
|
||||
sleOffer->setFlag(lsfPassive);
|
||||
|
||||
cLog(lsINFO) << boost::str(boost::format("doOfferCreate: final terResult=%s sleOffer=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("OfferCreate: final terResult=%s sleOffer=%s")
|
||||
% transToken(terResult)
|
||||
% sleOffer->getJson(0));
|
||||
}
|
||||
}
|
||||
|
||||
tLog(tesSUCCESS != terResult, lsINFO) << boost::str(boost::format("doOfferCreate: final terResult=%s") % transToken(terResult));
|
||||
tLog(tesSUCCESS != terResult, lsINFO) << boost::str(boost::format("OfferCreate: final terResult=%s") % transToken(terResult));
|
||||
|
||||
return terResult;
|
||||
}
|
||||
|
||||
@@ -26,37 +26,37 @@ TER PaymentTransactor::doApply()
|
||||
const uint160 uSrcCurrency = saMaxAmount.getCurrency();
|
||||
const uint160 uDstCurrency = saDstAmount.getCurrency();
|
||||
|
||||
cLog(lsINFO) << boost::str(boost::format("doPayment> saMaxAmount=%s saDstAmount=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("Payment> saMaxAmount=%s saDstAmount=%s")
|
||||
% saMaxAmount.getFullText()
|
||||
% saDstAmount.getFullText());
|
||||
|
||||
if (uTxFlags & tfPaymentMask)
|
||||
{
|
||||
cLog(lsINFO) << "doPayment: Malformed transaction: Invalid flags set.";
|
||||
cLog(lsINFO) << "Payment: Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
else if (!uDstAccountID)
|
||||
{
|
||||
cLog(lsINFO) << "doPayment: Malformed transaction: Payment destination account not specified.";
|
||||
cLog(lsINFO) << "Payment: Malformed transaction: Payment destination account not specified.";
|
||||
|
||||
return temDST_NEEDED;
|
||||
}
|
||||
else if (bMax && !saMaxAmount.isPositive())
|
||||
{
|
||||
cLog(lsINFO) << "doPayment: Malformed transaction: bad max amount: " << saMaxAmount.getFullText();
|
||||
cLog(lsINFO) << "Payment: Malformed transaction: bad max amount: " << saMaxAmount.getFullText();
|
||||
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
else if (!saDstAmount.isPositive())
|
||||
{
|
||||
cLog(lsINFO) << "doPayment: Malformed transaction: bad dst amount: " << saDstAmount.getFullText();
|
||||
cLog(lsINFO) << "Payment: Malformed transaction: bad dst amount: " << saDstAmount.getFullText();
|
||||
|
||||
return temBAD_AMOUNT;
|
||||
}
|
||||
else if (mTxnAccountID == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths)
|
||||
{
|
||||
cLog(lsINFO) << boost::str(boost::format("doPayment: Malformed transaction: Redundant transaction: src=%s, dst=%s, src_cur=%s, dst_cur=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("Payment: Malformed transaction: Redundant transaction: src=%s, dst=%s, src_cur=%s, dst_cur=%s")
|
||||
% mTxnAccountID.ToString()
|
||||
% uDstAccountID.ToString()
|
||||
% uSrcCurrency.ToString()
|
||||
@@ -68,7 +68,7 @@ TER PaymentTransactor::doApply()
|
||||
&& ((saMaxAmount == saDstAmount && saMaxAmount.getCurrency() == saDstAmount.getCurrency())
|
||||
|| (saDstAmount.isNative() && saMaxAmount.isNative())))
|
||||
{
|
||||
cLog(lsINFO) << "doPayment: Malformed transaction: bad SendMax.";
|
||||
cLog(lsINFO) << "Payment: Malformed transaction: bad SendMax.";
|
||||
|
||||
return temINVALID;
|
||||
}
|
||||
@@ -80,14 +80,14 @@ TER PaymentTransactor::doApply()
|
||||
|
||||
if (!saDstAmount.isNative())
|
||||
{
|
||||
cLog(lsINFO) << "doPayment: Delay transaction: Destination account does not exist.";
|
||||
cLog(lsINFO) << "Payment: Delay transaction: Destination account does not exist.";
|
||||
|
||||
// Another transaction could create the account and then this transaction would succeed.
|
||||
return tecNO_DST;
|
||||
}
|
||||
else if (saDstAmount.getNValue() < mEngine->getLedger()->getReserve(0)) // Reserve is not scaled by load.
|
||||
{
|
||||
cLog(lsINFO) << "doPayment: Delay transaction: Destination account does not exist. Insufficent payment to create account.";
|
||||
cLog(lsINFO) << "Payment: Delay transaction: Destination account does not exist. Insufficent payment to create account.";
|
||||
|
||||
// Another transaction could create the account and then this transaction would succeed.
|
||||
return tecNO_DST_INSUF_XRP;
|
||||
@@ -99,6 +99,14 @@ TER PaymentTransactor::doApply()
|
||||
sleDst->setFieldAccount(sfAccount, uDstAccountID);
|
||||
sleDst->setFieldU32(sfSequence, 1);
|
||||
}
|
||||
#if ENABLE_REQUIRE_DEST_TAG
|
||||
else if ((sleDst->getFlags() & lsfRequireDestTag) && !mTxn.isFieldPresent(sfDestinationTag))
|
||||
{
|
||||
cLog(lsINFO) << "Payment: Malformed transaction: DestinationTag required.";
|
||||
|
||||
return temINVALID;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
mEngine->entryModify(sleDst);
|
||||
@@ -148,7 +156,7 @@ TER PaymentTransactor::doApply()
|
||||
{
|
||||
// Vote no. However, transaction might succeed, if applied in a different order.
|
||||
cLog(lsINFO) << "";
|
||||
cLog(lsINFO) << boost::str(boost::format("doPayment: Delay transaction: Insufficient funds: %s / %s (%d)")
|
||||
cLog(lsINFO) << boost::str(boost::format("Payment: Delay transaction: Insufficient funds: %s / %s (%d)")
|
||||
% saSrcXRPBalance.getText() % (saDstAmount + uReserve).getText() % uReserve);
|
||||
|
||||
terResult = tecUNFUNDED;
|
||||
@@ -171,7 +179,7 @@ TER PaymentTransactor::doApply()
|
||||
|
||||
if (transResultInfo(terResult, strToken, strHuman))
|
||||
{
|
||||
cLog(lsINFO) << boost::str(boost::format("doPayment: %s: %s") % strToken % strHuman);
|
||||
cLog(lsINFO) << boost::str(boost::format("Payment: %s: %s") % strToken % strHuman);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#include "RegularKeySetTransactor.h"
|
||||
#include "Log.h"
|
||||
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
|
||||
uint64_t RegularKeySetTransactor::calculateBaseFee()
|
||||
{
|
||||
if ( !(mTxnAccount->getFlags() & lsfPasswordSpent) &&
|
||||
(mSigningPubKey.getAccountID() == mTxnAccountID))
|
||||
if ( !(mTxnAccount->getFlags() & lsfPasswordSpent)
|
||||
&& (mSigningPubKey.getAccountID() == mTxnAccountID))
|
||||
{ // flag is armed and they signed with the right account
|
||||
return 0;
|
||||
}
|
||||
@@ -18,9 +16,18 @@ uint64_t RegularKeySetTransactor::calculateBaseFee()
|
||||
|
||||
TER RegularKeySetTransactor::doApply()
|
||||
{
|
||||
std::cerr << "doRegularKeySet>" << std::endl;
|
||||
std::cerr << "RegularKeySet>" << std::endl;
|
||||
|
||||
if(mFeeDue.isZero())
|
||||
const uint32 uTxFlags = mTxn.getFlags();
|
||||
|
||||
if (uTxFlags)
|
||||
{
|
||||
cLog(lsINFO) << "RegularKeySet: Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
if (mFeeDue.isZero())
|
||||
{
|
||||
mTxnAccount->setFlag(lsfPasswordSpent);
|
||||
}
|
||||
@@ -28,8 +35,9 @@ TER RegularKeySetTransactor::doApply()
|
||||
uint160 uAuthKeyID=mTxn.getFieldAccount160(sfRegularKey);
|
||||
mTxnAccount->setFieldAccount(sfRegularKey, uAuthKeyID);
|
||||
|
||||
|
||||
std::cerr << "doRegularKeySet<" << std::endl;
|
||||
std::cerr << "RegularKeySet<" << std::endl;
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -2567,8 +2567,7 @@ cLog(lsDEBUG) << boost::str(boost::format("rippleCalc: Summary: %d rate: %s qual
|
||||
{
|
||||
// Have sent maximum allowed. Partial payment not allowed.
|
||||
|
||||
terResult = tepPATH_PARTIAL;
|
||||
lesActive = lesBase; // Revert to just fees charged.
|
||||
terResult = tecPATH_PARTIAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2581,14 +2580,13 @@ cLog(lsDEBUG) << boost::str(boost::format("rippleCalc: Summary: %d rate: %s qual
|
||||
else if (!bPartialPayment)
|
||||
{
|
||||
// Partial payment not allowed.
|
||||
terResult = tepPATH_PARTIAL;
|
||||
lesActive = lesBase; // Revert to just fees charged.
|
||||
terResult = tecPATH_PARTIAL;
|
||||
}
|
||||
// Partial payment ok.
|
||||
else if (!saDstAmountAct)
|
||||
{
|
||||
// No payment at all.
|
||||
terResult = tecPATH_DRY; // Revert to just fees charged is built into tec.
|
||||
terResult = tecPATH_DRY;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// This is not really a header file, but it can be used as one with
|
||||
// appropriate #define statements.
|
||||
|
||||
#define ENABLE_DESTINATION_TAG 0
|
||||
|
||||
// types (common)
|
||||
TYPE(Int16, UINT16, 1)
|
||||
TYPE(Int32, UINT32, 2)
|
||||
@@ -44,6 +46,9 @@
|
||||
FIELD(TransferRate, UINT32, 11)
|
||||
FIELD(WalletSize, UINT32, 12)
|
||||
FIELD(OwnerCount, UINT32, 13)
|
||||
#if ENABLE_DESTINATION_TAG
|
||||
FIELD(DestinationTag, UINT32, 14)
|
||||
#endif
|
||||
|
||||
// 32-bit integers (uncommon)
|
||||
FIELD(HighQualityIn, UINT32, 16)
|
||||
|
||||
@@ -77,8 +77,8 @@ public:
|
||||
int giveObject(std::auto_ptr<SerializedType> t) { mData.push_back(t); return mData.size() - 1; }
|
||||
int giveObject(SerializedType* t) { mData.push_back(t); return mData.size() - 1; }
|
||||
const boost::ptr_vector<SerializedType>& peekData() const { return mData; }
|
||||
boost::ptr_vector<SerializedType>& peekData() { return mData; }
|
||||
SerializedType& front() { return mData.front(); }
|
||||
boost::ptr_vector<SerializedType>& peekData() { return mData; }
|
||||
SerializedType& front() { return mData.front(); }
|
||||
const SerializedType& front() const { return mData.front(); }
|
||||
SerializedType& back() { return mData.back(); }
|
||||
const SerializedType& back() const { return mData.back(); }
|
||||
@@ -248,7 +248,7 @@ public:
|
||||
bool operator==(const STArray &s) { return value == s.value; }
|
||||
bool operator!=(const STArray &s) { return value != s.value; }
|
||||
|
||||
virtual SerializedTypeID getSType() const { return STI_ARRAY; }
|
||||
virtual SerializedTypeID getSType() const { return STI_ARRAY; }
|
||||
virtual bool isEquivalent(const SerializedType& t) const;
|
||||
virtual bool isDefault() const { return value.empty(); }
|
||||
};
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
STAmount getAmount() const { return mTransaction->getFieldU64(sfAmount); }
|
||||
STAmount getFee() const { return mTransaction->getTransactionFee(); }
|
||||
uint32 getFromAccountSeq() const { return mTransaction->getSequence(); }
|
||||
uint32 getIdent() const { return mTransaction->getFieldU32(sfSourceTag); }
|
||||
uint32 getSourceTag() const { return mTransaction->getFieldU32(sfSourceTag); }
|
||||
std::vector<unsigned char> getSignature() const { return mTransaction->getSignature(); }
|
||||
uint32 getLedger() const { return mInLedger; }
|
||||
TransStatus getStatus() const { return mStatus; }
|
||||
|
||||
@@ -116,10 +116,6 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
{
|
||||
didApply = true;
|
||||
}
|
||||
else if (isTepPartial(terResult) && !isSetBit(params, tapRETRY))
|
||||
{
|
||||
didApply = true;
|
||||
}
|
||||
else if (isTecClaim(terResult) && !isSetBit(params, tapRETRY))
|
||||
{ // only claim the transaction fee
|
||||
cLog(lsINFO) << "Reprocessing to only claim fee";
|
||||
|
||||
@@ -17,6 +17,8 @@ bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman)
|
||||
{ tecNO_LINE_INSUF_RESERVE, "tecNO_LINE_INSUF_RESERVE", "No such line. Too little reserve to create it." },
|
||||
{ tecNO_LINE_REDUNDANT, "tecNO_LINE_REDUNDANT", "Can't set non-existant line to default." },
|
||||
{ tecPATH_DRY, "tecPATH_DRY", "Path could not send partial amount." },
|
||||
{ tecPATH_PARTIAL, "tecPATH_PARTIAL", "Path could not send full amount." },
|
||||
|
||||
{ tecUNFUNDED, "tecUNFUNDED", "Source account had insufficient balance for transaction." },
|
||||
|
||||
{ tefFAILURE, "tefFAILURE", "Failed to apply." },
|
||||
@@ -51,6 +53,9 @@ bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman)
|
||||
{ temBAD_SEQUENCE, "temBAD_SEQUENCE", "Malformed: Sequence is not in the past." },
|
||||
{ temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." },
|
||||
{ temDST_NEEDED, "temDST_NEEDED", "Destination not specified." },
|
||||
#if ENABLE_REQUIRE_DEST_TAG
|
||||
{ temDST_TAG_NEEDED, "temDST_TAG_NEEDED", "Destination tag required." },
|
||||
#endif
|
||||
{ temINVALID, "temINVALID", "The transaction is ill-formed." },
|
||||
{ temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." },
|
||||
{ temREDUNDANT, "temREDUNDANT", "Sends same currency to self." },
|
||||
@@ -58,9 +63,6 @@ bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman)
|
||||
{ temUNCERTAIN, "temUNCERTAIN", "In process of determining result. Never returned." },
|
||||
{ temUNKNOWN, "temUNKNOWN", "The transactions requires logic not implemented yet." },
|
||||
|
||||
{ tepPARTIAL, "tepPARTIAL", "Partial success." },
|
||||
{ tepPATH_PARTIAL, "tepPATH_PARTIAL", "Path could not send full amount." },
|
||||
|
||||
{ terRETRY, "terRETRY", "Retry transaction." },
|
||||
{ terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." },
|
||||
{ terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee." },
|
||||
|
||||
@@ -39,6 +39,9 @@ enum TER // aka TransactionEngineResult
|
||||
temBAD_SEQUENCE,
|
||||
temDST_IS_SRC,
|
||||
temDST_NEEDED,
|
||||
#if ENABLE_REQUIRE_DEST_TAG
|
||||
temDST_TAG_NEEDED,
|
||||
#endif
|
||||
temINVALID,
|
||||
temINVALID_FLAG,
|
||||
temREDUNDANT,
|
||||
@@ -92,20 +95,9 @@ enum TER // aka TransactionEngineResult
|
||||
// - Forwarded
|
||||
tesSUCCESS = 0,
|
||||
|
||||
// 100 .. 119 P Partial success (SR) (ripple transaction with no good paths, pay to non-existent account)
|
||||
// 100 .. 129 C Claim fee only (ripple transaction with no good paths, pay to non-existent account, no path)
|
||||
// Causes:
|
||||
// - Success, but does not achieve optimal result.
|
||||
// Implications:
|
||||
// - Applied
|
||||
// - Forwarded
|
||||
// Only allowed as a return code of appliedTransaction when !tapRetry. Otherwise, treated as terRETRY.
|
||||
//
|
||||
// DO NOT CHANGE THESE NUMBERS: They appear in ledger meta data.
|
||||
tepPARTIAL = 100,
|
||||
tepPATH_PARTIAL = 101,
|
||||
|
||||
// 120 .. C Claim fee only (CO) (no path)
|
||||
// Causes:
|
||||
// - Invalid transaction or no effect, but claim fee to use the sequence number.
|
||||
// Implications:
|
||||
// - Applied
|
||||
@@ -113,7 +105,8 @@ enum TER // aka TransactionEngineResult
|
||||
// Only allowed as a return code of appliedTransaction when !tapRetry. Otherwise, treated as terRETRY.
|
||||
//
|
||||
// DO NOT CHANGE THESE NUMBERS: They appear in ledger meta data.
|
||||
tecCLAIM = 120,
|
||||
tecCLAIM = 100,
|
||||
tecPATH_PARTIAL = 101,
|
||||
tecDIR_FULL = 121,
|
||||
tecINSUF_RESERVE_LINE = 122,
|
||||
tecINSUF_RESERVE_OFFER = 123,
|
||||
@@ -130,7 +123,6 @@ enum TER // aka TransactionEngineResult
|
||||
#define isTefFailure(x) ((x) >= tefFAILURE && (x) < terRETRY)
|
||||
#define isTerRetry(x) ((x) >= terRETRY && (x) < tesSUCCESS)
|
||||
#define isTepSuccess(x) ((x) >= tesSUCCESS)
|
||||
#define isTepPartial(x) ((x) >= tepPATH_PARTIAL && (x) < tecCLAIM)
|
||||
#define isTecClaim(x) ((x) >= tecCLAIM)
|
||||
|
||||
bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman);
|
||||
|
||||
@@ -55,6 +55,9 @@ static bool TFInit()
|
||||
<< SOElement(sfSendMax, SOE_OPTIONAL)
|
||||
<< SOElement(sfPaths, SOE_DEFAULT)
|
||||
<< SOElement(sfInvoiceID, SOE_OPTIONAL)
|
||||
#if ENABLE_DESTINATION_TAG
|
||||
<< SOElement(sfDestinationTag, SOE_OPTIONAL)
|
||||
#endif
|
||||
;
|
||||
|
||||
DECLARE_TF(Contract, ttCONTRACT)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define __TRANSACTIONFORMATS__
|
||||
|
||||
#include "SerializedObject.h"
|
||||
#include "LedgerFormats.h"
|
||||
|
||||
enum TransactionType
|
||||
{
|
||||
@@ -19,10 +20,10 @@ enum TransactionType
|
||||
ttCONTRACT = 9,
|
||||
ttCONTRACT_REMOVE = 10, // can we use the same msg as offer cancel
|
||||
|
||||
ttTRUST_SET = 20,
|
||||
ttTRUST_SET = 20,
|
||||
|
||||
ttFEATURE = 100,
|
||||
ttFEE = 101,
|
||||
ttFEATURE = 100,
|
||||
ttFEE = 101,
|
||||
};
|
||||
|
||||
class TransactionFormat
|
||||
@@ -58,6 +59,13 @@ const int TransactionMaxLen = 1048576;
|
||||
// Transaction flags.
|
||||
//
|
||||
|
||||
#if ENABLE_REQUIRE_DEST_TAG
|
||||
// AccountSet flags:
|
||||
const uint32 tfRequireDestTag = 0x00010000;
|
||||
const uint32 tfOptionalDestTag = 0x00020000;
|
||||
const uint32 tfAccountSetMask = ~(tfRequireDestTag|tfOptionalDestTag);
|
||||
#endif
|
||||
|
||||
// OfferCreate flags:
|
||||
const uint32 tfPassive = 0x00010000;
|
||||
const uint32 tfOfferCreateMask = ~(tfPassive);
|
||||
|
||||
@@ -25,6 +25,15 @@ TER TrustSetTransactor::doApply()
|
||||
if (bQualityOut && QUALITY_ONE == uQualityOut)
|
||||
uQualityOut = 0;
|
||||
|
||||
const uint32 uTxFlags = mTxn.getFlags();
|
||||
|
||||
if (uTxFlags)
|
||||
{
|
||||
cLog(lsINFO) << "doTrustSet: Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
// Check if destination makes sense.
|
||||
|
||||
if (saLimitAmount.isNegative())
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "WalletAddTransactor.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
TER WalletAddTransactor::doApply()
|
||||
{
|
||||
std::cerr << "WalletAdd>" << std::endl;
|
||||
@@ -7,9 +9,18 @@ TER WalletAddTransactor::doApply()
|
||||
const std::vector<unsigned char> vucPubKey = mTxn.getFieldVL(sfPublicKey);
|
||||
const std::vector<unsigned char> vucSignature = mTxn.getFieldVL(sfSignature);
|
||||
const uint160 uAuthKeyID = mTxn.getFieldAccount160(sfRegularKey);
|
||||
const RippleAddress naMasterPubKey = RippleAddress::createAccountPublic(vucPubKey);
|
||||
const RippleAddress naMasterPubKey = RippleAddress::createAccountPublic(vucPubKey);
|
||||
const uint160 uDstAccountID = naMasterPubKey.getAccountID();
|
||||
|
||||
const uint32 uTxFlags = mTxn.getFlags();
|
||||
|
||||
if (uTxFlags)
|
||||
{
|
||||
cLog(lsINFO) << "WalletAdd: Malformed transaction: Invalid flags set.";
|
||||
|
||||
return temINVALID_FLAG;
|
||||
}
|
||||
|
||||
// FIXME: This should be moved to the transaction's signature check logic and cached
|
||||
if (!naMasterPubKey.accountPublicVerify(Serializer::getSHA512Half(uAuthKeyID.begin(), uAuthKeyID.size()), vucSignature))
|
||||
{
|
||||
|
||||
@@ -1162,7 +1162,7 @@ Remote.prototype.transaction = function () {
|
||||
// |/
|
||||
// |- 'tesSUCCESS' - Transaction in ledger as expected.
|
||||
// |- 'ter...' - Transaction failed.
|
||||
// \- 'tep...' - Transaction partially succeeded.
|
||||
// \- 'tec...' - Transaction claimed fee only.
|
||||
//
|
||||
// Notes:
|
||||
// - All transactions including those with local and malformed errors may be
|
||||
@@ -1225,7 +1225,7 @@ Transaction.prototype.consts = {
|
||||
'tefFAILURE' : -199,
|
||||
'terRETRY' : -99,
|
||||
'tesSUCCESS' : 0,
|
||||
'tepPARTIAL' : 100,
|
||||
'tecCLAIMED' : 100,
|
||||
};
|
||||
|
||||
Transaction.prototype.isTelLocal = function (ter) {
|
||||
@@ -1248,8 +1248,8 @@ Transaction.prototype.isTepSuccess = function (ter) {
|
||||
return ter >= this.consts.tesSUCCESS;
|
||||
};
|
||||
|
||||
Transaction.prototype.isTepPartial = function (ter) {
|
||||
return ter >= this.consts.tepPATH_PARTIAL;
|
||||
Transaction.prototype.isTecClaimed = function (ter) {
|
||||
return ter >= this.consts.tecCLAIMED;
|
||||
};
|
||||
|
||||
Transaction.prototype.isRejected = function (ter) {
|
||||
|
||||
@@ -602,7 +602,7 @@ buster.testCase("Offer tests", {
|
||||
.on('proposed', function (m) {
|
||||
// console.log("proposed: %s", JSON.stringify(m));
|
||||
|
||||
callback(m.result !== 'tepPATH_PARTIAL');
|
||||
callback(m.result !== 'tecPATH_PARTIAL');
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
|
||||
920
test/reserve-test.js
Normal file
920
test/reserve-test.js
Normal file
@@ -0,0 +1,920 @@
|
||||
|
||||
var async = require("async");
|
||||
var buster = require("buster");
|
||||
|
||||
var Amount = require("../src/js/amount.js").Amount;
|
||||
var Remote = require("../src/js/remote.js").Remote;
|
||||
var Server = require("./server.js").Server;
|
||||
|
||||
var testutils = require("./testutils.js");
|
||||
|
||||
require("../src/js/amount.js").config = require("./config.js");
|
||||
require("../src/js/remote.js").config = require("./config.js");
|
||||
|
||||
buster.testRunner.timeout = 5000;
|
||||
|
||||
buster.testCase("Reserve", {
|
||||
'setUp' : testutils.build_setup(),
|
||||
// 'setUp' : testutils.build_setup({ verbose: true, standalone: false }),
|
||||
'tearDown' : testutils.build_teardown(),
|
||||
|
||||
"offer create then cancel in one ledger" :
|
||||
function (done) {
|
||||
var self = this;
|
||||
var final_create;
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
self.remote.transaction()
|
||||
.offer_create("root", "500", "100/USD/root")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_create: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS', m);
|
||||
})
|
||||
.on('final', function (m) {
|
||||
// console.log("FINAL: offer_create: %s", JSON.stringify(m));
|
||||
|
||||
buster.assert.equals('tesSUCCESS', m.metadata.TransactionResult);
|
||||
|
||||
buster.assert(final_create);
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (m, callback) {
|
||||
self.remote.transaction()
|
||||
.offer_cancel("root", m.tx_json.Sequence)
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_cancel: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS', m);
|
||||
})
|
||||
.on('final', function (m) {
|
||||
// console.log("FINAL: offer_cancel: %s", JSON.stringify(m, undefined, 2));
|
||||
|
||||
buster.assert.equals('tesSUCCESS', m.metadata.TransactionResult);
|
||||
buster.assert(final_create);
|
||||
done();
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (m, callback) {
|
||||
self.remote
|
||||
.once('ledger_closed', function (message) {
|
||||
// console.log("LEDGER_CLOSED: %d: %s", ledger_index, ledger_hash);
|
||||
final_create = message;
|
||||
})
|
||||
.ledger_accept();
|
||||
}
|
||||
], function (error) {
|
||||
// console.log("result: error=%s", error);
|
||||
buster.refute(error);
|
||||
|
||||
if (error) done();
|
||||
});
|
||||
},
|
||||
|
||||
"offer_create then ledger_accept then offer_cancel then ledger_accept." :
|
||||
function (done) {
|
||||
var self = this;
|
||||
var final_create;
|
||||
var offer_seq;
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
self.remote.transaction()
|
||||
.offer_create("root", "500", "100/USD/root")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_create: %s", JSON.stringify(m));
|
||||
|
||||
offer_seq = m.tx_json.Sequence;
|
||||
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
})
|
||||
.on('final', function (m) {
|
||||
// console.log("FINAL: offer_create: %s", JSON.stringify(m));
|
||||
|
||||
buster.assert.equals('tesSUCCESS', m.metadata.TransactionResult);
|
||||
|
||||
final_create = m;
|
||||
|
||||
callback();
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
if (!final_create) {
|
||||
self.remote
|
||||
.once('ledger_closed', function (mesage) {
|
||||
// console.log("LEDGER_CLOSED: %d: %s", ledger_index, ledger_hash);
|
||||
|
||||
})
|
||||
.ledger_accept();
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
function (callback) {
|
||||
// console.log("CANCEL: offer_cancel: %d", offer_seq);
|
||||
|
||||
self.remote.transaction()
|
||||
.offer_cancel("root", offer_seq)
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_cancel: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
})
|
||||
.on('final', function (m) {
|
||||
// console.log("FINAL: offer_cancel: %s", JSON.stringify(m));
|
||||
|
||||
buster.assert.equals('tesSUCCESS', m.metadata.TransactionResult);
|
||||
buster.assert(final_create);
|
||||
|
||||
done();
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
// See if ledger_accept will crash.
|
||||
function (callback) {
|
||||
self.remote
|
||||
.once('ledger_closed', function (mesage) {
|
||||
// console.log("LEDGER_CLOSED: A: %d: %s", ledger_index, ledger_hash);
|
||||
callback();
|
||||
})
|
||||
.ledger_accept();
|
||||
},
|
||||
function (callback) {
|
||||
self.remote
|
||||
.once('ledger_closed', function (mesage) {
|
||||
// console.log("LEDGER_CLOSED: B: %d: %s", ledger_index, ledger_hash);
|
||||
callback();
|
||||
})
|
||||
.ledger_accept();
|
||||
},
|
||||
], function (error) {
|
||||
// console.log("result: error=%s", error);
|
||||
buster.refute(error);
|
||||
|
||||
if (error) done();
|
||||
});
|
||||
},
|
||||
|
||||
"//new user offer_create then ledger_accept then offer_cancel then ledger_accept." :
|
||||
function (done) {
|
||||
var self = this;
|
||||
var final_create;
|
||||
var offer_seq;
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
self.remote.transaction()
|
||||
.payment('root', 'alice', "1000")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("proposed: %s", JSON.stringify(m));
|
||||
buster.assert.equals(m.result, 'tesSUCCESS');
|
||||
callback();
|
||||
})
|
||||
.submit()
|
||||
},
|
||||
function (callback) {
|
||||
self.remote.transaction()
|
||||
.offer_create("alice", "500", "100/USD/alice")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_create: %s", JSON.stringify(m));
|
||||
|
||||
offer_seq = m.tx_json.Sequence;
|
||||
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
})
|
||||
.on('final', function (m) {
|
||||
// console.log("FINAL: offer_create: %s", JSON.stringify(m));
|
||||
|
||||
buster.assert.equals('tesSUCCESS', m.metadata.TransactionResult);
|
||||
|
||||
final_create = m;
|
||||
|
||||
callback();
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
if (!final_create) {
|
||||
self.remote
|
||||
.once('ledger_closed', function (mesage) {
|
||||
// console.log("LEDGER_CLOSED: %d: %s", ledger_index, ledger_hash);
|
||||
|
||||
})
|
||||
.ledger_accept();
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
function (callback) {
|
||||
// console.log("CANCEL: offer_cancel: %d", offer_seq);
|
||||
|
||||
self.remote.transaction()
|
||||
.offer_cancel("alice", offer_seq)
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_cancel: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
})
|
||||
.on('final', function (m) {
|
||||
// console.log("FINAL: offer_cancel: %s", JSON.stringify(m));
|
||||
|
||||
buster.assert.equals('tesSUCCESS', m.metadata.TransactionResult);
|
||||
buster.assert(final_create);
|
||||
|
||||
done();
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
// See if ledger_accept will crash.
|
||||
function (callback) {
|
||||
self.remote
|
||||
.once('ledger_closed', function (mesage) {
|
||||
// console.log("LEDGER_CLOSED: A: %d: %s", ledger_index, ledger_hash);
|
||||
callback();
|
||||
})
|
||||
.ledger_accept();
|
||||
},
|
||||
function (callback) {
|
||||
self.remote
|
||||
.once('ledger_closed', function (mesage) {
|
||||
// console.log("LEDGER_CLOSED: B: %d: %s", ledger_index, ledger_hash);
|
||||
callback();
|
||||
})
|
||||
.ledger_accept();
|
||||
},
|
||||
], function (error) {
|
||||
// console.log("result: error=%s", error);
|
||||
buster.refute(error);
|
||||
if (error) done();
|
||||
});
|
||||
},
|
||||
|
||||
"offer cancel past and future sequence" :
|
||||
function (done) {
|
||||
var self = this;
|
||||
var final_create;
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
self.remote.transaction()
|
||||
.payment('root', 'alice', Amount.from_json("10000.0"))
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: CreateAccount: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS', m);
|
||||
})
|
||||
.on('error', function(m) {
|
||||
// console.log("error: %s", m);
|
||||
|
||||
buster.assert(false);
|
||||
callback(m);
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
// Past sequence but wrong
|
||||
function (m, callback) {
|
||||
self.remote.transaction()
|
||||
.offer_cancel("root", m.tx_json.Sequence)
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_cancel past: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS', m);
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
// Same sequence
|
||||
function (m, callback) {
|
||||
self.remote.transaction()
|
||||
.offer_cancel("root", m.tx_json.Sequence+1)
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_cancel same: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'temBAD_SEQUENCE', m);
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
// Future sequence
|
||||
function (m, callback) {
|
||||
// After a malformed transaction, need to recover correct sequence.
|
||||
self.remote.set_account_seq("root", self.remote.account_seq("root")-1);
|
||||
|
||||
self.remote.transaction()
|
||||
.offer_cancel("root", m.tx_json.Sequence+2)
|
||||
.on('proposed', function (m) {
|
||||
// console.log("ERROR: offer_cancel future: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'temBAD_SEQUENCE');
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
// See if ledger_accept will crash.
|
||||
function (callback) {
|
||||
self.remote
|
||||
.once('ledger_closed', function (mesage) {
|
||||
// console.log("LEDGER_CLOSED: A: %d: %s", ledger_index, ledger_hash);
|
||||
callback();
|
||||
})
|
||||
.ledger_accept();
|
||||
},
|
||||
function (callback) {
|
||||
self.remote
|
||||
.once('ledger_closed', function (mesage) {
|
||||
// console.log("LEDGER_CLOSED: B: %d: %s", ledger_index, ledger_hash);
|
||||
callback();
|
||||
})
|
||||
.ledger_accept();
|
||||
},
|
||||
function (callback) {
|
||||
callback();
|
||||
}
|
||||
], function (error) {
|
||||
// console.log("result: error=%s", error);
|
||||
buster.refute(error);
|
||||
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
"ripple currency conversion : entire offer" :
|
||||
// mtgox in, XRP out
|
||||
function (done) {
|
||||
var self = this;
|
||||
var seq;
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
self.what = "Create accounts.";
|
||||
|
||||
testutils.create_accounts(self.remote, "root", "10000.0", ["alice", "bob", "mtgox"], callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Owner count 0.";
|
||||
|
||||
testutils.verify_owner_count(self.remote, "bob", 0, callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Set limits.";
|
||||
|
||||
testutils.credit_limits(self.remote,
|
||||
{
|
||||
"alice" : "100/USD/mtgox",
|
||||
"bob" : "1000/USD/mtgox"
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Owner counts after trust.";
|
||||
|
||||
testutils.verify_owner_counts(self.remote,
|
||||
{
|
||||
"alice" : 1,
|
||||
"bob" : 1,
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Distribute funds.";
|
||||
|
||||
testutils.payments(self.remote,
|
||||
{
|
||||
"mtgox" : "100/USD/alice"
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Create offer.";
|
||||
|
||||
self.remote.transaction()
|
||||
.offer_create("bob", "100/USD/mtgox", "500")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_create: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
|
||||
seq = m.tx_json.Sequence;
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Owner counts after offer create.";
|
||||
|
||||
testutils.verify_owner_counts(self.remote,
|
||||
{
|
||||
"alice" : 1,
|
||||
"bob" : 2,
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify offer balance.";
|
||||
|
||||
testutils.verify_offer(self.remote, "bob", seq, "100/USD/mtgox", "500", callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Alice converts USD to XRP.";
|
||||
|
||||
self.remote.transaction()
|
||||
.payment("alice", "alice", "500")
|
||||
.send_max("100/USD/mtgox")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("proposed: %s", JSON.stringify(m));
|
||||
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify balances.";
|
||||
|
||||
testutils.verify_balances(self.remote,
|
||||
{
|
||||
"alice" : [ "0/USD/mtgox", String(10000000000+500-2*(Remote.fees['default'].to_number())) ],
|
||||
"bob" : "100/USD/mtgox",
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify offer consumed.";
|
||||
|
||||
testutils.verify_offer_not_found(self.remote, "bob", seq, callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Owner counts after consumed.";
|
||||
|
||||
testutils.verify_owner_counts(self.remote,
|
||||
{
|
||||
"alice" : 1,
|
||||
"bob" : 1,
|
||||
},
|
||||
callback);
|
||||
},
|
||||
], function (error) {
|
||||
buster.refute(error, self.what);
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
"ripple currency conversion : offerer into debt" :
|
||||
// alice in, carol out
|
||||
function (done) {
|
||||
var self = this;
|
||||
var seq;
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
self.what = "Create accounts.";
|
||||
|
||||
testutils.create_accounts(self.remote, "root", "10000.0", ["alice", "bob", "carol"], callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Set limits.";
|
||||
|
||||
testutils.credit_limits(self.remote,
|
||||
{
|
||||
"alice" : "2000/EUR/carol",
|
||||
"bob" : "100/USD/alice",
|
||||
"carol" : "1000/EUR/bob"
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Create offer to exchange.";
|
||||
|
||||
self.remote.transaction()
|
||||
.offer_create("bob", "50/USD/alice", "200/EUR/carol")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_create: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tecUNFUNDED');
|
||||
|
||||
seq = m.tx_json.Sequence;
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
// function (callback) {
|
||||
// self.what = "Alice converts USD to EUR via offer.";
|
||||
//
|
||||
// self.remote.transaction()
|
||||
// .offer_create("alice", "200/EUR/carol", "50/USD/alice")
|
||||
// .on('proposed', function (m) {
|
||||
// // console.log("PROPOSED: offer_create: %s", JSON.stringify(m));
|
||||
// callback(m.result !== 'tesSUCCESS');
|
||||
//
|
||||
// seq = m.tx_json.Sequence;
|
||||
// })
|
||||
// .submit();
|
||||
// },
|
||||
// function (callback) {
|
||||
// self.what = "Verify balances.";
|
||||
//
|
||||
// testutils.verify_balances(self.remote,
|
||||
// {
|
||||
// "alice" : [ "-50/USD/bob", "200/EUR/carol" ],
|
||||
// "bob" : [ "50/USD/alice", "-200/EUR/carol" ],
|
||||
// "carol" : [ "-200/EUR/alice", "200/EUR/bob" ],
|
||||
// },
|
||||
// callback);
|
||||
// },
|
||||
// function (callback) {
|
||||
// self.what = "Verify offer consumed.";
|
||||
//
|
||||
// testutils.verify_offer_not_found(self.remote, "bob", seq, callback);
|
||||
// },
|
||||
], function (error) {
|
||||
buster.refute(error, self.what);
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
"ripple currency conversion : in parts" :
|
||||
function (done) {
|
||||
var self = this;
|
||||
var seq;
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
self.what = "Create accounts.";
|
||||
|
||||
testutils.create_accounts(self.remote, "root", "10000.0", ["alice", "bob", "mtgox"], callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Set limits.";
|
||||
|
||||
testutils.credit_limits(self.remote,
|
||||
{
|
||||
"alice" : "200/USD/mtgox",
|
||||
"bob" : "1000/USD/mtgox"
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Distribute funds.";
|
||||
|
||||
testutils.payments(self.remote,
|
||||
{
|
||||
"mtgox" : "200/USD/alice"
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Create offer.";
|
||||
|
||||
self.remote.transaction()
|
||||
.offer_create("bob", "100/USD/mtgox", "500")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_create: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
|
||||
seq = m.tx_json.Sequence;
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Alice converts USD to XRP.";
|
||||
|
||||
self.remote.transaction()
|
||||
.payment("alice", "alice", "200")
|
||||
.send_max("100/USD/mtgox")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("proposed: %s", JSON.stringify(m));
|
||||
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify offer balance.";
|
||||
|
||||
testutils.verify_offer(self.remote, "bob", seq, "60/USD/mtgox", "300", callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify balances.";
|
||||
|
||||
testutils.verify_balances(self.remote,
|
||||
{
|
||||
"alice" : [ "160/USD/mtgox", String(10000000000+200-2*(Remote.fees['default'].to_number())) ],
|
||||
"bob" : "40/USD/mtgox",
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Alice converts USD to XRP should fail due to PartialPayment.";
|
||||
|
||||
self.remote.transaction()
|
||||
.payment("alice", "alice", "600")
|
||||
.send_max("100/USD/mtgox")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("proposed: %s", JSON.stringify(m));
|
||||
|
||||
callback(m.result !== 'tecPATH_PARTIAL');
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Alice converts USD to XRP.";
|
||||
|
||||
self.remote.transaction()
|
||||
.payment("alice", "alice", "600")
|
||||
.send_max("100/USD/mtgox")
|
||||
.set_flags('PartialPayment')
|
||||
.on('proposed', function (m) {
|
||||
// console.log("proposed: %s", JSON.stringify(m));
|
||||
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify offer consumed.";
|
||||
|
||||
testutils.verify_offer_not_found(self.remote, "bob", seq, callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify balances.";
|
||||
|
||||
testutils.verify_balances(self.remote,
|
||||
{
|
||||
"alice" : [ "100/USD/mtgox", String(10000000000+200+300-4*(Remote.fees['default'].to_number())) ],
|
||||
"bob" : "100/USD/mtgox",
|
||||
},
|
||||
callback);
|
||||
},
|
||||
], function (error) {
|
||||
buster.refute(error, self.what);
|
||||
done();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
buster.testCase("Offer cross currency", {
|
||||
'setUp' : testutils.build_setup(),
|
||||
'tearDown' : testutils.build_teardown(),
|
||||
|
||||
"ripple cross currency payment - start with XRP" :
|
||||
// alice --> [XRP --> carol --> USD/mtgox] --> bob
|
||||
|
||||
function (done) {
|
||||
var self = this;
|
||||
var seq;
|
||||
|
||||
// self.remote.set_trace();
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
self.what = "Create accounts.";
|
||||
|
||||
testutils.create_accounts(self.remote, "root", "10000.0", ["alice", "bob", "carol", "mtgox"], callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Set limits.";
|
||||
|
||||
testutils.credit_limits(self.remote,
|
||||
{
|
||||
"carol" : "1000/USD/mtgox",
|
||||
"bob" : "2000/USD/mtgox"
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Distribute funds.";
|
||||
|
||||
testutils.payments(self.remote,
|
||||
{
|
||||
"mtgox" : "500/USD/carol"
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Create offer.";
|
||||
|
||||
self.remote.transaction()
|
||||
.offer_create("carol", "500", "50/USD/mtgox")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_create: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
|
||||
seq = m.tx_json.Sequence;
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Alice send USD/mtgox converting from XRP.";
|
||||
|
||||
self.remote.transaction()
|
||||
.payment("alice", "bob", "25/USD/mtgox")
|
||||
.send_max("333")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("proposed: %s", JSON.stringify(m));
|
||||
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify balances.";
|
||||
|
||||
testutils.verify_balances(self.remote,
|
||||
{
|
||||
// "alice" : [ "500" ],
|
||||
"bob" : "25/USD/mtgox",
|
||||
"carol" : "475/USD/mtgox",
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify offer consumed.";
|
||||
|
||||
testutils.verify_offer_not_found(self.remote, "bob", seq, callback);
|
||||
},
|
||||
], function (error) {
|
||||
buster.refute(error, self.what);
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
"ripple cross currency payment - end with XRP" :
|
||||
// alice --> [USD/mtgox --> carol --> XRP] --> bob
|
||||
|
||||
function (done) {
|
||||
var self = this;
|
||||
var seq;
|
||||
|
||||
// self.remote.set_trace();
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
self.what = "Create accounts.";
|
||||
|
||||
testutils.create_accounts(self.remote, "root", "10000.0", ["alice", "bob", "carol", "mtgox"], callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Set limits.";
|
||||
|
||||
testutils.credit_limits(self.remote,
|
||||
{
|
||||
"alice" : "1000/USD/mtgox",
|
||||
"carol" : "2000/USD/mtgox"
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Distribute funds.";
|
||||
|
||||
testutils.payments(self.remote,
|
||||
{
|
||||
"mtgox" : "500/USD/alice"
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Create offer.";
|
||||
|
||||
self.remote.transaction()
|
||||
.offer_create("carol", "50/USD/mtgox", "500")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_create: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
|
||||
seq = m.tx_json.Sequence;
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Alice send XRP to bob converting from USD/mtgox.";
|
||||
|
||||
self.remote.transaction()
|
||||
.payment("alice", "bob", "250")
|
||||
.send_max("333/USD/mtgox")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("proposed: %s", JSON.stringify(m));
|
||||
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify balances.";
|
||||
|
||||
testutils.verify_balances(self.remote,
|
||||
{
|
||||
"alice" : "475/USD/mtgox",
|
||||
"bob" : "10000000250",
|
||||
"carol" : "25/USD/mtgox",
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify offer partially consumed.";
|
||||
|
||||
testutils.verify_offer(self.remote, "carol", seq, "25/USD/mtgox", "250", callback);
|
||||
},
|
||||
], function (error) {
|
||||
buster.refute(error, self.what);
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
"ripple cross currency bridged payment" :
|
||||
// alice --> [USD/mtgox --> carol --> XRP] --> [XRP --> dan --> EUR/bitstamp] --> bob
|
||||
|
||||
function (done) {
|
||||
var self = this;
|
||||
var seq_carol;
|
||||
var seq_dan;
|
||||
|
||||
// self.remote.set_trace();
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
self.what = "Create accounts.";
|
||||
|
||||
testutils.create_accounts(self.remote, "root", "10000.0", ["alice", "bob", "carol", "dan", "bitstamp", "mtgox"], callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Set limits.";
|
||||
|
||||
testutils.credit_limits(self.remote,
|
||||
{
|
||||
"alice" : "1000/USD/mtgox",
|
||||
"bob" : "1000/EUR/bitstamp",
|
||||
"carol" : "1000/USD/mtgox",
|
||||
"dan" : "1000/EUR/bitstamp"
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Distribute funds.";
|
||||
|
||||
testutils.payments(self.remote,
|
||||
{
|
||||
"bitstamp" : "400/EUR/dan",
|
||||
"mtgox" : "500/USD/alice",
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Create offer carol.";
|
||||
|
||||
self.remote.transaction()
|
||||
.offer_create("carol", "50/USD/mtgox", "500")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_create: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
|
||||
seq_carol = m.tx_json.Sequence;
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Create offer dan.";
|
||||
|
||||
self.remote.transaction()
|
||||
.offer_create("dan", "500", "50/EUR/bitstamp")
|
||||
.on('proposed', function (m) {
|
||||
// console.log("PROPOSED: offer_create: %s", JSON.stringify(m));
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
|
||||
seq_dan = m.tx_json.Sequence;
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Alice send EUR/bitstamp to bob converting from USD/mtgox.";
|
||||
|
||||
self.remote.transaction()
|
||||
.payment("alice", "bob", "30/EUR/bitstamp")
|
||||
.send_max("333/USD/mtgox")
|
||||
.path_add( [ { currency: "XRP" } ])
|
||||
.on('proposed', function (m) {
|
||||
// console.log("proposed: %s", JSON.stringify(m));
|
||||
|
||||
callback(m.result !== 'tesSUCCESS');
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify balances.";
|
||||
|
||||
testutils.verify_balances(self.remote,
|
||||
{
|
||||
"alice" : "470/USD/mtgox",
|
||||
"bob" : "30/EUR/bitstamp",
|
||||
"carol" : "30/USD/mtgox",
|
||||
"dan" : "370/EUR/bitstamp",
|
||||
},
|
||||
callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify carol offer partially consumed.";
|
||||
|
||||
testutils.verify_offer(self.remote, "carol", seq_carol, "20/USD/mtgox", "200", callback);
|
||||
},
|
||||
function (callback) {
|
||||
self.what = "Verify dan offer partially consumed.";
|
||||
|
||||
testutils.verify_offer(self.remote, "dan", seq_dan, "200", "20/EUR/mtgox", callback);
|
||||
},
|
||||
], function (error) {
|
||||
buster.refute(error, self.what);
|
||||
done();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// vim:sw=2:sts=2:ts=8:et
|
||||
@@ -549,7 +549,7 @@ buster.testCase("Indirect ripple", {
|
||||
.on('proposed', function (m) {
|
||||
// console.log("proposed: %s", JSON.stringify(m));
|
||||
|
||||
callback(m.result !== 'tepPATH_PARTIAL');
|
||||
callback(m.result !== 'tecPATH_PARTIAL');
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
@@ -561,7 +561,7 @@ buster.testCase("Indirect ripple", {
|
||||
.on('proposed', function (m) {
|
||||
// console.log("proposed: %s", JSON.stringify(m));
|
||||
|
||||
callback(m.result !== 'tepPATH_PARTIAL');
|
||||
callback(m.result !== 'tecPATH_PARTIAL');
|
||||
})
|
||||
.submit();
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user