mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 19:15:54 +00:00
Merge branch 'book'
Conflicts: src/cpp/ripple/OrderBookDB.cpp src/cpp/ripple/OrderBookDB.h src/cpp/ripple/Pathfinder.cpp
This commit is contained in:
@@ -147,6 +147,8 @@ void Application::setup()
|
||||
else
|
||||
startNewLedger();
|
||||
|
||||
mOrderBookDB.setup(theApp->getLedgerMaster().getCurrentLedger()); // TODO: We need to update this if the ledger jumps
|
||||
|
||||
//
|
||||
// Begin validation and ip maintenance.
|
||||
// - Wallet maintains local information: including identity and network connection persistence information.
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "ProofOfWork.h"
|
||||
#include "LoadManager.h"
|
||||
#include "TransactionQueue.h"
|
||||
#include "OrderBookDB.h"
|
||||
|
||||
class RPCDoor;
|
||||
class PeerDoor;
|
||||
@@ -66,6 +67,7 @@ class Application
|
||||
LoadManager mLoadMgr;
|
||||
LoadFeeTrack mFeeTrack;
|
||||
TXQueue mTxnQueue;
|
||||
OrderBookDB mOrderBookDB;
|
||||
|
||||
DatabaseCon *mRpcDB, *mTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB;
|
||||
|
||||
@@ -115,6 +117,7 @@ public:
|
||||
LoadFeeTrack& getFeeTrack() { return mFeeTrack; }
|
||||
TXQueue& getTxnQueue() { return mTxnQueue; }
|
||||
PeerDoor& getPeerDoor() { return *mPeerDoor; }
|
||||
OrderBookDB& getOrderBookDB() { return mOrderBookDB; }
|
||||
|
||||
|
||||
bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); }
|
||||
|
||||
@@ -1321,6 +1321,7 @@ void NetworkOPs::pubAcceptedTransaction(Ledger::ref lpCurrent, const SerializedT
|
||||
ispListener->send(jvObj);
|
||||
}
|
||||
}
|
||||
theApp->getOrderBookDB().processTxn(stTxn, terResult, meta, jvObj);
|
||||
|
||||
pubAccountTransaction(lpCurrent, stTxn, terResult, true, meta);
|
||||
}
|
||||
@@ -1451,6 +1452,20 @@ void NetworkOPs::unsubAccount(InfoSub* ispListener, const boost::unordered_set<R
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkOPs::subBook(InfoSub* ispListener, uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut)
|
||||
{
|
||||
BookListeners::pointer listeners=theApp->getOrderBookDB().makeBookListeners(currencyIn, currencyOut, issuerIn, issuerOut);
|
||||
if(listeners) listeners->addSubscriber(ispListener);
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool NetworkOPs::unsubBook(InfoSub* ispListener, uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut)
|
||||
{
|
||||
BookListeners::pointer listeners=theApp->getOrderBookDB().getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut);
|
||||
if(listeners) listeners->removeSubscriber(ispListener);
|
||||
return(true);
|
||||
}
|
||||
|
||||
void NetworkOPs::newLCL(int proposers, int convergeTime, const uint256& ledgerHash)
|
||||
{
|
||||
assert(convergeTime);
|
||||
|
||||
@@ -71,6 +71,7 @@ protected:
|
||||
typedef boost::unordered_map<uint160,boost::unordered_set<InfoSub*> >::iterator subInfoMapIterator;
|
||||
|
||||
typedef boost::unordered_map<uint160,std::pair<InfoSub*,uint32> > subSubmitMapType;
|
||||
//typedef boost::unordered_map<OrderBook::pointer,boost::unordered_set<InfoSub*> > subOrderMap;
|
||||
|
||||
typedef boost::unordered_map<std::string, RPCSub* > subRpcMapType;
|
||||
|
||||
@@ -104,6 +105,7 @@ protected:
|
||||
subInfoMapType mSubRTAccount;
|
||||
subSubmitMapType mSubmitMap; // TODO: probably dump this
|
||||
|
||||
|
||||
subRpcMapType mRpcSubMap;
|
||||
|
||||
boost::unordered_set<InfoSub*> mSubLedger; // accepted ledgers
|
||||
@@ -283,6 +285,9 @@ public:
|
||||
bool subServer(InfoSub* ispListener, Json::Value& jvResult);
|
||||
bool unsubServer(InfoSub* ispListener);
|
||||
|
||||
bool subBook(InfoSub* ispListener, uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut);
|
||||
bool unsubBook(InfoSub* ispListener, uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut);
|
||||
|
||||
bool subTransactions(InfoSub* ispListener);
|
||||
bool unsubTransactions(InfoSub* ispListener);
|
||||
|
||||
|
||||
@@ -20,4 +20,6 @@ OrderBook::OrderBook(SerializedLedgerEntry::pointer ledgerEntry)
|
||||
|
||||
mBookBase=Ledger::getBookBase(mCurrencyIn, mIssuerIn, mCurrencyOut, mIssuerOut);
|
||||
}
|
||||
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "SerializedLedger.h"
|
||||
#include "NetworkOPs.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
/*
|
||||
Encapsulates the SLE for an orderbook
|
||||
*/
|
||||
|
||||
@@ -5,9 +5,18 @@
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
// TODO: this would be way faster if we could just look under the order dirs
|
||||
OrderBookDB::OrderBookDB(Ledger::pointer ledger)
|
||||
OrderBookDB::OrderBookDB()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// TODO: this would be way faster if we could just look under the order dirs
|
||||
void OrderBookDB::setup(Ledger::pointer ledger)
|
||||
{
|
||||
mXRPOrders.clear();
|
||||
mIssuerMap.clear();
|
||||
mKnownMap.clear();
|
||||
|
||||
// walk through the entire ledger looking for orderbook entries
|
||||
uint256 currentIndex = ledger->getFirstLedgerIndex();
|
||||
|
||||
@@ -70,4 +79,151 @@ void OrderBookDB::getBooks(const uint160& issuerID, const uint160& currencyID, s
|
||||
}
|
||||
}
|
||||
|
||||
BookListeners::pointer OrderBookDB::makeBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut)
|
||||
{
|
||||
BookListeners::pointer ret=getBookListeners(currencyIn, currencyOut, issuerIn, issuerOut);
|
||||
if(!ret)
|
||||
{
|
||||
ret=BookListeners::pointer(new BookListeners);
|
||||
mListeners[issuerIn][issuerOut][currencyIn][currencyOut]=ret;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
BookListeners::pointer OrderBookDB::getBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut)
|
||||
{
|
||||
std::map<uint160, std::map<uint160, std::map<uint160, std::map<uint160, BookListeners::pointer> > > >::iterator it0=mListeners.find(issuerIn);
|
||||
if(it0 != mListeners.end())
|
||||
{
|
||||
std::map<uint160, std::map<uint160, std::map<uint160, BookListeners::pointer> > >::iterator it1=(*it0).second.find(issuerOut);
|
||||
if(it1 != (*it0).second.end())
|
||||
{
|
||||
std::map<uint160, std::map<uint160, BookListeners::pointer> >::iterator it2=(*it1).second.find(currencyIn);
|
||||
if(it2 != (*it1).second.end())
|
||||
{
|
||||
std::map<uint160, BookListeners::pointer>::iterator it3=(*it2).second.find(currencyOut);
|
||||
if(it3 != (*it2).second.end())
|
||||
{
|
||||
return( (*it3).second );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(BookListeners::pointer());
|
||||
}
|
||||
|
||||
/*
|
||||
"CreatedNode" : {
|
||||
"LedgerEntryType" : "Offer",
|
||||
"LedgerIndex" : "F353BF8A7DCE35EA2985596F4C8421E30EF3B9A21618566BFE0ED00B62A8A5AB",
|
||||
"NewFields" : {
|
||||
"Account" : "rB5TihdPbKgMrkFqrqUC3yLdE8hhv4BdeY",
|
||||
"BookDirectory" : "FF26BE244767D0EA9EFD523941439009E4185E4CBB918F714C08E1BC9BF04000",
|
||||
"Sequence" : 112,
|
||||
"TakerGets" : "400000000",
|
||||
"TakerPays" : {
|
||||
"currency" : "BTC",
|
||||
"issuer" : "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV",
|
||||
"value" : "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"ModifiedNode" : {
|
||||
"FinalFields" : {
|
||||
"Account" : "rHTxKLzRbniScyQFGMb3NodmxA848W8dKM",
|
||||
"BookDirectory" : "407AF8FFDE71114B1981574FDDA9B0334572D56FC579735B4B0BD7A625405555",
|
||||
"BookNode" : "0000000000000000",
|
||||
"Flags" : 0,
|
||||
"OwnerNode" : "0000000000000000",
|
||||
"Sequence" : 32,
|
||||
"TakerGets" : "149900000000",
|
||||
"TakerPays" : {
|
||||
"currency" : "USD",
|
||||
"issuer" : "r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X",
|
||||
"value" : "49.96666666666667"
|
||||
}
|
||||
},
|
||||
"LedgerEntryType" : "Offer",
|
||||
"LedgerIndex" : "C60F8CC514208FA5F7BD03CF1B64B38B7183CD52318FCBBD3726350D4FE693B0",
|
||||
"PreviousFields" : {
|
||||
"TakerGets" : "150000000000",
|
||||
"TakerPays" : {
|
||||
"currency" : "USD",
|
||||
"issuer" : "r9vbV3EHvXWjSkeQ6CAcYVPGeq7TuiXY2X",
|
||||
"value" : "50"
|
||||
}
|
||||
},
|
||||
"PreviousTxnID" : "1A6AAE3F1AC5A8A7554A5ABC395D17FED5BF62CD90181AA8E4315EDFED4EDEB3",
|
||||
"PreviousTxnLgrSeq" : 140734
|
||||
}
|
||||
|
||||
*/
|
||||
// Based on the meta, send the meta to the streams that are listening
|
||||
// We need to determine which streams a given meta effects
|
||||
void OrderBookDB::processTxn(const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta,Json::Value& jvObj)
|
||||
{
|
||||
if(terResult==tesSUCCESS)
|
||||
{
|
||||
// check if this is an offer or an offer cancel or a payment that consumes an offer
|
||||
//check to see what the meta looks like
|
||||
BOOST_FOREACH(STObject& node,meta->getNodes())
|
||||
{
|
||||
try{
|
||||
if(node.getFieldU16(sfLedgerEntryType)==ltOFFER)
|
||||
{
|
||||
SField* field=NULL;
|
||||
|
||||
if(node.getFName() == sfModifiedNode)
|
||||
{
|
||||
field=&sfPreviousFields;
|
||||
}else if(node.getFName() == sfCreatedNode)
|
||||
{
|
||||
field=&sfNewFields;
|
||||
}
|
||||
|
||||
const STObject* previous = dynamic_cast<const STObject*>(node.peekAtPField(*field));
|
||||
if(previous)
|
||||
{
|
||||
STAmount& takerGets = previous->getFieldAmount(sfTakerGets);
|
||||
uint160 currencyOut=takerGets.getCurrency();
|
||||
uint160 issuerOut=takerGets.getIssuer();
|
||||
|
||||
STAmount& takerPays = previous->getFieldAmount(sfTakerPays);
|
||||
uint160 currencyIn=takerPays.getCurrency();
|
||||
uint160 issuerIn=takerPays.getIssuer();
|
||||
|
||||
// determine the OrderBook
|
||||
BookListeners::pointer book=getBookListeners(currencyIn,currencyOut,issuerIn,issuerOut);
|
||||
if(book) book->publish(jvObj);
|
||||
}
|
||||
}
|
||||
}catch(...)
|
||||
{
|
||||
cLog(lsINFO) << "Fields not found in OrderBookDB::processTxn";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BookListeners::addSubscriber(InfoSub* sub)
|
||||
{
|
||||
mListeners.insert(sub);
|
||||
}
|
||||
|
||||
void BookListeners::removeSubscriber(InfoSub* sub)
|
||||
{
|
||||
mListeners.erase(sub);
|
||||
}
|
||||
|
||||
void BookListeners::publish(Json::Value& jvObj)
|
||||
{
|
||||
//Json::Value jvObj=node.getJson(0);
|
||||
|
||||
BOOST_FOREACH(InfoSub* sub,mListeners)
|
||||
{
|
||||
sub->send(jvObj);
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -1,21 +1,39 @@
|
||||
#include "Ledger.h"
|
||||
#include "OrderBook.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
|
||||
//
|
||||
// XXX Eventually make this cached and just update it as transactions come in.
|
||||
// But, for now it is probably faster to just generate it each time.
|
||||
//
|
||||
|
||||
class BookListeners
|
||||
{
|
||||
boost::unordered_set<InfoSub*> mListeners;
|
||||
public:
|
||||
typedef boost::shared_ptr<BookListeners> pointer;
|
||||
|
||||
void addSubscriber(InfoSub* sub);
|
||||
void removeSubscriber(InfoSub* sub);
|
||||
void publish(Json::Value& jvObj);
|
||||
};
|
||||
|
||||
class OrderBookDB
|
||||
{
|
||||
std::vector<OrderBook::pointer> mEmptyVector;
|
||||
std::vector<OrderBook::pointer> mXRPOrders;
|
||||
std::map<uint160, std::vector<OrderBook::pointer> > mIssuerMap;
|
||||
//std::vector<OrderBook::pointer> mAllOrderBooks;
|
||||
|
||||
// issuerIn, issuerOut, currencyIn, currencyOut
|
||||
std::map<uint160, std::map<uint160, std::map<uint160, std::map<uint160, BookListeners::pointer> > > > mListeners;
|
||||
|
||||
std::map<uint256, bool > mKnownMap;
|
||||
|
||||
public:
|
||||
OrderBookDB(Ledger::pointer ledger);
|
||||
OrderBookDB();
|
||||
void setup(Ledger::pointer ledger);
|
||||
|
||||
// return list of all orderbooks that want XRP
|
||||
std::vector<OrderBook::pointer>& getXRPInBooks(){ return mXRPOrders; }
|
||||
@@ -28,6 +46,14 @@ public:
|
||||
|
||||
// returns the best rate we can find
|
||||
float getPrice(uint160& currencyIn,uint160& currencyOut);
|
||||
|
||||
|
||||
BookListeners::pointer getBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut);
|
||||
BookListeners::pointer makeBookListeners(uint160 currencyIn, uint160 currencyOut, uint160 issuerIn, uint160 issuerOut);
|
||||
|
||||
// see if this txn effects any orderbook
|
||||
void processTxn(const SerializedTransaction& stTxn, TER terResult,TransactionMetaSet::pointer& meta,Json::Value& jvObj);
|
||||
|
||||
};
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
SETUP_LOG();
|
||||
|
||||
/*
|
||||
JED: V IIII
|
||||
|
||||
we just need to find a succession of the highest quality paths there until we find enough width
|
||||
|
||||
Don't do branching within each path
|
||||
@@ -134,12 +132,13 @@ Pathfinder::Pathfinder(const RippleAddress& uSrcAccountID, const RippleAddress&
|
||||
mDstAccountID(uDstAccountID.getAccountID()),
|
||||
mDstAmount(saDstAmount),
|
||||
mSrcCurrencyID(uSrcCurrencyID),
|
||||
mSrcIssuerID(uSrcIssuerID),
|
||||
mOrderBook(theApp->getLedgerMaster().getCurrentLedger())
|
||||
mSrcIssuerID(uSrcIssuerID)
|
||||
{
|
||||
mLedger = theApp->getLedgerMaster().getCurrentLedger();
|
||||
mSrcAmount = STAmount(uSrcCurrencyID, uSrcIssuerID, 1, 0, true); // -1/uSrcIssuerID/uSrcIssuerID
|
||||
|
||||
theApp->getOrderBookDB().setup( theApp->getLedgerMaster().getCurrentLedger()); // TODO: have the orderbook update itself rather than rebuild it from scratch each time
|
||||
|
||||
// Construct the default path for later comparison.
|
||||
|
||||
PathState::pointer psDefault = boost::make_shared<PathState>(mDstAmount, mSrcAmount, mLedger);
|
||||
@@ -326,8 +325,7 @@ bool Pathfinder::findPaths(const unsigned int iMaxSteps, const unsigned int iMax
|
||||
else if (!speEnd.mCurrencyID)
|
||||
{
|
||||
// Cursor is for XRP, continue with qualifying books: XRP -> non-XRP
|
||||
|
||||
BOOST_FOREACH(OrderBook::ref book, mOrderBook.getXRPInBooks())
|
||||
BOOST_FOREACH(OrderBook::ref book, theApp->getOrderBookDB().getXRPInBooks())
|
||||
{
|
||||
// New end is an order book with the currency and issuer.
|
||||
|
||||
@@ -420,7 +418,8 @@ bool Pathfinder::findPaths(const unsigned int iMaxSteps, const unsigned int iMax
|
||||
// Every book that wants the source currency.
|
||||
std::vector<OrderBook::pointer> books;
|
||||
|
||||
mOrderBook.getBooks(speEnd.mIssuerID, speEnd.mCurrencyID, books);
|
||||
|
||||
theApp->getOrderBookDB().getBooks(speEnd.mIssuerID, speEnd.mCurrencyID, books);
|
||||
|
||||
BOOST_FOREACH(OrderBook::ref book, books)
|
||||
{
|
||||
@@ -573,7 +572,7 @@ void Pathfinder::addOptions(PathOption::pointer tail)
|
||||
{
|
||||
if (!tail->mCurrencyID)
|
||||
{ // source XRP
|
||||
BOOST_FOREACH(OrderBook::ref book, mOrderBook.getXRPInBooks())
|
||||
BOOST_FOREACH(OrderBook::ref book, theApp->getOrderBookDB().getXRPInBooks())
|
||||
{
|
||||
PathOption::pointer pathOption(new PathOption(tail));
|
||||
|
||||
@@ -607,7 +606,7 @@ void Pathfinder::addOptions(PathOption::pointer tail)
|
||||
|
||||
// every offer that wants the source currency
|
||||
std::vector<OrderBook::pointer> books;
|
||||
mOrderBook.getBooks(tail->mCurrentAccount, tail->mCurrencyID, books);
|
||||
theApp->getOrderBookDB().getBooks(tail->mCurrentAccount, tail->mCurrencyID, books);
|
||||
|
||||
BOOST_FOREACH(OrderBook::ref book,books)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "SerializedTypes.h"
|
||||
#include "RippleAddress.h"
|
||||
#include "OrderBookDB.h"
|
||||
#include "RippleCalc.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
@@ -42,7 +41,7 @@ class Pathfinder
|
||||
uint160 mSrcIssuerID;
|
||||
STAmount mSrcAmount;
|
||||
|
||||
OrderBookDB mOrderBook;
|
||||
//OrderBookDB mOrderBook;
|
||||
Ledger::pointer mLedger;
|
||||
PathState::pointer mPsDefault;
|
||||
|
||||
|
||||
@@ -2455,6 +2455,25 @@ Json::Value RPCHandler::doSubscribe(Json::Value jvRequest)
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("books"))
|
||||
{
|
||||
for (Json::Value::iterator it = jvRequest["books"].begin(); it != jvRequest["books"].end(); it++)
|
||||
{
|
||||
uint160 currencyOut;
|
||||
STAmount::issuerFromString(currencyOut,(*it)["CurrencyOut"].asString());
|
||||
uint160 issuerOut=RippleAddress::createNodePublic( (*it)["IssuerOut"].asString() ).getAccountID();
|
||||
uint160 currencyIn;
|
||||
STAmount::issuerFromString(currencyOut,(*it)["CurrencyIn"].asString());
|
||||
uint160 issuerIn=RippleAddress::createNodePublic( (*it)["IssuerIn"].asString() ).getAccountID();
|
||||
|
||||
mNetOps->subBook(ispSub,currencyIn,currencyOut,issuerIn,issuerOut);
|
||||
if((*it)["StateNow"].asBool())
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
@@ -2552,6 +2571,21 @@ Json::Value RPCHandler::doUnsubscribe(Json::Value jvRequest)
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("books"))
|
||||
{
|
||||
for (Json::Value::iterator it = jvRequest["books"].begin(); it != jvRequest["books"].end(); it++)
|
||||
{
|
||||
uint160 currencyOut;
|
||||
STAmount::issuerFromString(currencyOut,(*it)["CurrencyOut"].asString());
|
||||
uint160 issuerOut=RippleAddress::createNodePublic( (*it)["IssuerOut"].asString() ).getAccountID();
|
||||
uint160 currencyIn;
|
||||
STAmount::issuerFromString(currencyOut,(*it)["CurrencyIn"].asString());
|
||||
uint160 issuerIn=RippleAddress::createNodePublic( (*it)["IssuerIn"].asString() ).getAccountID();
|
||||
|
||||
mNetOps->unsubBook(ispSub,currencyIn,currencyOut,issuerIn,issuerOut);
|
||||
}
|
||||
}
|
||||
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "key.h"
|
||||
#include "Config.h"
|
||||
#include "BitcoinUtil.h"
|
||||
#include "rfc1751.h"
|
||||
#include "utils.h"
|
||||
#include "Log.h"
|
||||
#include "Serializer.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ public:
|
||||
void addRaw(Serializer&, TER, uint32 index);
|
||||
|
||||
STObject getAsObject() const;
|
||||
STArray& getNodes(){ return(mNodes); }
|
||||
|
||||
static bool thread(STObject& node, const uint256& prevTxID, uint32 prevLgrID);
|
||||
};
|
||||
|
||||
Submodule src/js/sjcl updated: dbdef434e7...d04d0bdccd
@@ -39,8 +39,8 @@ buster.testCase("Fee Changes", {
|
||||
*/
|
||||
|
||||
buster.testCase("Sending", {
|
||||
'setUp' : testutils.build_setup(),
|
||||
// 'setUp' : testutils.build_setup({verbose: true , no_server: true}),
|
||||
//'setUp' : testutils.build_setup(),
|
||||
'setUp' : testutils.build_setup({verbose: true , no_server: true}),
|
||||
'tearDown' : testutils.build_teardown(),
|
||||
|
||||
"send XRP to non-existent account with insufficent fee" :
|
||||
@@ -974,7 +974,7 @@ buster.testCase("Indirect ripple", {
|
||||
});
|
||||
},
|
||||
|
||||
"indirect ripple with path" :
|
||||
"=> indirect ripple with path" :
|
||||
function (done) {
|
||||
var self = this;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user