[gitian] Use vm-builder_0.12.4+bzr494 on Debian
[bitcoinplatinum.git] / src / qt / transactiondesc.cpp
blob801c6c62d2b609e2be86fb28f85ae271685893a4
1 // Copyright (c) 2011-2014 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 "transactiondesc.h"
7 #include "bitcoinunits.h"
8 #include "guiutil.h"
9 #include "paymentserver.h"
10 #include "transactionrecord.h"
12 #include "base58.h"
13 #include "consensus/consensus.h"
14 #include "main.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))
29 if (wtx.nLockTime < LOCKTIME_THRESHOLD)
30 return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height());
31 else
32 return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
34 else
36 int nDepth = wtx.GetDepthInMainChain();
37 if (nDepth < 0)
38 return tr("conflicted");
39 else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
40 return tr("%1/offline").arg(nDepth);
41 else if (nDepth < 6)
42 return tr("%1/unconfirmed").arg(nDepth);
43 else
44 return tr("%1 confirmations").arg(nDepth);
48 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionRecord *rec, int unit)
50 QString strHTML;
52 LOCK2(cs_main, wallet->cs_wallet);
53 strHTML.reserve(4000);
54 strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
56 int64_t nTime = wtx.GetTxTime();
57 CAmount nCredit = wtx.GetCredit(ISMINE_ALL);
58 CAmount nDebit = wtx.GetDebit(ISMINE_ALL);
59 CAmount nNet = nCredit - nDebit;
61 strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx);
62 int nRequests = wtx.GetRequestCount();
63 if (nRequests != -1)
65 if (nRequests == 0)
66 strHTML += tr(", has not been successfully broadcast yet");
67 else if (nRequests > 0)
68 strHTML += tr(", broadcast through %n node(s)", "", nRequests);
70 strHTML += "<br>";
72 strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
75 // From
77 if (wtx.IsCoinBase())
79 strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";
81 else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
83 // Online transaction
84 strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
86 else
88 // Offline transaction
89 if (nNet > 0)
91 // Credit
92 if (CBitcoinAddress(rec->address).IsValid())
94 CTxDestination address = CBitcoinAddress(rec->address).Get();
95 if (wallet->mapAddressBook.count(address))
97 strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
98 strHTML += "<b>" + tr("To") + ":</b> ";
99 strHTML += GUIUtil::HtmlEscape(rec->address);
100 QString addressOwned = (::IsMine(*wallet, address) == ISMINE_SPENDABLE) ? tr("own address") : tr("watch-only");
101 if (!wallet->mapAddressBook[address].name.empty())
102 strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")";
103 else
104 strHTML += " (" + addressOwned + ")";
105 strHTML += "<br>";
112 // To
114 if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
116 // Online transaction
117 std::string strAddress = wtx.mapValue["to"];
118 strHTML += "<b>" + tr("To") + ":</b> ";
119 CTxDestination dest = CBitcoinAddress(strAddress).Get();
120 if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].name.empty())
121 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest].name) + " ";
122 strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
126 // Amount
128 if (wtx.IsCoinBase() && nCredit == 0)
131 // Coinbase
133 CAmount nUnmatured = 0;
134 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
135 nUnmatured += wallet->GetCredit(txout, ISMINE_ALL);
136 strHTML += "<b>" + tr("Credit") + ":</b> ";
137 if (wtx.IsInMainChain())
138 strHTML += BitcoinUnits::formatHtmlWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
139 else
140 strHTML += "(" + tr("not accepted") + ")";
141 strHTML += "<br>";
143 else if (nNet > 0)
146 // Credit
148 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet) + "<br>";
150 else
152 isminetype fAllFromMe = ISMINE_SPENDABLE;
153 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
155 isminetype mine = wallet->IsMine(txin);
156 if(fAllFromMe > mine) fAllFromMe = mine;
159 isminetype fAllToMe = ISMINE_SPENDABLE;
160 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
162 isminetype mine = wallet->IsMine(txout);
163 if(fAllToMe > mine) fAllToMe = mine;
166 if (fAllFromMe)
168 if(fAllFromMe & ISMINE_WATCH_ONLY)
169 strHTML += "<b>" + tr("From") + ":</b> " + tr("watch-only") + "<br>";
172 // Debit
174 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
176 // Ignore change
177 isminetype toSelf = wallet->IsMine(txout);
178 if ((toSelf == ISMINE_SPENDABLE) && (fAllFromMe == ISMINE_SPENDABLE))
179 continue;
181 if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
183 // Offline transaction
184 CTxDestination address;
185 if (ExtractDestination(txout.scriptPubKey, address))
187 strHTML += "<b>" + tr("To") + ":</b> ";
188 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
189 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
190 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
191 if(toSelf == ISMINE_SPENDABLE)
192 strHTML += " (own address)";
193 else if(toSelf & ISMINE_WATCH_ONLY)
194 strHTML += " (watch-only)";
195 strHTML += "<br>";
199 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -txout.nValue) + "<br>";
200 if(toSelf)
201 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue) + "<br>";
204 if (fAllToMe)
206 // Payment to self
207 CAmount nChange = wtx.GetChange();
208 CAmount nValue = nCredit - nChange;
209 strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nValue) + "<br>";
210 strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nValue) + "<br>";
213 CAmount nTxFee = nDebit - wtx.GetValueOut();
214 if (nTxFee > 0)
215 strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nTxFee) + "<br>";
217 else
220 // Mixed debit transaction
222 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
223 if (wallet->IsMine(txin))
224 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
225 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
226 if (wallet->IsMine(txout))
227 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
231 strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet, true) + "<br>";
234 // Message
236 if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
237 strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
238 if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
239 strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
241 strHTML += "<b>" + tr("Transaction ID") + ":</b> " + TransactionRecord::formatSubTxId(wtx.GetHash(), rec->idx) + "<br>";
243 // Message from normal bitcoin:URI (bitcoin:123...?message=example)
244 Q_FOREACH (const PAIRTYPE(std::string, std::string)& r, wtx.vOrderForm)
245 if (r.first == "Message")
246 strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>";
249 // PaymentRequest info:
251 Q_FOREACH (const PAIRTYPE(std::string, std::string)& r, wtx.vOrderForm)
253 if (r.first == "PaymentRequest")
255 PaymentRequestPlus req;
256 req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
257 QString merchant;
258 if (req.getMerchant(PaymentServer::getCertStore(), merchant))
259 strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
263 if (wtx.IsCoinBase())
265 quint32 numBlocksToMaturity = COINBASE_MATURITY + 1;
266 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>";
270 // Debug view
272 if (fDebug)
274 strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
275 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
276 if(wallet->IsMine(txin))
277 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
278 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
279 if(wallet->IsMine(txout))
280 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
282 strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
283 strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
285 strHTML += "<br><b>" + tr("Inputs") + ":</b>";
286 strHTML += "<ul>";
288 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
290 COutPoint prevout = txin.prevout;
292 CCoins prev;
293 if(pcoinsTip->GetCoins(prevout.hash, prev))
295 if (prevout.n < prev.vout.size())
297 strHTML += "<li>";
298 const CTxOut &vout = prev.vout[prevout.n];
299 CTxDestination address;
300 if (ExtractDestination(vout.scriptPubKey, address))
302 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
303 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
304 strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
306 strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, vout.nValue);
307 strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "</li>";
308 strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + "</li>";
313 strHTML += "</ul>";
316 strHTML += "</font></html>";
317 return strHTML;