add label to sender address
[novacoin.git] / src / qt / transactiondesc.cpp
1 #include "transactiondesc.h"
2
3 #include "guiutil.h"
4 #include "bitcoinunits.h"
5
6 #include "main.h"
7 #include "wallet.h"
8 #include "txdb.h"
9 #include "ui_interface.h"
10 #include "base58.h"
11
12 QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
13 {
14     if (!wtx.IsFinal())
15     {
16         if (wtx.nLockTime < LOCKTIME_THRESHOLD)
17             return tr("Open for %n block(s)", "", nBestHeight - wtx.nLockTime);
18         else
19             return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
20     }
21     else
22     {
23         int nDepth = wtx.GetDepthInMainChain();
24         if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
25             return tr("%1/offline").arg(nDepth);
26         else if (nDepth < 6)
27             return tr("%1/unconfirmed").arg(nDepth);
28         else
29             return tr("%1 confirmations").arg(nDepth);
30     }
31 }
32
33 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
34 {
35     QString strHTML;
36
37     {
38         LOCK(wallet->cs_wallet);
39         strHTML.reserve(4000);
40         strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
41
42         int64 nTime = wtx.GetTxTime();
43         int64 nCredit = wtx.GetCredit(MINE_ALL);
44         int64 nDebit = wtx.GetDebit(MINE_ALL);
45         int64 nNet = nCredit - nDebit;
46
47         strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx);
48         int nRequests = wtx.GetRequestCount();
49         if (nRequests != -1)
50         {
51             if (nRequests == 0)
52                 strHTML += tr(", has not been successfully broadcast yet");
53             else if (nRequests > 0)
54                 strHTML += tr(", broadcast through %n node(s)", "", nRequests);
55         }
56         strHTML += "<br>";
57
58         strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
59
60         //
61         // From
62         //
63         if (wtx.IsCoinBase() || wtx.IsCoinStake())
64         {
65             strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";
66         }
67         else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
68         {
69             // Online transaction
70             strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
71         }
72         else
73         {
74             // Offline transaction
75             if (nNet > 0)
76             {
77                 // Credit
78                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
79                 {
80                     if (wallet->IsMine(txout))
81                     {
82                         CTxDestination address;
83                         if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
84                         {
85                             if (wallet->mapAddressBook.count(address))
86                             {
87                                 for (unsigned int i = 0; i < wtx.vin.size(); i++)
88                                 {
89                                     uint256 hash;
90                                     const CTxIn& vin = wtx.vin[i];
91                                     hash.SetHex(vin.prevout.hash.ToString());
92                                     CTransaction wtxPrev;
93                                     uint256 hashBlock = 0;
94                                     if (!GetTransaction(hash, wtxPrev, hashBlock))
95                                     {
96                                         strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
97                                         continue; 
98                                     }
99                                     CTxDestination senderAddress;
100                                     if (!ExtractDestination(wtxPrev.vout[vin.prevout.n].scriptPubKey, senderAddress) )
101                                     {
102                                         strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
103                                     }
104                                     else
105                                     {
106                                         strHTML += "<b>" + tr("From") + ":</b> ";
107                                         strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(senderAddress).ToString());
108                                         if(wallet->mapAddressBook.find(senderAddress) !=  wallet->mapAddressBook.end())
109                                             if (!wallet->mapAddressBook[senderAddress].empty())
110                                             {
111                                                 strHTML += " (" + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[senderAddress]) + ")";
112                                             }
113                                         strHTML += "<br>";
114                                     }
115                                 }
116                                 strHTML += "<b>" + tr("To") + ":</b> ";
117                                 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
118                                 if (!wallet->mapAddressBook[address].empty())
119                                     strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")";
120                                 else
121                                     strHTML += " (" + tr("own address") + ")";
122                                 strHTML += "<br>";
123                             }
124                         }
125                         break;
126                     }
127                 }
128             }
129         }
130
131         //
132         // To
133         //
134         if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
135         {
136             // Online transaction
137             std::string strAddress = wtx.mapValue["to"];
138             strHTML += "<b>" + tr("To") + ":</b> ";
139             CTxDestination dest = CBitcoinAddress(strAddress).Get();
140             if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty())
141                 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " ";
142             strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
143         }
144
145         //
146         // Amount
147         //
148         if (wtx.IsCoinBase() && nCredit == 0)
149         {
150             //
151             // Coinbase
152             //
153             int64 nUnmatured = 0;
154             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
155                 nUnmatured += wallet->GetCredit(txout, MINE_ALL);
156             strHTML += "<b>" + tr("Credit") + ":</b> ";
157             if (wtx.IsInMainChain())
158                 strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
159             else
160                 strHTML += "(" + tr("not accepted") + ")";
161             strHTML += "<br>";
162         }
163         else if (nNet > 0)
164         {
165             //
166             // Credit
167             //
168             strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>";
169         }
170         else
171         {
172             bool fAllFromMe = true;
173             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
174                 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
175
176             bool fAllToMe = true;
177             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
178                 fAllToMe = fAllToMe && wallet->IsMine(txout);
179
180             if (fAllFromMe)
181             {
182                 //
183                 // Debit
184                 //
185                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
186                 {
187                     if (wallet->IsMine(txout))
188                         continue;
189
190                     if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
191                     {
192                         // Offline transaction
193                         CTxDestination address;
194                         if (ExtractDestination(txout.scriptPubKey, address))
195                         {
196                             strHTML += "<b>" + tr("To") + ":</b> ";
197                             if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
198                                 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
199                             strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
200                             strHTML += "<br>";
201                         }
202                     }
203
204                     strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>";
205                 }
206
207                 if (fAllToMe)
208                 {
209                     // Payment to self
210                     int64 nChange = wtx.GetChange();
211                     int64 nValue = nCredit - nChange;
212                     strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "<br>";
213                     strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>";
214                 }
215
216                 int64 nTxFee = nDebit - wtx.GetValueOut();
217                 if (nTxFee > 0)
218                     strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nTxFee) + "<br>";
219             }
220             else
221             {
222                 //
223                 // Mixed debit transaction
224                 //
225                 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
226                     if (wallet->IsMine(txin))
227                         strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin, MINE_ALL)) + "<br>";
228                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
229                     if (wallet->IsMine(txout))
230                         strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, MINE_ALL)) + "<br>";
231             }
232         }
233
234         strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet, true) + "<br>";
235
236         //
237         // Message
238         //
239         if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
240             strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
241         if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
242             strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
243
244         strHTML += "<b>" + tr("Transaction ID") + ":</b> " + wtx.GetHash().ToString().c_str() + "<br>";
245
246         if (wtx.IsCoinBase() || wtx.IsCoinStake())
247             strHTML += "<br>" + tr("Generated coins must mature 520 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.") + "<br>";
248
249         //
250         // Debug view
251         //
252         if (fDebug)
253         {
254             strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
255             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
256                 if(wallet->IsMine(txin))
257                     strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin, MINE_ALL)) + "<br>";
258             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
259                 if(wallet->IsMine(txout))
260                     strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, MINE_ALL)) + "<br>";
261
262             strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
263             strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
264
265             CTxDB txdb("r"); // To fetch source txouts
266
267             strHTML += "<br><b>" + tr("Inputs") + ":</b>";
268             strHTML += "<ul>";
269
270             {
271                 LOCK(wallet->cs_wallet);
272                 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
273                 {
274                     COutPoint prevout = txin.prevout;
275
276                     CTransaction prev;
277                     if(txdb.ReadDiskTx(prevout.hash, prev))
278                     {
279                         if (prevout.n < prev.vout.size())
280                         {
281                             strHTML += "<li>";
282                             const CTxOut &vout = prev.vout[prevout.n];
283                             CTxDestination address;
284                             if (ExtractDestination(vout.scriptPubKey, address))
285                             {
286                                 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
287                                     strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
288                                 strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
289                             }
290                             strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, vout.nValue);
291                             strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "</li>";
292                         }
293                     }
294                 }
295             }
296
297             strHTML += "</ul>";
298         }
299
300         strHTML += "</font></html>";
301     }
302     return strHTML;
303 }