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();
25 return tr("conflicted");
26 else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
27 return tr("%1/offline").arg(nDepth);
29 return tr("%1/unconfirmed").arg(nDepth);
31 return tr("%1 confirmations").arg(nDepth);
35 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
40 LOCK(wallet->cs_wallet);
41 strHTML.reserve(4000);
42 strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
44 int64 nTime = wtx.GetTxTime();
45 int64 nCredit = wtx.GetCredit();
46 int64 nDebit = wtx.GetDebit();
47 int64 nNet = nCredit - nDebit;
49 strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx);
50 int nRequests = wtx.GetRequestCount();
54 strHTML += tr(", has not been successfully broadcast yet");
55 else if (nRequests > 0)
56 strHTML += tr(", broadcast through %n node(s)", "", nRequests);
60 strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
67 strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";
69 else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
72 strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
76 // Offline transaction
80 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
82 if (wallet->IsMine(txout))
84 CTxDestination address;
85 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
87 if (wallet->mapAddressBook.count(address))
89 strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
90 strHTML += "<b>" + tr("To") + ":</b> ";
91 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
92 if (!wallet->mapAddressBook[address].empty())
93 strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")";
95 strHTML += " (" + tr("own address") + ")";
108 if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
110 // Online transaction
111 std::string strAddress = wtx.mapValue["to"];
112 strHTML += "<b>" + tr("To") + ":</b> ";
113 CTxDestination dest = CBitcoinAddress(strAddress).Get();
114 if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty())
115 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " ";
116 strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
122 if (wtx.IsCoinBase() && nCredit == 0)
127 int64 nUnmatured = 0;
128 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
129 nUnmatured += wallet->GetCredit(txout);
130 strHTML += "<b>" + tr("Credit") + ":</b> ";
131 if (wtx.IsInMainChain())
132 strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
134 strHTML += "(" + tr("not accepted") + ")";
142 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>";
146 bool fAllFromMe = true;
147 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
148 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
150 bool fAllToMe = true;
151 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
152 fAllToMe = fAllToMe && wallet->IsMine(txout);
159 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
161 if (wallet->IsMine(txout))
164 if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
166 // Offline transaction
167 CTxDestination address;
168 if (ExtractDestination(txout.scriptPubKey, address))
170 strHTML += "<b>" + tr("To") + ":</b> ";
171 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
172 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
173 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
178 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>";
184 int64 nChange = wtx.GetChange();
185 int64 nValue = nCredit - nChange;
186 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "<br>";
187 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>";
190 int64 nTxFee = nDebit - wtx.GetValueOut();
192 strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nTxFee) + "<br>";
197 // Mixed debit transaction
199 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
200 if (wallet->IsMine(txin))
201 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "<br>";
202 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
203 if (wallet->IsMine(txout))
204 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "<br>";
208 strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet, true) + "<br>";
213 if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
214 strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
215 if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
216 strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
218 strHTML += "<b>" + tr("Transaction ID") + ":</b> " + wtx.GetHash().ToString().c_str() + "<br>";
220 if (wtx.IsCoinBase() || wtx.IsCoinStake())
221 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>";
228 strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
229 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
230 if(wallet->IsMine(txin))
231 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "<br>";
232 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
233 if(wallet->IsMine(txout))
234 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "<br>";
236 strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
237 strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
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(pcoinsTip->GetCoins(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>";