1 #include <transactiondesc.h>
8 /* Taken straight from ui.cpp
9 TODO: Convert to use QStrings, Qt::Escape and tr()
14 static string HtmlEscape(const char* psz, bool fMultiLine=false)
17 for (const char* p = psz; *p; p++)
19 if (*p == '<') len += 4;
20 else if (*p == '>') len += 4;
21 else if (*p == '&') len += 5;
22 else if (*p == '"') len += 6;
23 else if (*p == ' ' && p > psz && p[-1] == ' ' && p[1] == ' ') len += 6;
24 else if (*p == '\n' && fMultiLine) len += 5;
30 for (const char* p = psz; *p; p++)
32 if (*p == '<') str += "<";
33 else if (*p == '>') str += ">";
34 else if (*p == '&') str += "&";
35 else if (*p == '"') str += """;
36 else if (*p == ' ' && p > psz && p[-1] == ' ' && p[1] == ' ') str += " ";
37 else if (*p == '\n' && fMultiLine) str += "<br>\n";
44 static string HtmlEscape(const string& str, bool fMultiLine=false)
46 return HtmlEscape(str.c_str(), fMultiLine);
49 static string FormatTxStatus(const CWalletTx& wtx)
54 if (wtx.nLockTime < 500000000)
55 return strprintf(_("Open for %d blocks"), nBestHeight - wtx.nLockTime);
57 return strprintf(_("Open until %s"), GUIUtil::DateTimeStr(wtx.nLockTime).toStdString().c_str());
61 int nDepth = wtx.GetDepthInMainChain();
62 if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
63 return strprintf(_("%d/offline?"), nDepth);
65 return strprintf(_("%d/unconfirmed"), nDepth);
67 return strprintf(_("%d confirmations"), nDepth);
71 string TransactionDesc::toHTML(CWalletTx &wtx)
74 CRITICAL_BLOCK(cs_mapAddressBook)
76 strHTML.reserve(4000);
77 strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
79 int64 nTime = wtx.GetTxTime();
80 int64 nCredit = wtx.GetCredit();
81 int64 nDebit = wtx.GetDebit();
82 int64 nNet = nCredit - nDebit;
86 strHTML += _("<b>Status:</b> ") + FormatTxStatus(wtx);
87 int nRequests = wtx.GetRequestCount();
91 strHTML += _(", has not been successfully broadcast yet");
92 else if (nRequests == 1)
93 strHTML += strprintf(_(", broadcast through %d node"), nRequests);
95 strHTML += strprintf(_(", broadcast through %d nodes"), nRequests);
99 strHTML += _("<b>Date:</b> ") + (nTime ? GUIUtil::DateTimeStr(nTime).toStdString() : "") + "<br>";
105 if (wtx.IsCoinBase())
107 strHTML += _("<b>Source:</b> Generated<br>");
109 else if (!wtx.mapValue["from"].empty())
111 // Online transaction
112 if (!wtx.mapValue["from"].empty())
113 strHTML += _("<b>From:</b> ") + HtmlEscape(wtx.mapValue["from"]) + "<br>";
117 // Offline transaction
121 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
125 vector<unsigned char> vchPubKey;
126 if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
128 string strAddress = PubKeyToAddress(vchPubKey);
129 if (mapAddressBook.count(strAddress))
131 strHTML += string() + _("<b>From:</b> ") + _("unknown") + "<br>";
132 strHTML += _("<b>To:</b> ");
133 strHTML += HtmlEscape(strAddress);
134 if (!mapAddressBook[strAddress].empty())
135 strHTML += _(" (yours, label: ") + mapAddressBook[strAddress] + ")";
137 strHTML += _(" (yours)");
152 if (!wtx.mapValue["to"].empty())
154 // Online transaction
155 strAddress = wtx.mapValue["to"];
156 strHTML += _("<b>To:</b> ");
157 if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
158 strHTML += mapAddressBook[strAddress] + " ";
159 strHTML += HtmlEscape(strAddress) + "<br>";
166 if (wtx.IsCoinBase() && nCredit == 0)
171 int64 nUnmatured = 0;
172 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
173 nUnmatured += txout.GetCredit();
174 strHTML += _("<b>Credit:</b> ");
175 if (wtx.IsInMainChain())
176 strHTML += strprintf(_("(%s matures in %d more blocks)"), FormatMoney(nUnmatured).c_str(), wtx.GetBlocksToMaturity());
178 strHTML += _("(not accepted)");
186 strHTML += _("<b>Credit:</b> ") + FormatMoney(nNet) + "<br>";
190 bool fAllFromMe = true;
191 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
192 fAllFromMe = fAllFromMe && txin.IsMine();
194 bool fAllToMe = true;
195 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
196 fAllToMe = fAllToMe && txout.IsMine();
203 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
208 if (wtx.mapValue["to"].empty())
210 // Offline transaction
212 if (ExtractHash160(txout.scriptPubKey, hash160))
214 string strAddress = Hash160ToAddress(hash160);
215 strHTML += _("<b>To:</b> ");
216 if (mapAddressBook.count(strAddress) && !mapAddressBook[strAddress].empty())
217 strHTML += mapAddressBook[strAddress] + " ";
218 strHTML += strAddress;
223 strHTML += _("<b>Debit:</b> ") + FormatMoney(-txout.nValue) + "<br>";
229 int64 nChange = wtx.GetChange();
230 int64 nValue = nCredit - nChange;
231 strHTML += _("<b>Debit:</b> ") + FormatMoney(-nValue) + "<br>";
232 strHTML += _("<b>Credit:</b> ") + FormatMoney(nValue) + "<br>";
235 int64 nTxFee = nDebit - wtx.GetValueOut();
237 strHTML += _("<b>Transaction fee:</b> ") + FormatMoney(-nTxFee) + "<br>";
242 // Mixed debit transaction
244 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
246 strHTML += _("<b>Debit:</b> ") + FormatMoney(-txin.GetDebit()) + "<br>";
247 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
249 strHTML += _("<b>Credit:</b> ") + FormatMoney(txout.GetCredit()) + "<br>";
253 strHTML += _("<b>Net amount:</b> ") + FormatMoney(nNet, true) + "<br>";
259 if (!wtx.mapValue["message"].empty())
260 strHTML += string() + "<br><b>" + _("Message:") + "</b><br>" + HtmlEscape(wtx.mapValue["message"], true) + "<br>";
261 if (!wtx.mapValue["comment"].empty())
262 strHTML += string() + "<br><b>" + _("Comment:") + "</b><br>" + HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
264 if (wtx.IsCoinBase())
265 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>";
273 strHTML += "<hr><br>debug print<br><br>";
274 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
276 strHTML += "<b>Debit:</b> " + FormatMoney(-txin.GetDebit()) + "<br>";
277 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
279 strHTML += "<b>Credit:</b> " + FormatMoney(txout.GetCredit()) + "<br>";
281 strHTML += "<br><b>Transaction:</b><br>";
282 strHTML += HtmlEscape(wtx.ToString(), true);
284 strHTML += "<br><b>Inputs:</b><br>";
285 CRITICAL_BLOCK(cs_mapWallet)
287 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
289 COutPoint prevout = txin.prevout;
290 map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
291 if (mi != mapWallet.end())
293 const CWalletTx& prev = (*mi).second;
294 if (prevout.n < prev.vout.size())
296 strHTML += HtmlEscape(prev.ToString(), true);
297 strHTML += " " + FormatTxStatus(prev) + ", ";
298 strHTML = strHTML + "IsMine=" + (prev.vout[prevout.n].IsMine() ? "true" : "false") + "<br>";
307 strHTML += "</font></html>";