Skip to content

Commit

Permalink
UI: move TradeHistoryDialog to cache map (non-final)
Browse files Browse the repository at this point in the history
commit to transfer remaining changes from old dev to new dev systems
  • Loading branch information
zathras-crypto committed May 18, 2015
1 parent 88413a9 commit aff7717
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 2 deletions.
18 changes: 18 additions & 0 deletions src/mastercore_mdex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,24 @@ int mastercore::MetaDEx_CANCEL_EVERYTHING(const uint256& txid, unsigned int bloc
return rc;
}

// searches the metadex maps to see if a trade is still open
// allows search to be optimized if propertyIdForSale is specified
bool mastercore::MetaDEx_isOpen(const uint256& txid, uint32_t propertyIdForSale)
{
for (md_PropertiesMap::iterator my_it = metadex.begin(); my_it != metadex.end(); ++my_it) {
if (propertyIdForSale != 0 && propertyIdForSale != my_it->first) continue;
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() == txid.GetHex() ) return true;
}
}
}
return false;
}

void mastercore::MetaDEx_debug_print(bool bShowPriceLevel, bool bDisplay)
{
file_log("<<<\n");
Expand Down
1 change: 1 addition & 0 deletions src/mastercore_mdex.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ int MetaDEx_CANCEL_ALL_FOR_PAIR(const uint256&, uint32_t, const std::string&, ui
int MetaDEx_CANCEL_EVERYTHING(const uint256& txid, uint32_t block, const std::string& sender_addr, unsigned char ecosystem);
bool MetaDEx_INSERT(const CMPMetaDEx& objMetaDEx);
void MetaDEx_debug_print(bool bShowPriceLevel = false, bool bDisplay = false);
bool MetaDEx_isOpen(const uint256& txid, uint32_t propertyIdForSale = 0);
}

#endif // MASTERCORE_MDEX_H
197 changes: 196 additions & 1 deletion src/qt/tradehistorydialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "wallet.h"
#include "base58.h"
#include "ui_interface.h"
#include "guiutil.h"
#include "txdb.h"

#include <boost/filesystem.hpp>

Expand Down Expand Up @@ -64,6 +64,7 @@ using namespace leveldb;
#include <QScrollBar>
#include <QTextDocument>
#include <QPushButton>
#include <QSortFilterProxyModel>

TradeHistoryDialog::TradeHistoryDialog(QWidget *parent) :
QDialog(parent),
Expand Down Expand Up @@ -124,6 +125,200 @@ TradeHistoryDialog::TradeHistoryDialog(QWidget *parent) :
connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
}

// Used to cache trades so we don't need to reparse all our transactions on every update
int TradeHistoryDialog::PopulateTradeHistoryMap()
{
// Attempt to obtain locks
CWallet *wallet = pwalletMain;
if (NULL == wallet) return -1;
TRY_LOCK(cs_main,lckMain);
if (!lckMain) return -1;
TRY_LOCK(wallet->cs_wallet, lckWallet);
if (!lckWallet) return -1;

int64_t nProcessed = 0; // number of new entries, forms return code

// ### START PENDING TRANSACTIONS PROCESSING ###
for(PendingMap::iterator it = my_pending.begin(); it != my_pending.end(); ++it) {
uint256 txid = it->first;

// check historyMap, if this tx exists don't waste resources doing anymore work on it
TradeHistoryMap::iterator hIter = tradeHistoryMap.find(txid);
if (hIter != tradeHistoryMap.end()) continue;

// grab pending object, extract details and skip if not a metadex trade
CMPPending *p_pending = &(it->second);
if (p_pending->type != MSC_TYPE_METADEX) continue;
uint64_t propertyId = p_pending->prop;
int64_t amount = p_pending->amount;

// create a TradeHistoryObject and populate it
TradeHistoryObject objTH;
objTH.blockHeight = 0;
objTH.blockByteOffset = 0; // attempt to use the position of the transaction in the wallet to provide a sortkey for pending
std::map<uint256, CWalletTx>::const_iterator walletIt = wallet->mapWallet.find(txid);
if (walletIt != wallet->mapWallet.end()) {
const CWalletTx* pendingWTx = &(*walletIt).second;
objTH.blockByteOffset = pendingWTx->nOrderPos;
}
objTH.valid = true; // all pending transactions are assumed to be valid
objTH.status = "Pending";
objTH.amountIn = "---";
objTH.amountOut = "---";
objTH.info = "Sell ";
if (isPropertyDivisible(propertyId)) {
objTH.info += FormatDivisibleShortMP(amount) + getTokenLabel(propertyId) + " (awaiting confirmation)";
} else {
objTH.info += FormatIndivisibleMP(amount) + getTokenLabel(propertyId) + " (awaiting confirmation)";
}

// add the new TradeHistoryObject to the map
tradeHistoryMap.insert(std::make_pair(txid, objTH));
nProcessed += 1;
}
// ### END PENDING TRANSACTIONS PROCESSING ###

// ### START WALLET TRANSACTIONS PROCESSING ###
std::list<CAccountingEntry> acentries;
CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, "*");
for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) {
CWalletTx *const pwtx = (*it).second.first;
if (pwtx == 0) continue;
uint256 hash = pwtx->GetHash();

// use levelDB to perform a fast check on whether it's a bitcoin or Omni tx and whether it's a trade
std::string tempStrValue;
if (!p_txlistdb->getTX(hash, tempStrValue)) continue;
std::vector<std::string> vstr;
boost::split(vstr, tempStrValue, boost::is_any_of(":"), token_compress_on);
if (vstr.size() > 2) {
if (atoi(vstr[2]) != MSC_TYPE_METADEX) continue;
}

// check historyMap, if this tx exists don't waste resources doing anymore work on it
TradeHistoryMap::iterator hIter = tradeHistoryMap.find(hash);
if (hIter != tradeHistoryMap.end()) {
// the tx is in historyMap, check if it has a blockheight of 0 (means a pending has confirmed & we should delete pending tx and add it again via parsing)
TradeHistoryObject *objTH = &(hIter->second);
if (objTH->blockHeight != 0) {
continue;
} else {
tradeHistoryMap.erase(hIter);
ui->tradeHistoryTable->setSortingEnabled(false); // disable sorting temporarily while we update the table (leaving enabled gives unexpected results)
QAbstractItemModel* tradeHistoryAbstractModel = ui->tradeHistoryTable->model();
QSortFilterProxyModel tradeHistoryProxy;
tradeHistoryProxy.setSourceModel(tradeHistoryAbstractModel);
tradeHistoryProxy.setFilterKeyColumn(0);
tradeHistoryProxy.setFilterFixedString(QString::fromStdString(hash.GetHex()));
QModelIndex rowIndex = tradeHistoryProxy.mapToSource(tradeHistoryProxy.index(0,0)); // map to the row in the actual table
if(rowIndex.isValid()) ui->tradeHistoryTable->removeRow(rowIndex.row()); // delete the pending tx row, it'll be readded as a proper confirmed transaction
ui->tradeHistoryTable->setSortingEnabled(true); // re-enable sorting
}
}

// tx not in historyMap, retrieve the transaction object
CTransaction wtx;
uint256 blockHash = 0;
if (!GetTransaction(hash, wtx, blockHash, true)) continue;
blockHash = pwtx->hashBlock;
if ((0 == blockHash) || (NULL == mapBlockIndex[blockHash])) continue;
CBlockIndex* pBlockIndex = mapBlockIndex[blockHash];
if (NULL == pBlockIndex) continue;
int blockHeight = pBlockIndex->nHeight;

// setup some variables
CMPTransaction mp_obj;
CMPMetaDEx temp_metadexoffer;
std::string statusText;
unsigned int propertyIdForSale = 0;
unsigned int propertyIdDesired = 0;
uint64_t amountForSale = 0;
uint64_t amountDesired = 0;
bool divisibleForSale = false;
bool divisibleDesired = false;
Array tradeArray;
uint64_t totalBought = 0;
uint64_t totalSold = 0;
bool orderOpen = false;
bool valid = false;

// parse the transaction
int parseRC = parseTransaction(true, wtx, blockHeight, 0, &mp_obj);
if (0 != parseRC) continue;
if (0<=mp_obj.step1()) {
int tmpblock=0;
uint32_t tmptype=0;
uint64_t amountNew=0;
valid = getValidMPTX(hash, &tmpblock, &tmptype, &amountNew);
if (0 == mp_obj.step2_Value()) {
propertyIdForSale = mp_obj.getProperty();
amountForSale = mp_obj.getAmount();
divisibleForSale = isPropertyDivisible(propertyIdForSale);
if (0 <= mp_obj.interpretPacket(NULL,&temp_metadexoffer)) {
uint8_t mdex_action = temp_metadexoffer.getAction();
if (mdex_action != 1) continue; // cancels aren't trades
propertyIdDesired = temp_metadexoffer.getDesProperty();
divisibleDesired = isPropertyDivisible(propertyIdDesired);
amountDesired = temp_metadexoffer.getAmountDesired();
t_tradelistdb->getMatchingTrades(hash, propertyIdForSale, &tradeArray, &totalSold, &totalBought);
orderOpen = MetaDEx_isOpen(hash, propertyIdForSale);
}
}
}

// work out status
bool partialFilled = false;
bool filled = false;
statusText = "Unknown";
if (totalSold > 0) partialFilled = true;
if (totalSold >= amountForSale) filled = true;
if (!orderOpen && !partialFilled) statusText = "Cancelled";
if (!orderOpen && partialFilled) statusText = "Part Cancel";
if (!orderOpen && filled) statusText = "Filled";
if (orderOpen && !partialFilled) statusText = "Open";
if (orderOpen && partialFilled) statusText = "Part Filled";

// prepare display values
std::string displayText = "Sell ";
if (divisibleForSale) { displayText += FormatDivisibleShortMP(amountForSale); } else { displayText += FormatIndivisibleMP(amountForSale); }
displayText += getTokenLabel(propertyIdForSale) + " for ";
if (divisibleDesired) { displayText += FormatDivisibleShortMP(amountDesired); } else { displayText += FormatIndivisibleMP(amountDesired); }
displayText += getTokenLabel(propertyIdDesired);
std::string displayIn = "";
std::string displayOut = "-";
if(divisibleDesired) { displayIn += FormatDivisibleShortMP(totalBought); } else { displayIn += FormatIndivisibleMP(totalBought); }
if(divisibleForSale) { displayOut += FormatDivisibleShortMP(totalSold); } else { displayOut += FormatIndivisibleMP(totalSold); }
if(totalBought == 0) displayIn = "0";
if(totalSold == 0) displayOut = "0";
displayIn += getTokenLabel(propertyIdDesired);
displayOut += getTokenLabel(propertyIdForSale);
QDateTime txTime;
txTime.setTime_t(pwtx->GetTxTime());
QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate);

// create a TradeHistoryObject and populate it
TradeHistoryObject objTH;
objTH.blockHeight = blockHeight;
objTH.blockByteOffset = 0;
CDiskTxPos position;
if (pblocktree->ReadTxIndex(hash, position)) {
objTH.blockByteOffset = position.nTxOffset;
}
objTH.valid = valid;
objTH.status = statusText;
objTH.amountIn = displayIn;
objTH.amountOut = displayOut;
objTH.info = displayText;

// add the new TradeHistoryObject to the map
tradeHistoryMap.insert(std::make_pair(hash, objTH));
nProcessed += 1;
}
// ### END WALLET TRANSACTIONS PROCESSING ###

return nProcessed;
}

void TradeHistoryDialog::Update()
{
//pending orders
Expand Down
20 changes: 19 additions & 1 deletion src/qt/tradehistorydialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,22 @@ namespace Ui {
class tradeHistoryDialog;
}

class TradeHistoryObject
{

public:
int blockHeight; // block transaction was mined in
int blockByteOffset; // byte offset the tx is stored in the block (used for ordering multiple txs same block)
bool valid; // whether the transaction is valid from an Omni perspective
std::string status; // string containing status of trade
std::string info; // string containing human readable description of trade
std::string amountOut; // string containing formatted amount out
std::string amountIn; // string containing formatted amount in

};

typedef std::map<uint256, TradeHistoryObject> TradeHistoryMap;

/** Dialog for looking up Master Protocol tokens */
class TradeHistoryDialog : public QDialog
{
Expand Down Expand Up @@ -54,6 +70,8 @@ class TradeHistoryDialog : public QDialog
GUIUtil::TableViewLastColumnResizingFixer *borrowedColumnResizingFixer;
virtual void resizeEvent(QResizeEvent* event);

TradeHistoryMap tradeHistoryMap;

public slots:
void Update();
void contextualMenu(const QPoint &);
Expand All @@ -66,7 +84,7 @@ public slots:
QMenu *contextMenu;

private slots:
//void buyRecalc();
int PopulateTradeHistoryMap();

signals:
// Fired when a message should be reported to the user
Expand Down

0 comments on commit aff7717

Please sign in to comment.