1 #include "transactiondesc.h"
4 #include "bitcoinunits.h"
7 #include "ui_interface.h"
13 QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
17 if (wtx.nLockTime < LOCKTIME_THRESHOLD)
18 return tr("Open for %1 blocks").arg(nBestHeight - wtx.nLockTime);
20 return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
24 int nDepth = wtx.GetDepthInMainChain();
25 if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
26 return tr("%1/offline?").arg(nDepth);
28 return tr("%1/unconfirmed").arg(nDepth);
30 return tr("%1 confirmations").arg(nDepth);
34 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
37 CRITICAL_BLOCK(wallet->cs_wallet)
39 strHTML.reserve(4000);
40 strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
42 int64 nTime = wtx.GetTxTime();
43 int64 nCredit = wtx.GetCredit();
44 int64 nDebit = wtx.GetDebit();
45 int64 nNet = nCredit - nDebit;
47 strHTML += tr("<b>Status:</b> ") + FormatTxStatus(wtx);
48 int nRequests = wtx.GetRequestCount();
52 strHTML += tr(", has not been successfully broadcast yet");
53 else if (nRequests == 1)
54 strHTML += tr(", broadcast through %1 node").arg(nRequests);
56 strHTML += tr(", broadcast through %1 nodes").arg(nRequests);
60 strHTML += tr("<b>Date:</b> ") + (nTime ? GUIUtil::dateTimeStr(nTime) : QString("")) + "<br>";
67 strHTML += tr("<b>Source:</b> Generated<br>");
69 else if (!wtx.mapValue["from"].empty())
72 if (!wtx.mapValue["from"].empty())
73 strHTML += tr("<b>From:</b> ") + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
77 // Offline transaction
81 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
83 if (wallet->IsMine(txout))
85 CBitcoinAddress address;
86 if (ExtractAddress(txout.scriptPubKey, address) && wallet->HaveKey(address))
88 if (wallet->mapAddressBook.count(address))
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]) + ")";
96 strHTML += tr(" (yours)");
110 if (!wtx.mapValue["to"].empty())
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>";
123 if (wtx.IsCoinBase() && nCredit == 0)
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());
137 strHTML += tr("(not accepted)");
145 strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>";
149 bool fAllFromMe = true;
150 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
151 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
153 bool fAllToMe = true;
154 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
155 fAllToMe = fAllToMe && wallet->IsMine(txout);
162 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
164 if (wallet->IsMine(txout))
167 if (wtx.mapValue["to"].empty())
169 // Offline transaction
170 CBitcoinAddress address;
171 if (ExtractAddress(txout.scriptPubKey, address))
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());
181 strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>";
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>";
193 int64 nTxFee = nDebit - wtx.GetValueOut();
195 strHTML += tr("<b>Transaction fee:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-nTxFee) + "<br>";
200 // Mixed debit transaction
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>";
211 strHTML += tr("<b>Net amount:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,nNet, true) + "<br>";
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>";
221 strHTML += QString("<b>") + tr("Transaction ID:") + "</b> " + wtx.GetHash().ToString().c_str() + "<br>";
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>";
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>";
239 strHTML += "<br><b>Transaction:</b><br>";
240 strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
242 CTxDB txdb("r"); // To fetch source txouts
244 strHTML += "<br><b>Inputs:</b>";
246 CRITICAL_BLOCK(wallet->cs_wallet)
248 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
250 COutPoint prevout = txin.prevout;
253 if(txdb.ReadDiskTx(prevout.hash, prev))
255 if (prevout.n < prev.vout.size())
258 const CTxOut &vout = prev.vout[prevout.n];
259 CBitcoinAddress address;
260 if (ExtractAddress(vout.scriptPubKey, address))
262 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
263 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
264 strHTML += QString::fromStdString(address.ToString());
266 strHTML = strHTML + " Amount=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,vout.nValue);
267 strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? "true" : "false") + "</li>";
275 strHTML += "</font></html>";