diff --git a/src/mastercore.cpp b/src/mastercore.cpp index 4ff12a910eab..ae464af03977 100644 --- a/src/mastercore.cpp +++ b/src/mastercore.cpp @@ -114,6 +114,7 @@ int msc_debug_tally = 1; int msc_debug_sp = 1; int msc_debug_sto = 1; int msc_debug_txdb = 0; +int msc_debug_tradedb = 1; int msc_debug_persistence = 0; int msc_debug_metadex = 1; int msc_debug_metadex2= 1; @@ -151,6 +152,7 @@ static const int txRestrictionsRules[][3] = { }; CMPTxList *mastercore::p_txlistdb; +CMPTradeList *mastercore::t_tradelistdb; // a copy from main.cpp -- unfortunately that one is in a private namespace int mastercore::GetHeight() @@ -2291,6 +2293,7 @@ int mastercore_init() exodus_address = exodus_testnet; }*/ + t_tradelistdb = new CMPTradeList(GetDataDir() / "MP_tradelist", 1<<20, false, fReindex); p_txlistdb = new CMPTxList(GetDataDir() / "MP_txlist", 1<<20, false, fReindex); _my_sps = new CMPSPInfo(GetDataDir() / "MP_spinfo"); MPPersistencePath = GetDataDir() / "MP_persist"; @@ -2388,6 +2391,10 @@ int mastercore_shutdown() { delete p_txlistdb; p_txlistdb = NULL; } + if (t_tradelistdb) + { + delete t_tradelistdb; t_tradelistdb = NULL; + } if (mp_fp) { @@ -3078,6 +3085,170 @@ unsigned int n_found = 0; return (n_found); } +// MPTradeList here +bool CMPTradeList::getMatchingTrades(const uint256 txid, unsigned int propertyId, Array *tradeArray, uint64_t *totalBought) +{ + if (!tdb) return false; + totalBought = 0; + leveldb::Slice skey, svalue; + unsigned int count = 0; + std::vector vstr; + string txidStr = txid.ToString(); + leveldb::Iterator* it = tdb->NewIterator(iteroptions); + for(it->SeekToFirst(); it->Valid(); it->Next()) + { + skey = it->key(); + svalue = it->value(); + string strkey = it->key().ToString(); + size_t txidMatch = strkey.find(txidStr); + if(txidMatch!=std::string::npos) + { + // we have a matching trade involving this txid + // get the txid of the match + string matchTxid; + // make sure string is correct length + if (strkey.length() == 129) + { + if (txidMatch==0) { matchTxid = strkey.substr(65,64); } else { matchTxid = strkey.substr(0,64); } + + string strvalue = it->value().ToString(); + boost::split(vstr, strvalue, boost::is_any_of(":"), token_compress_on); + if (7 == vstr.size()) // ensure there are the expected amount of tokens + { + string address; + string address1 = vstr[0]; + string address2 = vstr[1]; + unsigned int prop1; + unsigned int prop2; + uint64_t uAmount1; + uint64_t uAmount2; + uint64_t nBought; + string amountBought; + string amountSold; + string amount1; + string amount2; + prop1 = boost::lexical_cast(vstr[2]); + prop2 = boost::lexical_cast(vstr[3]); + uAmount1 = boost::lexical_cast(vstr[4]); + uAmount2 = boost::lexical_cast(vstr[5]); + if(isPropertyDivisible(prop1)) + { amount1 = FormatDivisibleMP(uAmount1); } + else + { amount1 = FormatIndivisibleMP(uAmount1); } + if(isPropertyDivisible(prop2)) + { amount2 = FormatDivisibleMP(uAmount2); } + else + { amount2 = FormatIndivisibleMP(uAmount2); } + + // correct orientation of trade + if (prop1 == propertyId) + { + address = address2; + amountBought = amount2; + amountSold = amount1; + nBought = boost::lexical_cast(vstr[5]); + } + else + { + address = address1; + amountBought = amount1; + amountSold = amount2; + nBought = boost::lexical_cast(vstr[4]); + } + int blockNum = atoi(vstr[6]); + Object trade; + trade.push_back(Pair("txid", matchTxid)); + trade.push_back(Pair("address", address)); + trade.push_back(Pair("block", blockNum)); + trade.push_back(Pair("amountsold", amountSold)); + trade.push_back(Pair("amountbought", amountBought)); + tradeArray->push_back(trade); + ++count; + totalBought=totalBought + nBought; + } + } + } + } + delete it; + if (count) { return true; } else { return false; } +} + +void CMPTradeList::recordTrade(const uint256 txid1, const uint256 txid2, string address1, string address2, unsigned int prop1, unsigned int prop2, uint64_t amount1, uint64_t amount2, int blockNum) +{ + if (!tdb) return; + const string key = txid1.ToString() + "+" + txid2.ToString(); + const string value = strprintf("%s:%s:%u:%u:%lu:%lu:%d", address1, address2, prop1, prop2, amount1, amount2, blockNum); + Status status; + if (tdb) + { + status = tdb->Put(writeoptions, key, value); + ++tWritten; + if (msc_debug_tradedb) fprintf(mp_fp, "%s(): %s, line %d, file: %s\n", __FUNCTION__, status.ToString().c_str(), __LINE__, __FILE__); + } +} + +// delete any trades after blockNum +int CMPTradeList::deleteAboveBlock(int blockNum) +{ + leveldb::Slice skey, svalue; + unsigned int count = 0; + std::vector vstr; + int block; + unsigned int n_found = 0; + leveldb::Iterator* it = tdb->NewIterator(iteroptions); + for(it->SeekToFirst(); it->Valid(); it->Next()) + { + skey = it->key(); + svalue = it->value(); + ++count; + string strvalue = it->value().ToString(); + boost::split(vstr, strvalue, boost::is_any_of(":"), token_compress_on); + // only care about the block number/height here + if (7 == vstr.size()) + { + block = atoi(vstr[6]); + + if (block >= blockNum) + { + ++n_found; + fprintf(mp_fp, "%s() DELETING FROM TRADEDB: %s=%s\n", __FUNCTION__, skey.ToString().c_str(), svalue.ToString().c_str()); + tdb->Delete(writeoptions, skey); + } + } + } + + printf("%s(%d); tradedb n_found= %d\n", __FUNCTION__, blockNum, n_found); + + delete it; + + return (n_found); +} + +void CMPTradeList::printStats() +{ + fprintf(mp_fp, "CMPTradeList stats: tWritten= %d , tRead= %d\n", tWritten, tRead); +} + +void CMPTradeList::printAll() +{ + int count = 0; + Slice skey, svalue; + + readoptions.fill_cache = false; + + Iterator* it = tdb->NewIterator(readoptions); + + for(it->SeekToFirst(); it->Valid(); it->Next()) + { + skey = it->key(); + svalue = it->value(); + ++count; + printf("entry #%8d= %s:%s\n", count, skey.ToString().c_str(), svalue.ToString().c_str()); + } + + delete it; +} + // global wrapper, block numbers are inclusive, if ending_block is 0 top of the chain will be used bool mastercore::isMPinBlockRange(int starting_block, int ending_block, bool bDeleteFound) { @@ -3178,6 +3349,7 @@ int mastercore_handler_block_begin(int nBlockPrev, CBlockIndex const * pBlockInd // reset states if(!readPersistence()) clear_all_state(); p_txlistdb->isMPinBlockRange(pBlockIndex->nHeight, reorgRecoveryMaxHeight, true); + t_tradelistdb->deleteAboveBlock(pBlockIndex->nHeight); reorgRecoveryMaxHeight = 0; diff --git a/src/mastercore.h b/src/mastercore.h index 46f288c62780..c47acd1d785e 100644 --- a/src/mastercore.h +++ b/src/mastercore.h @@ -290,6 +290,48 @@ typedef struct } }; +/* leveldb-based storage for trade history - trades will be listed here atomically with key txid1:txid2 */ +class CMPTradeList +{ +protected: + // datebase options reused from MPTxList + leveldb::Options options; + leveldb::ReadOptions readoptions; + leveldb::ReadOptions iteroptions; + leveldb::WriteOptions writeoptions; + leveldb::WriteOptions syncoptions; + leveldb::DB *tdb; + // statistics + unsigned int tWritten; + unsigned int tRead; + +public: + CMPTradeList(const boost::filesystem::path &path, size_t nCacheSize, bool fMemory, bool fWipe):tWritten(0),tRead(0) + { + options.paranoid_checks = true; + options.create_if_missing = true; + readoptions.verify_checksums = true; + iteroptions.verify_checksums = true; + iteroptions.fill_cache = false; + syncoptions.sync = true; + leveldb::Status status = leveldb::DB::Open(options, path.string(), &tdb); + printf("%s(): %s, line %d, file: %s\n", __FUNCTION__, status.ToString().c_str(), __LINE__, __FILE__); + } + + ~CMPTradeList() + { + delete tdb; + tdb = NULL; + } + + void recordTrade(const uint256 txid1, const uint256 txid2, string address1, string address2, unsigned int prop1, unsigned int prop2, uint64_t amount1, uint64_t amount2, int blockNum); + int deleteAboveBlock(int blockNum); + bool exists(const uint256 &txid); + void printStats(); + void printAll(); + bool getMatchingTrades(const uint256 txid, unsigned int propertyId, Array *tradeArray, uint64_t *totalBought); +}; + /* leveldb-based storage for the list of ALL Master Protocol TXIDs (key) with validity bit & other misc data as value */ class CMPTxList { @@ -402,6 +444,7 @@ namespace mastercore { extern std::map mp_tally_map; extern CMPTxList *p_txlistdb; +extern CMPTradeList *t_tradelistdb; typedef std::map PendingMap; diff --git a/src/mastercore_dex.cpp b/src/mastercore_dex.cpp index e529aeecae2a..ae48164a4a2a 100644 --- a/src/mastercore_dex.cpp +++ b/src/mastercore_dex.cpp @@ -286,6 +286,8 @@ const XDOUBLE desprice = (1/buyersprice); // inverse } if (msc_debug_metadex) fprintf(mp_fp, "==== TRADED !!! %u=%s\n", NewReturn, getTradeReturnType(NewReturn).c_str()); + // record the trade in MPTradeList + t_tradelistdb->recordTrade(p_older->getHash(), newo->getHash(), p_older->getAddr(), newo->getAddr(), p_older->getProperty(), newo->getProperty(), buyer_amountGot, paymentAmount, newo->getBlock()); if (msc_debug_metadex) fprintf(mp_fp, "++ erased old: %s\n", iitt->ToString().c_str()); // erase the old seller element diff --git a/src/mastercore_rpc.cpp b/src/mastercore_rpc.cpp index 127971d30dd1..dd7017854f1d 100644 --- a/src/mastercore_rpc.cpp +++ b/src/mastercore_rpc.cpp @@ -131,6 +131,13 @@ int extra2 = 0, extra3 = 0; case 6: MetaDEx_debug_print(); break; + + case 7: + // display the whole CMPTradeList (leveldb) + t_tradelistdb->printAll(); + t_tradelistdb->printStats(); + break; + } return GetHeight(); @@ -1522,6 +1529,7 @@ static int populateRPCTransactionObject(uint256 txid, Object *txobj, string filt bool bIsMine = false; bool isMPTx = false; uint64_t nFee = 0; + bool offerOpen = false; string MPTxType; unsigned int MPTxTypeInt; string selectedAddress; @@ -1548,11 +1556,8 @@ static int populateRPCTransactionObject(uint256 txid, Object *txobj, string filt bool mdex = false; bool mdex_propertyId_Div = false; uint64_t mdex_propertyWanted = 0; + uint64_t mdex_amountWanted = 0; bool mdex_propertyWanted_Div = false; - string mdex_unitPrice; - string mdex_invUnitPrice; - uint64_t mdex_amt_orig_sale = 0; - uint64_t mdex_amt_des = 0; unsigned int mdex_action = 0; if ((0 == blockHash) || (NULL == mapBlockIndex[blockHash])) { return MP_TX_UNCONFIRMED; } @@ -1566,6 +1571,7 @@ static int populateRPCTransactionObject(uint256 txid, Object *txobj, string filt mp_obj.SetNull(); CMPOffer temp_offer; + CMPMetaDEx temp_metadexoffer; // replace initial MP detection with levelDB lookup instead of parse, this is much faster especially in calls like list/search if (p_txlistdb->exists(wtxid)) @@ -1647,44 +1653,22 @@ static int populateRPCTransactionObject(uint256 txid, Object *txobj, string filt switch (MPTxTypeInt) { case MSC_TYPE_METADEX: + offerOpen = false; if (0 == mp_obj.step2_Value()) { - mdex = true; - - for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) - { - md_PricesMap & prices = my_it->second; - for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) - { - md_Set & indexes = (it->second); - for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) - { - CMPMetaDEx obj = *it; - CMPSPInfo::Entry sp; - - - if( obj.getHash().GetHex() == wtxid.GetHex() ) { - propertyId = mp_obj.getProperty(); - amount = mp_obj.getAmount(); - _my_sps->getSP(propertyId, sp); - mdex_propertyId_Div = sp.isDivisible(); - mdex_propertyWanted = obj.getDesProperty(); - _my_sps->getSP(mdex_propertyWanted, sp); - mdex_propertyWanted_Div = sp.isDivisible(); - - //uint64_t *price = obj.getPrice(); - //uint64_t *invprice = obj.getInversePrice(); - - //mdex_unitPrice = strprintf("%lu.%.8s", price[0], boost::lexical_cast(price[1]) ).c_str(); - //mdex_invUnitPrice = strprintf("%lu.%.8s", invprice[0], boost::lexical_cast(invprice[1]) ).c_str(); - mdex_amt_orig_sale = obj.getAmount(); - mdex_amt_des = obj.getAmountDesired(); - mdex_action = obj.getAction(); - } - } - } + mdex = true; + propertyId = mp_obj.getProperty(); + amount = mp_obj.getAmount(); + mdex_propertyId_Div = isPropertyDivisible(propertyId); + if (0 <= mp_obj.interpretPacket(NULL,&temp_metadexoffer)) + { + mdex_propertyWanted = temp_metadexoffer.getDesProperty(); + mdex_propertyWanted_Div = isPropertyDivisible(mdex_propertyWanted); + mdex_amountWanted = temp_metadexoffer.getAmountDesired(); + mdex_action = temp_metadexoffer.getAction(); } } + break; case MSC_TYPE_GRANT_PROPERTY_TOKENS: if (0 == mp_obj.step2_Value()) @@ -1826,19 +1810,22 @@ static int populateRPCTransactionObject(uint256 txid, Object *txobj, string filt txobj->push_back(Pair("fee", ValueFromAmount(nFee))); txobj->push_back(Pair("blocktime", blockTime)); txobj->push_back(Pair("type", MPTxType)); - txobj->push_back(Pair("propertyid", propertyId)); + if (!MSC_TYPE_METADEX == MPTxTypeInt) txobj->push_back(Pair("propertyid", propertyId)); if ((MSC_TYPE_CREATE_PROPERTY_VARIABLE == MPTxTypeInt) || (MSC_TYPE_CREATE_PROPERTY_FIXED == MPTxTypeInt) || (MSC_TYPE_CREATE_PROPERTY_MANUAL == MPTxTypeInt)) { txobj->push_back(Pair("propertyname", propertyName)); } - txobj->push_back(Pair("divisible", divisible)); - if (divisible) - { - txobj->push_back(Pair("amount", FormatDivisibleMP(amount))); //divisible, format w/ bitcoins VFA func - } - else + if (!MSC_TYPE_METADEX == MPTxTypeInt) txobj->push_back(Pair("divisible", divisible)); + if (!MSC_TYPE_METADEX == MPTxTypeInt) { - txobj->push_back(Pair("amount", FormatIndivisibleMP(amount))); //indivisible, push raw 64 + if (divisible) + { + txobj->push_back(Pair("amount", FormatDivisibleMP(amount))); //divisible, format w/ bitcoins VFA func + } + else + { + txobj->push_back(Pair("amount", FormatIndivisibleMP(amount))); //indivisible, push raw 64 + } } if (crowdPurchase) { @@ -1865,18 +1852,25 @@ static int populateRPCTransactionObject(uint256 txid, Object *txobj, string filt if (3 == sell_subaction) txobj->push_back(Pair("subaction", "Cancel")); txobj->push_back(Pair("bitcoindesired", ValueFromAmount(sell_btcdesired))); } - if (mdex) + if (MSC_TYPE_METADEX == MPTxTypeInt) { - txobj->push_back(Pair("property_owned", propertyId)); - txobj->push_back(Pair("property_owned_divisible", mdex_propertyId_Div)); - txobj->push_back(Pair("property_desired", mdex_propertyWanted)); - txobj->push_back(Pair("property_desired_divisible", mdex_propertyWanted_Div)); + string amountOffered; + string amountDesired; + if (mdex_propertyId_Div) {amountOffered=FormatDivisibleMP(amount);} else {amountOffered=FormatIndivisibleMP(amount);} + if (mdex_propertyWanted_Div) {amountDesired=FormatDivisibleMP(mdex_amountWanted);} else {amountDesired=FormatIndivisibleMP(mdex_amountWanted);} + + txobj->push_back(Pair("amountoffered", amountOffered)); + txobj->push_back(Pair("propertyoffered", propertyId)); + txobj->push_back(Pair("propertyofferedisdivisible", mdex_propertyId_Div)); + txobj->push_back(Pair("amountdesired", amountDesired)); + txobj->push_back(Pair("propertydesired", mdex_propertyWanted)); + txobj->push_back(Pair("propertydesiredisdivisible", mdex_propertyWanted_Div)); + txobj->push_back(Pair("action", (uint64_t) mdex_action)); //txobj->push_back(Pair("unit_price", mdex_unitPrice ) ); //txobj->push_back(Pair("inverse_unit_price", mdex_invUnitPrice ) ); //active? - txobj->push_back(Pair("amount_original", FormatDivisibleMP(mdex_amt_orig_sale))); - txobj->push_back(Pair("amount_desired", FormatDivisibleMP(mdex_amt_des))); - txobj->push_back(Pair("action", (uint64_t) mdex_action)); + //txobj->push_back(Pair("amount_original", FormatDivisibleMP(mdex_amt_orig_sale))); + //txobj->push_back(Pair("amount_desired", FormatDivisibleMP(mdex_amt_des))); } txobj->push_back(Pair("valid", valid)); } @@ -2050,3 +2044,105 @@ Value listtransactions_MP(const Array& params, bool fHelp) return response; // return response array for JSON serialization } +Value gettrade_MP(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "gettrade_MP \"txid\"\n" + "\nGet detailed information and trade matches for a Master Protocol MetaDEx trade offer \n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id\n" + "\nResult:\n" + "{\n" + " \"txid\" : \"transactionid\", (string) The transaction id\n" + + HelpExampleCli("gettrade_MP", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + + HelpExampleRpc("gettrade_MP", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + ); + + uint256 hash; + hash.SetHex(params[0].get_str()); + Object tradeobj; + Object txobj; + + //get sender & propId + string senderAddress; + unsigned int propertyId = 0; + CTransaction wtx; + uint256 blockHash = 0; + if (!GetTransaction(hash, wtx, blockHash, true)) { return MP_TX_NOT_FOUND; } + CMPTransaction mp_obj; + int parseRC = parseTransaction(true, wtx, 0, 0, &mp_obj); + if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sa$ + { + if (0<=mp_obj.step1()) + { + senderAddress = mp_obj.getSender(); + if (0 == mp_obj.step2_Value()) + { + propertyId = mp_obj.getProperty(); + } + } + } + if (propertyId == 0) // something went wrong, couldn't decode property ID - bad packet? + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not a Master Protocol transaction"); + if (senderAddress.empty()) // something went wrong, couldn't decode transaction + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not a Master Protocol transaction"); + + // make a request to new RPC populator function to populate a transaction object + int populateResult = populateRPCTransactionObject(hash, &txobj); + + // check the response, throw any error codes if false + if (0>populateResult) + { + // TODO: consider throwing other error codes, check back with Bitcoin Core + switch (populateResult) + { + case MP_TX_NOT_FOUND: + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); + case MP_TX_UNCONFIRMED: + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unconfirmed transactions are not supported"); + case MP_BLOCK_NOT_IN_CHAIN: + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not part of the active chain"); + case MP_CROWDSALE_WITHOUT_PROPERTY: + throw JSONRPCError(RPC_INTERNAL_ERROR, "Potential database corruption: \ + \"Crowdsale Purchase\" without valid property identifier"); + case MP_INVALID_TX_IN_DB_FOUND: + throw JSONRPCError(RPC_INTERNAL_ERROR, "Potential database corruption: Invalid transaction found"); + case MP_TX_IS_NOT_MASTER_PROTOCOL: + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not a Master Protocol transaction"); + } + } + + // everything seems ok, now add status and get an array of matches to add to the object + // status - is order cancelled/closed-filled/open/open-partialfilled? + bool orderOpen = false; + // is the sell offer still open - need more efficient way to do this + for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) + { + if (my_it->first == propertyId) //at bear minimum only go deeper if it's the right property id + { + md_PricesMap & prices = my_it->second; + for (md_PricesMap::iterator it = prices.begin(); it != prices.end(); ++it) + { + md_Set & indexes = (it->second); + for (md_Set::iterator it = indexes.begin(); it != indexes.end(); ++it) + { + CMPMetaDEx obj = *it; + if( obj.getHash().GetHex() == hash.GetHex() ) orderOpen = true; + } + } + } + } + txobj.push_back(Pair("active", orderOpen)); + + // create array of matches + Array tradeArray; + uint64_t totalBought; + t_tradelistdb->getMatchingTrades(hash, propertyId, &tradeArray, &totalBought); + + // add array to object + txobj.push_back(Pair("matches", tradeArray)); + + // return object + return txobj; +} diff --git a/src/qt/balancesview.cpp b/src/qt/balancesview.cpp index 1899c519f1e2..f227e87adaca 100644 --- a/src/qt/balancesview.cpp +++ b/src/qt/balancesview.cpp @@ -46,6 +46,7 @@ #include "leveldb/db.h" #include "leveldb/write_batch.h" // end potentially overzealous includes +using namespace json_spirit; // since now using Array in mastercore.h this needs to come first #include "mastercore.h" using namespace mastercore; @@ -54,7 +55,6 @@ using namespace mastercore; using namespace std; using namespace boost; using namespace boost::assign; -using namespace json_spirit; using namespace leveldb; // end potentially overzealous using diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 58c2b231ad54..3ccfd2d06ecf 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -37,6 +37,7 @@ #include "leveldb/db.h" #include "leveldb/write_batch.h" // end potentially overzealous includes +using namespace json_spirit; // since now using Array in mastercore.h this needs to come first #include "mastercore.h" using namespace mastercore; @@ -45,7 +46,6 @@ using namespace mastercore; using namespace std; using namespace boost; using namespace boost::assign; -using namespace json_spirit; using namespace leveldb; // end potentially overzealous using diff --git a/src/qt/sendmpdialog.cpp b/src/qt/sendmpdialog.cpp index 718a9e4906f3..a94a9d54b01c 100644 --- a/src/qt/sendmpdialog.cpp +++ b/src/qt/sendmpdialog.cpp @@ -43,6 +43,7 @@ #include "leveldb/db.h" #include "leveldb/write_batch.h" // end potentially overzealous includes +using namespace json_spirit; // since now using Array in mastercore.h this needs to come first #include "mastercore.h" using namespace mastercore; @@ -51,7 +52,6 @@ using namespace mastercore; using namespace std; using namespace boost; using namespace boost::assign; -using namespace json_spirit; using namespace leveldb; // end potentially overzealous using diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 43be1fd9365d..5a2b733bcbd5 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -46,6 +46,7 @@ #include "leveldb/db.h" #include "leveldb/write_batch.h" // end potentially overzealous includes +using namespace json_spirit; // since now using Array in mastercore.h this needs to come first #include "mastercore.h" using namespace mastercore; @@ -54,7 +55,6 @@ using namespace mastercore; using namespace std; using namespace boost; using namespace boost::assign; -using namespace json_spirit; using namespace leveldb; // end potentially overzealous using diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 55e9015f9699..35cdc99c83f6 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -335,6 +335,7 @@ static const CRPCCommand vRPCCommands[] = { "gettradehistory_MP", &gettradehistory_MP, false, false, true }, { "sendtoowners_MP", &sendtoowners_MP, false, false, true }, { "sendrawtx_MP", &sendrawtx_MP, false, false, true }, + { "gettrade_MP", &gettrade_MP, false, false, true }, { "listblocktransactions_MP", &listblocktransactions_MP, false, false, true }, { "getallbalancesforaddress_MP", &getallbalancesforaddress_MP, false, false, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 0073138e488e..08629fe13bf7 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -203,6 +203,7 @@ extern json_spirit::Value getallbalancesforaddress_MP(const json_spirit::Array& extern json_spirit::Value getactivedexsells_MP(const json_spirit::Array& params, bool fHelp); // in mastercore.cpp extern json_spirit::Value gettransaction_MP(const json_spirit::Array& params, bool fHelp); // in mastercore.cpp extern json_spirit::Value trade_MP(const json_spirit::Array& params, bool fHelp); // in mastercore.cpp +extern json_spirit::Value gettrade_MP(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getorderbook_MP(const json_spirit::Array& params, bool fHelp); // in mastercore.cpp extern json_spirit::Value gettradessince_MP(const json_spirit::Array& params, bool fHelp); // in mastercore.cpp extern json_spirit::Value getopenorders_MP(const json_spirit::Array& params, bool fHelp);