Merge #11683: tests: Remove unused mininode functions {ser,deser}_int_vector(......
[bitcoinplatinum.git] / src / qt / transactiondesc.cpp
blob3f245e6c33d68a1c9012c03e474a39dd894644a4
1 // Copyright (c) 2011-2016 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 #include <qt/transactiondesc.h>
7 #include <qt/bitcoinunits.h>
8 #include <qt/guiutil.h>
9 #include <qt/paymentserver.h>
10 #include <qt/transactionrecord.h>
12 #include <base58.h>
13 #include <consensus/consensus.h>
14 #include <validation.h>
15 #include <script/script.h>
16 #include <timedata.h>
17 #include <util.h>
18 #include <wallet/db.h>
19 #include <wallet/wallet.h>
21 #include <stdint.h>
22 #include <string>
24 QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
26 AssertLockHeld(cs_main);
27 if (!CheckFinalTx(*wtx.tx))
29 if (wtx.tx->nLockTime < LOCKTIME_THRESHOLD)
30 return tr("Open for %n more block(s)", "", wtx.tx->nLockTime - chainActive.Height());
31 else
32 return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.tx->nLockTime));
34 else
36 int nDepth = wtx.GetDepthInMainChain();
37 if (nDepth < 0)
38 return tr("conflicted with a transaction with %1 confirmations").arg(-nDepth);
39 else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
40 return tr("%1/offline").arg(nDepth);
41 else if (nDepth == 0)
42 return tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool"))) + (wtx.isAbandoned() ? ", "+tr("abandoned") : "");
43 else if (nDepth < 6)
44 return tr("%1/unconfirmed").arg(nDepth);
45 else
46 return tr("%1 confirmations").arg(nDepth);
50 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
52 QString strHTML;
54 LOCK2(cs_main, wallet->cs_wallet);
55 strHTML.reserve(4000);
56 strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
58 int64_t nTime = wtx.GetTxTime();
59 CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
60 CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
61 CAmount nNet = nCredit - nDebit;
63 strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx);
64 int nRequests = wtx.GetRequestCount();
65 if (nRequests != -1)
67 if (nRequests == 0)
68 strHTML += tr(", has not been successfully broadcast yet");
69 else if (nRequests > 0)
70 strHTML += tr(", broadcast through %n node(s)", "", nRequests);
72 strHTML += "<br>";
74 strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
77 // From
79 if (wtx.IsCoinBase())
81 strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";
83 else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
85 // Online transaction
86 strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
88 else
90 // Offline transaction
91 if (nNet > 0)
93 // Credit
94 CTxDestination address = DecodeDestination(rec->address);
95 if (IsValidDestination(address)) {
96 if (wallet->mapAddressBook.count(address))
98 strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
99 strHTML += "<b>" + tr("To") + ":</b> ";
100 strHTML += GUIUtil::HtmlEscape(rec->address);
101 QString addressOwned = (::IsMine(*wallet, address) == ISMINE_SPENDABLE) ? tr("own address") : tr("watch-only");
102 if (!wallet->mapAddressBook[address].name.empty())
103 strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")";
104 else
105 strHTML += " (" + addressOwned + ")";
106 strHTML += "<br>";
113 // To
115 if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
117 // Online transaction
118 std::string strAddress = wtx.mapValue["to"];
119 strHTML += "<b>" + tr("To") + ":</b> ";
120 CTxDestination dest = DecodeDestination(strAddress);
121 if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].name.empty())
122 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest].name) + " ";
123 strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
127 // Amount
129 if (wtx.IsCoinBase() && nCredit == 0)
132 // Coinbase
134 CAmount nUnmatured = 0;
135 for (const CTxOut& txout : wtx.tx->vout)
136 nUnmatured += wallet->GetCredit(txout, ISMINE_ALL);
137 strHTML += "<b>" + tr("Credit") + ":</b> ";
138 if (wtx.IsInMainChain())
139 strHTML += BitcoinUnits::formatHtmlWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
140 else
141 strHTML += "(" + tr("not accepted") + ")";
142 strHTML += "<br>";
144 else if (nNet > 0)
147 // Credit
149 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet) + "<br>";
151 else
153 isminetype fAllFromMe = ISMINE_SPENDABLE;
154 for (const CTxIn& txin : wtx.tx->vin)
156 isminetype mine = wallet->IsMine(txin);
157 if(fAllFromMe > mine) fAllFromMe = mine;
160 isminetype fAllToMe = ISMINE_SPENDABLE;
161 for (const CTxOut& txout : wtx.tx->vout)
163 isminetype mine = wallet->IsMine(txout);
164 if(fAllToMe > mine) fAllToMe = mine;
167 if (fAllFromMe)
169 if(fAllFromMe & ISMINE_WATCH_ONLY)
170 strHTML += "<b>" + tr("From") + ":</b> " + tr("watch-only") + "<br>";
173 // Debit
175 for (const CTxOut& txout : wtx.tx->vout)
177 // Ignore change
178 isminetype toSelf = wallet->IsMine(txout);
179 if ((toSelf == ISMINE_SPENDABLE) && (fAllFromMe == ISMINE_SPENDABLE))
180 continue;
182 if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
184 // Offline transaction
185 CTxDestination address;
186 if (ExtractDestination(txout.scriptPubKey, address))
188 strHTML += "<b>" + tr("To") + ":</b> ";
189 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
190 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
191 strHTML += GUIUtil::HtmlEscape(EncodeDestination(address));
192 if(toSelf == ISMINE_SPENDABLE)
193 strHTML += " (own address)";
194 else if(toSelf & ISMINE_WATCH_ONLY)
195 strHTML += " (watch-only)";
196 strHTML += "<br>";
200 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -txout.nValue) + "<br>";
201 if(toSelf)
202 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue) + "<br>";
205 if (fAllToMe)
207 // Payment to self
208 CAmount nChange = wtx.GetChange();
209 CAmount nValue = nCredit - nChange;
210 strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nValue) + "<br>";
211 strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nValue) + "<br>";
214 CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
215 if (nTxFee > 0)
216 strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nTxFee) + "<br>";
218 else
221 // Mixed debit transaction
223 for (const CTxIn& txin : wtx.tx->vin)
224 if (wallet->IsMine(txin))
225 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
226 for (const CTxOut& txout : wtx.tx->vout)
227 if (wallet->IsMine(txout))
228 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
232 strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet, true) + "<br>";
235 // Message
237 if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
238 strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
239 if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
240 strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
242 strHTML += "<b>" + tr("Transaction ID") + ":</b> " + rec->getTxID() + "<br>";
243 strHTML += "<b>" + tr("Transaction total size") + ":</b> " + QString::number(wtx.tx->GetTotalSize()) + " bytes<br>";
244 strHTML += "<b>" + tr("Output index") + ":</b> " + QString::number(rec->getOutputIndex()) + "<br>";
246 // Message from normal bitcoin:URI (bitcoin:123...?message=example)
247 for (const std::pair<std::string, std::string>& r : wtx.vOrderForm)
248 if (r.first == "Message")
249 strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>";
252 // PaymentRequest info:
254 for (const std::pair<std::string, std::string>& r : wtx.vOrderForm)
256 if (r.first == "PaymentRequest")
258 PaymentRequestPlus req;
259 req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
260 QString merchant;
261 if (req.getMerchant(PaymentServer::getCertStore(), merchant))
262 strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
266 if (wtx.IsCoinBase())
268 quint32 numBlocksToMaturity = COINBASE_MATURITY + 1;
269 strHTML += "<br>" + tr("Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.").arg(QString::number(numBlocksToMaturity)) + "<br>";
273 // Debug view
275 if (logCategories != BCLog::NONE)
277 strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
278 for (const CTxIn& txin : wtx.tx->vin)
279 if(wallet->IsMine(txin))
280 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
281 for (const CTxOut& txout : wtx.tx->vout)
282 if(wallet->IsMine(txout))
283 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
285 strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
286 strHTML += GUIUtil::HtmlEscape(wtx.tx->ToString(), true);
288 strHTML += "<br><b>" + tr("Inputs") + ":</b>";
289 strHTML += "<ul>";
291 for (const CTxIn& txin : wtx.tx->vin)
293 COutPoint prevout = txin.prevout;
295 Coin prev;
296 if(pcoinsTip->GetCoin(prevout, prev))
299 strHTML += "<li>";
300 const CTxOut &vout = prev.out;
301 CTxDestination address;
302 if (ExtractDestination(vout.scriptPubKey, address))
304 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
305 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
306 strHTML += QString::fromStdString(EncodeDestination(address));
308 strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, vout.nValue);
309 strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "</li>";
310 strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + "</li>";
315 strHTML += "</ul>";
318 strHTML += "</font></html>";
319 return strHTML;