remove commented code, use // for one-line comments and comments inside functions
[novacoin.git] / src / qt / transactiondesc.cpp
1 #include <transactiondesc.h>
2
3 #include "guiutil.h"
4 #include "main.h"
5 #include "externui.h"
6
7 #include <QString>
8
9 // Taken straight from ui.cpp
10 // TODO: Convert to use QStrings, Qt::Escape and tr()
11 //   or: refactor and put describeAsHTML() into bitcoin core but that is unneccesary with better
12 //       UI<->core API, no need to put display logic in core.
13
14 using namespace std;
15
16 static string HtmlEscape(const char* psz, bool fMultiLine=false)
17 {
18     int len = 0;
19     for (const char* p = psz; *p; p++)
20     {
21              if (*p == '<') len += 4;
22         else if (*p == '>') len += 4;
23         else if (*p == '&') len += 5;
24         else if (*p == '"') len += 6;
25         else if (*p == ' ' && p > psz && p[-1] == ' ' && p[1] == ' ') len += 6;
26         else if (*p == '\n' && fMultiLine) len += 5;
27         else
28             len++;
29     }
30     string str;
31     str.reserve(len);
32     for (const char* p = psz; *p; p++)
33     {
34              if (*p == '<') str += "&lt;";
35         else if (*p == '>') str += "&gt;";
36         else if (*p == '&') str += "&amp;";
37         else if (*p == '"') str += "&quot;";
38         else if (*p == ' ' && p > psz && p[-1] == ' ' && p[1] == ' ') str += "&nbsp;";
39         else if (*p == '\n' && fMultiLine) str += "<br>\n";
40         else
41             str += *p;
42     }
43     return str;
44 }
45
46 static string HtmlEscape(const string& str, bool fMultiLine=false)
47 {
48     return HtmlEscape(str.c_str(), fMultiLine);
49 }
50
51 static string FormatTxStatus(const CWalletTx& wtx)
52 {
53     // Status
54     if (!wtx.IsFinal())
55     {
56         if (wtx.nLockTime < 500000000)
57             return strprintf(_("Open for %d blocks"), nBestHeight - wtx.nLockTime);
58         else
59             return strprintf(_("Open until %s"), GUIUtil::DateTimeStr(wtx.nLockTime).toStdString().c_str());
60     }
61     else
62     {
63         int nDepth = wtx.GetDepthInMainChain();
64         if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
65             return strprintf(_("%d/offline?"), nDepth);
66         else if (nDepth < 6)
67             return strprintf(_("%d/unconfirmed"), nDepth);
68         else
69             return strprintf(_("%d confirmations"), nDepth);
70     }
71 }
72
73 string TransactionDesc::toHTML(CWalletTx &wtx)
74 {
75     string strHTML;
76     CRITICAL_BLOCK(cs_mapAddressBook)
77     {
78         strHTML.reserve(4000);
79         strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
80
81         int64 nTime = wtx.GetTxTime();
82         int64 nCredit = wtx.GetCredit();
83         int64 nDebit = wtx.GetDebit();
84         int64 nNet = nCredit - nDebit;
85
86
87
88         strHTML += _("<b>Status:</b> ") + FormatTxStatus(wtx);
89         int nRequests = wtx.GetRequestCount();
90         if (nRequests != -1)
91         {
92             if (nRequests == 0)
93                 strHTML += _(", has not been successfully broadcast yet");
94             else if (nRequests == 1)
95                 strHTML += strprintf(_(", broadcast through %d node"), nRequests);
96             else
97                 strHTML += strprintf(_(", broadcast through %d nodes"), nRequests);
98         }
99         strHTML += "<br>";
100
101         strHTML += _("<b>Date:</b> ") + (nTime ? GUIUtil::DateTimeStr(nTime).toStdString() : "") + "<br>";
102
103
104         //
105         // From
106         //
107         if (wtx.IsCoinBase())
108         {
109             strHTML += _("<b>Source:</b> Generated<br>");
110         }
111         else if (!wtx.mapValue["from"].empty())
112         {
113             // Online transaction
114             if (!wtx.mapValue["from"].empty())
115                 strHTML += _("<b>From:</b> ") + HtmlEscape(wtx.mapValue["from"]) + "<br>";
116         }
117         else
118         {
119             // Offline transaction
120             if (nNet > 0)
121             {
122                 // Credit
123                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
124                 {
125                     if (txout.IsMine())
126                     {
127                         vector<unsigned char> vchPubKey;
128                         if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
129                         {
130                             string strAddress = PubKeyToAddress(vchPubKey);
131                             if (mapAddressBook.count(strAddress))
132                             {
133                                 strHTML += string() + _("<b>From:</b> ") + _("unknown") + "<br>";
134                                 strHTML += _("<b>To:</b> ");
135                                 strHTML += HtmlEscape(strAddress);
136                                 if (!mapAddressBook[strAddress].empty())
137                                     strHTML += _(" (yours, label: ") + mapAddressBook[strAddress] + ")";
138                                 else
139                                     strHTML += _(" (yours)");
140                                 strHTML += "<br>";
141                             }
142                         }
143                         break;
144                     }
145                 }
146             }
147         }
148
149
150         //
151         // To
152         //
153         string strAddress;
154         if (!wtx.mapValue["to"].empty())
155         {
156             // Online transaction
157             strAddress = wtx.mapValue["to"];
158             strHTML += _("<b>To:</b> ");
159             if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
160                 strHTML += mapAddressBook[strAddress] + " ";
161             strHTML += HtmlEscape(strAddress) + "<br>";
162         }
163
164
165         //
166         // Amount
167         //
168         if (wtx.IsCoinBase() && nCredit == 0)
169         {
170             //
171             // Coinbase
172             //
173             int64 nUnmatured = 0;
174             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
175                 nUnmatured += txout.GetCredit();
176             strHTML += _("<b>Credit:</b> ");
177             if (wtx.IsInMainChain())
178                 strHTML += strprintf(_("(%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
179             else
180                 strHTML += _("(not accepted)");
181             strHTML += "<br>";
182         }
183         else if (nNet > 0)
184         {
185             //
186             // Credit
187             //
188             strHTML += _("<b>Credit:</b> ") + FormatMoney(nNet) + "<br>";
189         }
190         else
191         {
192             bool fAllFromMe = true;
193             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
194                 fAllFromMe = fAllFromMe && txin.IsMine();
195
196             bool fAllToMe = true;
197             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
198                 fAllToMe = fAllToMe && txout.IsMine();
199
200             if (fAllFromMe)
201             {
202                 //
203                 // Debit
204                 //
205                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
206                 {
207                     if (txout.IsMine())
208                         continue;
209
210                     if (wtx.mapValue["to"].empty())
211                     {
212                         // Offline transaction
213                         uint160 hash160;
214                         if (ExtractHash160(txout.scriptPubKey, hash160))
215                         {
216                             string strAddress = Hash160ToAddress(hash160);
217                             strHTML += _("<b>To:</b> ");
218                             if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
219                                 strHTML += mapAddressBook[strAddress] + " ";
220                             strHTML += strAddress;
221                             strHTML += "<br>";
222                         }
223                     }
224
225                     strHTML += _("<b>Debit:</b> ") + FormatMoney(-txout.nValue) + "<br>";
226                 }
227
228                 if (fAllToMe)
229                 {
230                     // Payment to self
231                     int64 nChange = wtx.GetChange();
232                     int64 nValue = nCredit - nChange;
233                     strHTML += _("<b>Debit:</b> ") + FormatMoney(-nValue) + "<br>";
234                     strHTML += _("<b>Credit:</b> ") + FormatMoney(nValue) + "<br>";
235                 }
236
237                 int64 nTxFee = nDebit - wtx.GetValueOut();
238                 if (nTxFee > 0)
239                     strHTML += _("<b>Transaction fee:</b> ") + FormatMoney(-nTxFee) + "<br>";
240             }
241             else
242             {
243                 //
244                 // Mixed debit transaction
245                 //
246                 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
247                     if (txin.IsMine())
248                         strHTML += _("<b>Debit:</b> ") + FormatMoney(-txin.GetDebit()) + "<br>";
249                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
250                     if (txout.IsMine())
251                         strHTML += _("<b>Credit:</b> ") + FormatMoney(txout.GetCredit()) + "<br>";
252             }
253         }
254
255         strHTML += _("<b>Net amount:</b> ") + FormatMoney(nNet, true) + "<br>";
256
257
258         //
259         // Message
260         //
261         if (!wtx.mapValue["message"].empty())
262             strHTML += string() + "<br><b>" + _("Message:") + "</b><br>" + HtmlEscape(wtx.mapValue["message"], true) + "<br>";
263         if (!wtx.mapValue["comment"].empty())
264             strHTML += string() + "<br><b>" + _("Comment:") + "</b><br>" + HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
265
266         if (wtx.IsCoinBase())
267             strHTML += string() + "<br>" + _("Generated coins must wait 120 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, it will change to \"not accepted\" and not be spendable.  This may occasionally happen if another node generates a block within a few seconds of yours.") + "<br>";
268
269
270         //
271         // Debug view
272         //
273         if (fDebug)
274         {
275             strHTML += "<hr><br>debug print<br><br>";
276             BOOST_FOREACH(const CTxIn& txin, wtx.vin)
277                 if (txin.IsMine())
278                     strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
279             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
280                 if (txout.IsMine())
281                     strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
282
283             strHTML += "<br><b>Transaction:</b><br>";
284             strHTML += HtmlEscape(wtx.ToString(), true);
285
286             strHTML += "<br><b>Inputs:</b><br>";
287             CRITICAL_BLOCK(cs_mapWallet)
288             {
289                 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
290                 {
291                     COutPoint prevout = txin.prevout;
292                     map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
293                     if (mi != mapWallet.end())
294                     {
295                         const CWalletTx& prev = (*mi).second;
296                         if (prevout.n < prev.vout.size())
297                         {
298                             strHTML += HtmlEscape(prev.ToString(), true);
299                             strHTML += " &nbsp;&nbsp; " + FormatTxStatus(prev) + ", ";
300                             strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "<br>";
301                         }
302                     }
303                 }
304             }
305         }
306
307
308
309         strHTML += "</font></html>";
310     }
311     return strHTML;
312 }