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 for (unsigned int i = 0; i < wtx.vin.size(); i++)
90 const CTxIn& vin = wtx.vin[i];
91 hash.SetHex(vin.prevout.hash.ToString());
93 uint256 hashBlock = 0;
94 if (!GetTransaction(hash, wtxPrev, hashBlock))
96 strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
99 CTxDestination senderAddress;
100 if (!ExtractDestination(wtxPrev.vout[vin.prevout.n].scriptPubKey, senderAddress) )
102 strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
106 strHTML += "<b>" + tr("From") + ":</b> ";
107 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(senderAddress).ToString());
111 strHTML += "<b>" + tr("To") + ":</b> ";
112 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
113 if (!wallet->mapAddressBook[address].empty())
114 strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")";
116 strHTML += " (" + tr("own address") + ")";
129 if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
131 // Online transaction
132 std::string strAddress = wtx.mapValue["to"];
133 strHTML += "<b>" + tr("To") + ":</b> ";
134 CTxDestination dest = CBitcoinAddress(strAddress).Get();
135 if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty())
136 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " ";
137 strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
143 if (wtx.IsCoinBase() && nCredit == 0)
148 int64 nUnmatured = 0;
149 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
150 nUnmatured += wallet->GetCredit(txout, MINE_ALL);
151 strHTML += "<b>" + tr("Credit") + ":</b> ";
152 if (wtx.IsInMainChain())
153 strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
155 strHTML += "(" + tr("not accepted") + ")";
163 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>";
167 bool fAllFromMe = true;
168 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
169 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
171 bool fAllToMe = true;
172 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
173 fAllToMe = fAllToMe && wallet->IsMine(txout);
180 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
182 if (wallet->IsMine(txout))
185 if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
187 // Offline transaction
188 CTxDestination address;
189 if (ExtractDestination(txout.scriptPubKey, address))
191 strHTML += "<b>" + tr("To") + ":</b> ";
192 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
193 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
194 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
199 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>";
205 int64 nChange = wtx.GetChange();
206 int64 nValue = nCredit - nChange;
207 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "<br>";
208 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>";
211 int64 nTxFee = nDebit - wtx.GetValueOut();
213 strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nTxFee) + "<br>";
218 // Mixed debit transaction
220 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
221 if (wallet->IsMine(txin))
222 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin, MINE_ALL)) + "<br>";
223 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
224 if (wallet->IsMine(txout))
225 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, MINE_ALL)) + "<br>";
229 strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet, true) + "<br>";
234 if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
235 strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
236 if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
237 strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
239 strHTML += "<b>" + tr("Transaction ID") + ":</b> " + wtx.GetHash().ToString().c_str() + "<br>";
241 if (wtx.IsCoinBase() || wtx.IsCoinStake())
242 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>";
249 strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
250 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
251 if(wallet->IsMine(txin))
252 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin, MINE_ALL)) + "<br>";
253 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
254 if(wallet->IsMine(txout))
255 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, MINE_ALL)) + "<br>";
257 strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
258 strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
260 CTxDB txdb("r"); // To fetch source txouts
262 strHTML += "<br><b>" + tr("Inputs") + ":</b>";
266 LOCK(wallet->cs_wallet);
267 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
269 COutPoint prevout = txin.prevout;
272 if(txdb.ReadDiskTx(prevout.hash, prev))
274 if (prevout.n < prev.vout.size())
277 const CTxOut &vout = prev.vout[prevout.n];
278 CTxDestination address;
279 if (ExtractDestination(vout.scriptPubKey, address))
281 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
282 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
283 strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
285 strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, vout.nValue);
286 strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "</li>";
295 strHTML += "</font></html>";