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)
39 LOCK(wallet->cs_wallet);
40 strHTML.reserve(4000);
41 strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
43 int64 nTime = wtx.GetTxTime();
44 int64 nCredit = wtx.GetCredit();
45 int64 nDebit = wtx.GetDebit();
46 int64 nNet = nCredit - nDebit;
48 strHTML += tr("<b>Status:</b> ") + FormatTxStatus(wtx);
49 int nRequests = wtx.GetRequestCount();
53 strHTML += tr(", has not been successfully broadcast yet");
54 else if (nRequests == 1)
55 strHTML += tr(", broadcast through %1 node").arg(nRequests);
57 strHTML += tr(", broadcast through %1 nodes").arg(nRequests);
61 strHTML += tr("<b>Date:</b> ") + (nTime ? GUIUtil::dateTimeStr(nTime) : QString("")) + "<br>";
68 strHTML += tr("<b>Source:</b> Generated<br>");
70 else if (!wtx.mapValue["from"].empty())
73 if (!wtx.mapValue["from"].empty())
74 strHTML += tr("<b>From:</b> ") + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
78 // Offline transaction
82 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
84 if (wallet->IsMine(txout))
86 CBitcoinAddress address;
87 if (ExtractAddress(txout.scriptPubKey, address) && wallet->HaveKey(address))
89 if (wallet->mapAddressBook.count(address))
91 strHTML += tr("<b>From:</b> ") + tr("unknown") + "<br>";
92 strHTML += tr("<b>To:</b> ");
93 strHTML += GUIUtil::HtmlEscape(address.ToString());
94 if (!wallet->mapAddressBook[address].empty())
95 strHTML += tr(" (yours, label: ") + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")";
97 strHTML += tr(" (yours)");
111 if (!wtx.mapValue["to"].empty())
113 // Online transaction
114 strAddress = wtx.mapValue["to"];
115 strHTML += tr("<b>To:</b> ");
116 if (wallet->mapAddressBook.count(strAddress) && !wallet->mapAddressBook[strAddress].empty())
117 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[strAddress]) + " ";
118 strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
124 if (wtx.IsCoinBase() && nCredit == 0)
129 int64 nUnmatured = 0;
130 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
131 nUnmatured += wallet->GetCredit(txout);
132 strHTML += tr("<b>Credit:</b> ");
133 if (wtx.IsInMainChain())
134 strHTML += tr("(%1 matures in %2 more blocks)")
135 .arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured))
136 .arg(wtx.GetBlocksToMaturity());
138 strHTML += tr("(not accepted)");
146 strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>";
150 bool fAllFromMe = true;
151 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
152 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
154 bool fAllToMe = true;
155 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
156 fAllToMe = fAllToMe && wallet->IsMine(txout);
163 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
165 if (wallet->IsMine(txout))
168 if (wtx.mapValue["to"].empty())
170 // Offline transaction
171 CBitcoinAddress address;
172 if (ExtractAddress(txout.scriptPubKey, address))
174 strHTML += tr("<b>To:</b> ");
175 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
176 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
177 strHTML += GUIUtil::HtmlEscape(address.ToString());
182 strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>";
188 int64 nChange = wtx.GetChange();
189 int64 nValue = nCredit - nChange;
190 strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "<br>";
191 strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>";
194 int64 nTxFee = nDebit - wtx.GetValueOut();
196 strHTML += tr("<b>Transaction fee:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-nTxFee) + "<br>";
201 // Mixed debit transaction
203 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
204 if (wallet->IsMine(txin))
205 strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-wallet->GetDebit(txin)) + "<br>";
206 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
207 if (wallet->IsMine(txout))
208 strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,wallet->GetCredit(txout)) + "<br>";
212 strHTML += tr("<b>Net amount:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,nNet, true) + "<br>";
217 if (!wtx.mapValue["message"].empty())
218 strHTML += QString("<br><b>") + tr("Message:") + "</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
219 if (!wtx.mapValue["comment"].empty())
220 strHTML += QString("<br><b>") + tr("Comment:") + "</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
222 strHTML += QString("<b>") + tr("Transaction ID:") + "</b> " + wtx.GetHash().ToString().c_str() + "<br>";
224 if (wtx.IsCoinBase())
225 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>";
232 strHTML += "<hr><br>Debug information<br><br>";
233 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
234 if(wallet->IsMine(txin))
235 strHTML += "<b>Debit:</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-wallet->GetDebit(txin)) + "<br>";
236 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
237 if(wallet->IsMine(txout))
238 strHTML += "<b>Credit:</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,wallet->GetCredit(txout)) + "<br>";
240 strHTML += "<br><b>Transaction:</b><br>";
241 strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
243 CTxDB txdb("r"); // To fetch source txouts
245 strHTML += "<br><b>Inputs:</b>";
249 LOCK(wallet->cs_wallet);
250 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
252 COutPoint prevout = txin.prevout;
255 if(txdb.ReadDiskTx(prevout.hash, prev))
257 if (prevout.n < prev.vout.size())
260 const CTxOut &vout = prev.vout[prevout.n];
261 CBitcoinAddress address;
262 if (ExtractAddress(vout.scriptPubKey, address))
264 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
265 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
266 strHTML += QString::fromStdString(address.ToString());
268 strHTML = strHTML + " Amount=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,vout.nValue);
269 strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? "true" : "false") + "</li>";
277 strHTML += "</font></html>";