1 #include "transactiondesc.h"
4 #include "bitcoinunits.h"
9 #include "ui_interface.h"
12 QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
16 if (wtx.nLockTime < LOCKTIME_THRESHOLD)
17 return tr("Open for %n block(s)", "", nBestHeight - wtx.nLockTime);
19 return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
23 int nDepth = wtx.GetDepthInMainChain();
24 if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
25 return tr("%1/offline").arg(nDepth);
27 return tr("%1/unconfirmed").arg(nDepth);
29 return tr("%1 confirmations").arg(nDepth);
33 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
38 LOCK(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(MINE_ALL);
44 int64 nDebit = wtx.GetDebit(MINE_ALL);
45 int64 nNet = nCredit - nDebit;
47 strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx);
48 int nRequests = wtx.GetRequestCount();
52 strHTML += tr(", has not been successfully broadcast yet");
53 else if (nRequests > 0)
54 strHTML += tr(", broadcast through %n node(s)", "", nRequests);
58 strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
63 if (wtx.IsCoinBase() || wtx.IsCoinStake())
65 strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";
67 else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
70 strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
74 // Offline transaction
78 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
80 if (wallet->IsMine(txout))
82 CTxDestination address;
83 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
85 if (wallet->mapAddressBook.count(address))
87 strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
88 strHTML += "<b>" + tr("To") + ":</b> ";
89 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
90 if (!wallet->mapAddressBook[address].empty())
91 strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")";
93 strHTML += " (" + tr("own address") + ")";
106 if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
108 // Online transaction
109 std::string strAddress = wtx.mapValue["to"];
110 strHTML += "<b>" + tr("To") + ":</b> ";
111 CTxDestination dest = CBitcoinAddress(strAddress).Get();
112 if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty())
113 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " ";
114 strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
120 if (wtx.IsCoinBase() && nCredit == 0)
125 int64 nUnmatured = 0;
126 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
127 nUnmatured += wallet->GetCredit(txout, MINE_ALL);
128 strHTML += "<b>" + tr("Credit") + ":</b> ";
129 if (wtx.IsInMainChain())
130 strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
132 strHTML += "(" + tr("not accepted") + ")";
140 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>";
144 bool fAllFromMe = true;
145 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
146 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
148 bool fAllToMe = true;
149 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
150 fAllToMe = fAllToMe && wallet->IsMine(txout);
157 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
159 if (wallet->IsMine(txout))
162 if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
164 // Offline transaction
165 CTxDestination address;
166 if (ExtractDestination(txout.scriptPubKey, address))
168 strHTML += "<b>" + tr("To") + ":</b> ";
169 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
170 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
171 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
176 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>";
182 int64 nChange = wtx.GetChange();
183 int64 nValue = nCredit - nChange;
184 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "<br>";
185 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>";
188 int64 nTxFee = nDebit - wtx.GetValueOut();
190 strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nTxFee) + "<br>";
195 // Mixed debit transaction
197 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
198 if (wallet->IsMine(txin))
199 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin, MINE_ALL)) + "<br>";
200 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
201 if (wallet->IsMine(txout))
202 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, MINE_ALL)) + "<br>";
206 strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet, true) + "<br>";
211 if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
212 strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
213 if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
214 strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
216 strHTML += "<b>" + tr("Transaction ID") + ":</b> " + wtx.GetHash().ToString().c_str() + "<br>";
218 if (wtx.IsCoinBase() || wtx.IsCoinStake())
219 strHTML += "<br>" + tr("Generated coins must mature 520 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, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.") + "<br>";
226 strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
227 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
228 if(wallet->IsMine(txin))
229 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin, MINE_ALL)) + "<br>";
230 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
231 if(wallet->IsMine(txout))
232 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, MINE_ALL)) + "<br>";
234 strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
235 strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
237 CTxDB txdb("r"); // To fetch source txouts
239 strHTML += "<br><b>" + tr("Inputs") + ":</b>";
243 LOCK(wallet->cs_wallet);
244 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
246 COutPoint prevout = txin.prevout;
249 if(txdb.ReadDiskTx(prevout.hash, prev))
251 if (prevout.n < prev.vout.size())
254 const CTxOut &vout = prev.vout[prevout.n];
255 CTxDestination address;
256 if (ExtractDestination(vout.scriptPubKey, address))
258 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
259 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
260 strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
262 strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, vout.nValue);
263 strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "</li>";
272 strHTML += "</font></html>";