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