1 #include <transactiondesc.h>
4 #include "bitcoinunits.h"
10 #include <QTextDocument> // For Qt::escape
14 QString TransactionDesc::HtmlEscape(const QString& str, bool fMultiLine)
16 QString escaped = Qt::escape(str);
19 escaped = escaped.replace("\n", "<br>\n");
24 QString TransactionDesc::HtmlEscape(const std::string& str, bool fMultiLine)
26 return HtmlEscape(QString::fromStdString(str), fMultiLine);
29 QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
33 if (wtx.nLockTime < LOCKTIME_THRESHOLD)
34 return tr("Open for %1 blocks").arg(nBestHeight - wtx.nLockTime);
36 return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
40 int nDepth = wtx.GetDepthInMainChain();
41 if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
42 return tr("%1/offline?").arg(nDepth);
44 return tr("%1/unconfirmed").arg(nDepth);
46 return tr("%1 confirmations").arg(nDepth);
50 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
53 CRITICAL_BLOCK(wallet->cs_wallet)
55 strHTML.reserve(4000);
56 strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
58 int64 nTime = wtx.GetTxTime();
59 int64 nCredit = wtx.GetCredit();
60 int64 nDebit = wtx.GetDebit();
61 int64 nNet = nCredit - nDebit;
63 strHTML += tr("<b>Status:</b> ") + FormatTxStatus(wtx);
64 int nRequests = wtx.GetRequestCount();
68 strHTML += tr(", has not been successfully broadcast yet");
69 else if (nRequests == 1)
70 strHTML += tr(", broadcast through %1 node").arg(nRequests);
72 strHTML += tr(", broadcast through %1 nodes").arg(nRequests);
76 strHTML += tr("<b>Date:</b> ") + (nTime ? GUIUtil::dateTimeStr(nTime) : QString("")) + "<br>";
83 strHTML += tr("<b>Source:</b> Generated<br>");
85 else if (!wtx.mapValue["from"].empty())
88 if (!wtx.mapValue["from"].empty())
89 strHTML += tr("<b>From:</b> ") + HtmlEscape(wtx.mapValue["from"]) + "<br>";
93 // Offline transaction
97 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
99 if (wallet->IsMine(txout))
101 CBitcoinAddress address;
102 if (ExtractAddress(txout.scriptPubKey, wallet, address))
104 if (wallet->mapAddressBook.count(address))
106 strHTML += tr("<b>From:</b> ") + tr("unknown") + "<br>";
107 strHTML += tr("<b>To:</b> ");
108 strHTML += HtmlEscape(address.ToString());
109 if (!wallet->mapAddressBook[address].empty())
110 strHTML += tr(" (yours, label: ") + HtmlEscape(wallet->mapAddressBook[address]) + ")";
112 strHTML += tr(" (yours)");
126 if (!wtx.mapValue["to"].empty())
128 // Online transaction
129 strAddress = wtx.mapValue["to"];
130 strHTML += tr("<b>To:</b> ");
131 if (wallet->mapAddressBook.count(strAddress) && !wallet->mapAddressBook[strAddress].empty())
132 strHTML += HtmlEscape(wallet->mapAddressBook[strAddress]) + " ";
133 strHTML += HtmlEscape(strAddress) + "<br>";
139 if (wtx.IsCoinBase() && nCredit == 0)
144 int64 nUnmatured = 0;
145 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
146 nUnmatured += wallet->GetCredit(txout);
147 strHTML += tr("<b>Credit:</b> ");
148 if (wtx.IsInMainChain())
149 strHTML += tr("(%1 matures in %2 more blocks)")
150 .arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured))
151 .arg(wtx.GetBlocksToMaturity());
153 strHTML += tr("(not accepted)");
161 strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>";
165 bool fAllFromMe = true;
166 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
167 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
169 bool fAllToMe = true;
170 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
171 fAllToMe = fAllToMe && wallet->IsMine(txout);
178 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
180 if (wallet->IsMine(txout))
183 if (wtx.mapValue["to"].empty())
185 // Offline transaction
186 CBitcoinAddress address;
187 if (ExtractAddress(txout.scriptPubKey, 0, address))
189 strHTML += tr("<b>To:</b> ");
190 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
191 strHTML += HtmlEscape(wallet->mapAddressBook[address]) + " ";
192 strHTML += HtmlEscape(address.ToString());
197 strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>";
203 int64 nChange = wtx.GetChange();
204 int64 nValue = nCredit - nChange;
205 strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "<br>";
206 strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>";
209 int64 nTxFee = nDebit - wtx.GetValueOut();
211 strHTML += tr("<b>Transaction fee:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-nTxFee) + "<br>";
216 // Mixed debit transaction
218 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
219 if (wallet->IsMine(txin))
220 strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-wallet->GetDebit(txin)) + "<br>";
221 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
222 if (wallet->IsMine(txout))
223 strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,wallet->GetCredit(txout)) + "<br>";
227 strHTML += tr("<b>Net amount:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,nNet, true) + "<br>";
232 if (!wtx.mapValue["message"].empty())
233 strHTML += QString("<br><b>") + tr("Message:") + "</b><br>" + HtmlEscape(wtx.mapValue["message"], true) + "<br>";
234 if (!wtx.mapValue["comment"].empty())
235 strHTML += QString("<br><b>") + tr("Comment:") + "</b><br>" + HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
237 if (wtx.IsCoinBase())
238 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>";
245 strHTML += "<hr><br>Debug information<br><br>";
246 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
247 if(wallet->IsMine(txin))
248 strHTML += "<b>Debit:</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-wallet->GetDebit(txin)) + "<br>";
249 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
250 if(wallet->IsMine(txout))
251 strHTML += "<b>Credit:</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,wallet->GetCredit(txout)) + "<br>";
253 strHTML += "<br><b>Transaction:</b><br>";
254 strHTML += HtmlEscape(wtx.ToString(), true);
256 CTxDB txdb("r"); // To fetch source txouts
258 strHTML += "<br><b>Inputs:</b>";
260 CRITICAL_BLOCK(wallet->cs_wallet)
262 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
264 COutPoint prevout = txin.prevout;
267 if(txdb.ReadDiskTx(prevout.hash, prev))
269 if (prevout.n < prev.vout.size())
272 const CTxOut &vout = prev.vout[prevout.n];
273 CBitcoinAddress address;
274 if (ExtractAddress(vout.scriptPubKey, 0, address))
276 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
277 strHTML += HtmlEscape(wallet->mapAddressBook[address]) + " ";
278 strHTML += QString::fromStdString(address.ToString());
280 strHTML = strHTML + " Amount=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,vout.nValue);
281 strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? "true" : "false") + "</li>";
289 strHTML += "</font></html>";