1 #include <transactiondesc.h>
9 /* Taken straight from ui.cpp
10 TODO: Convert to use QStrings, Qt::Escape and tr()
15 static string HtmlEscape(const char* psz, bool fMultiLine=false)
18 for (const char* p = psz; *p; p++)
20 if (*p == '<') len += 4;
21 else if (*p == '>') len += 4;
22 else if (*p == '&') len += 5;
23 else if (*p == '"') len += 6;
24 else if (*p == ' ' && p > psz && p[-1] == ' ' && p[1] == ' ') len += 6;
25 else if (*p == '\n' && fMultiLine) len += 5;
31 for (const char* p = psz; *p; p++)
33 if (*p == '<') str += "<";
34 else if (*p == '>') str += ">";
35 else if (*p == '&') str += "&";
36 else if (*p == '"') str += """;
37 else if (*p == ' ' && p > psz && p[-1] == ' ' && p[1] == ' ') str += " ";
38 else if (*p == '\n' && fMultiLine) str += "<br>\n";
45 static string HtmlEscape(const string& str, bool fMultiLine=false)
47 return HtmlEscape(str.c_str(), fMultiLine);
50 static string FormatTxStatus(const CWalletTx& wtx)
55 if (wtx.nLockTime < 500000000)
56 return strprintf(_("Open for %d blocks"), nBestHeight - wtx.nLockTime);
58 return strprintf(_("Open until %s"), GUIUtil::DateTimeStr(wtx.nLockTime).toStdString().c_str());
62 int nDepth = wtx.GetDepthInMainChain();
63 if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
64 return strprintf(_("%d/offline?"), nDepth);
66 return strprintf(_("%d/unconfirmed"), nDepth);
68 return strprintf(_("%d confirmations"), nDepth);
72 string TransactionDesc::toHTML(CWalletTx &wtx)
75 CRITICAL_BLOCK(cs_mapAddressBook)
77 strHTML.reserve(4000);
78 strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
80 int64 nTime = wtx.GetTxTime();
81 int64 nCredit = wtx.GetCredit();
82 int64 nDebit = wtx.GetDebit();
83 int64 nNet = nCredit - nDebit;
87 strHTML += _("<b>Status:</b> ") + FormatTxStatus(wtx);
88 int nRequests = wtx.GetRequestCount();
92 strHTML += _(", has not been successfully broadcast yet");
93 else if (nRequests == 1)
94 strHTML += strprintf(_(", broadcast through %d node"), nRequests);
96 strHTML += strprintf(_(", broadcast through %d nodes"), nRequests);
100 strHTML += _("<b>Date:</b> ") + (nTime ? GUIUtil::DateTimeStr(nTime).toStdString() : "") + "<br>";
106 if (wtx.IsCoinBase())
108 strHTML += _("<b>Source:</b> Generated<br>");
110 else if (!wtx.mapValue["from"].empty())
112 // Online transaction
113 if (!wtx.mapValue["from"].empty())
114 strHTML += _("<b>From:</b> ") + HtmlEscape(wtx.mapValue["from"]) + "<br>";
118 // Offline transaction
122 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
126 vector<unsigned char> vchPubKey;
127 if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
129 string strAddress = PubKeyToAddress(vchPubKey);
130 if (mapAddressBook.count(strAddress))
132 strHTML += string() + _("<b>From:</b> ") + _("unknown") + "<br>";
133 strHTML += _("<b>To:</b> ");
134 strHTML += HtmlEscape(strAddress);
135 if (!mapAddressBook[strAddress].empty())
136 strHTML += _(" (yours, label: ") + mapAddressBook[strAddress] + ")";
138 strHTML += _(" (yours)");
153 if (!wtx.mapValue["to"].empty())
155 // Online transaction
156 strAddress = wtx.mapValue["to"];
157 strHTML += _("<b>To:</b> ");
158 if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
159 strHTML += mapAddressBook[strAddress] + " ";
160 strHTML += HtmlEscape(strAddress) + "<br>";
167 if (wtx.IsCoinBase() && nCredit == 0)
172 int64 nUnmatured = 0;
173 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
174 nUnmatured += txout.GetCredit();
175 strHTML += _("<b>Credit:</b> ");
176 if (wtx.IsInMainChain())
177 strHTML += strprintf(_("(%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
179 strHTML += _("(not accepted)");
187 strHTML += _("<b>Credit:</b> ") + FormatMoney(nNet) + "<br>";
191 bool fAllFromMe = true;
192 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
193 fAllFromMe = fAllFromMe && txin.IsMine();
195 bool fAllToMe = true;
196 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
197 fAllToMe = fAllToMe && txout.IsMine();
204 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
209 if (wtx.mapValue["to"].empty())
211 // Offline transaction
213 if (ExtractHash160(txout.scriptPubKey, hash160))
215 string strAddress = Hash160ToAddress(hash160);
216 strHTML += _("<b>To:</b> ");
217 if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
218 strHTML += mapAddressBook[strAddress] + " ";
219 strHTML += strAddress;
224 strHTML += _("<b>Debit:</b> ") + FormatMoney(-txout.nValue) + "<br>";
230 int64 nChange = wtx.GetChange();
231 int64 nValue = nCredit - nChange;
232 strHTML += _("<b>Debit:</b> ") + FormatMoney(-nValue) + "<br>";
233 strHTML += _("<b>Credit:</b> ") + FormatMoney(nValue) + "<br>";
236 int64 nTxFee = nDebit - wtx.GetValueOut();
238 strHTML += _("<b>Transaction fee:</b> ") + FormatMoney(-nTxFee) + "<br>";
243 // Mixed debit transaction
245 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
247 strHTML += _("<b>Debit:</b> ") + FormatMoney(-txin.GetDebit()) + "<br>";
248 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
250 strHTML += _("<b>Credit:</b> ") + FormatMoney(txout.GetCredit()) + "<br>";
254 strHTML += _("<b>Net amount:</b> ") + FormatMoney(nNet, true) + "<br>";
260 if (!wtx.mapValue["message"].empty())
261 strHTML += string() + "<br><b>" + _("Message:") + "</b><br>" + HtmlEscape(wtx.mapValue["message"], true) + "<br>";
262 if (!wtx.mapValue["comment"].empty())
263 strHTML += string() + "<br><b>" + _("Comment:") + "</b><br>" + HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
265 if (wtx.IsCoinBase())
266 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>";
274 strHTML += "<hr><br>debug print<br><br>";
275 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
277 strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
278 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
280 strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
282 strHTML += "<br><b>Transaction:</b><br>";
283 strHTML += HtmlEscape(wtx.ToString(), true);
285 strHTML += "<br><b>Inputs:</b><br>";
286 CRITICAL_BLOCK(cs_mapWallet)
288 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
290 COutPoint prevout = txin.prevout;
291 map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
292 if (mi != mapWallet.end())
294 const CWalletTx& prev = (*mi).second;
295 if (prevout.n < prev.vout.size())
297 strHTML += HtmlEscape(prev.ToString(), true);
298 strHTML += " " + FormatTxStatus(prev) + ", ";
299 strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "<br>";
308 strHTML += "</font></html>";