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());
108 if(wallet->mapAddressBook.find(senderAddress) != wallet->mapAddressBook.end())
109 if (!wallet->mapAddressBook[senderAddress].empty())
111 strHTML += " (" + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[senderAddress]) + ")";
116 strHTML += "<b>" + tr("To") + ":</b> ";
117 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
118 if (!wallet->mapAddressBook[address].empty())
119 strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")";
121 strHTML += " (" + tr("own address") + ")";
134 if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
136 // Online transaction
137 std::string strAddress = wtx.mapValue["to"];
138 strHTML += "<b>" + tr("To") + ":</b> ";
139 CTxDestination dest = CBitcoinAddress(strAddress).Get();
140 if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty())
141 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " ";
142 strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
148 if (wtx.IsCoinBase() && nCredit == 0)
153 int64 nUnmatured = 0;
154 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
155 nUnmatured += wallet->GetCredit(txout, MINE_ALL);
156 strHTML += "<b>" + tr("Credit") + ":</b> ";
157 if (wtx.IsInMainChain())
158 strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
160 strHTML += "(" + tr("not accepted") + ")";
168 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>";
172 bool fAllFromMe = true;
173 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
174 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
176 bool fAllToMe = true;
177 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
178 fAllToMe = fAllToMe && wallet->IsMine(txout);
185 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
187 if (wallet->IsMine(txout))
190 if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
192 // Offline transaction
193 CTxDestination address;
194 if (ExtractDestination(txout.scriptPubKey, address))
196 strHTML += "<b>" + tr("To") + ":</b> ";
197 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
198 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
199 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
204 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>";
210 int64 nChange = wtx.GetChange();
211 int64 nValue = nCredit - nChange;
212 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "<br>";
213 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>";
216 int64 nTxFee = nDebit - wtx.GetValueOut();
218 strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nTxFee) + "<br>";
223 // Mixed debit transaction
225 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
226 if (wallet->IsMine(txin))
227 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin, MINE_ALL)) + "<br>";
228 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
229 if (wallet->IsMine(txout))
230 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, MINE_ALL)) + "<br>";
234 strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet, true) + "<br>";
239 if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
240 strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
241 if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
242 strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
244 strHTML += "<b>" + tr("Transaction ID") + ":</b> " + wtx.GetHash().ToString().c_str() + "<br>";
246 if (wtx.IsCoinBase() || wtx.IsCoinStake())
247 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>";
254 strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
255 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
256 if(wallet->IsMine(txin))
257 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin, MINE_ALL)) + "<br>";
258 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
259 if(wallet->IsMine(txout))
260 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, MINE_ALL)) + "<br>";
262 strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
263 strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
265 CTxDB txdb("r"); // To fetch source txouts
267 strHTML += "<br><b>" + tr("Inputs") + ":</b>";
271 LOCK(wallet->cs_wallet);
272 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
274 COutPoint prevout = txin.prevout;
277 if(txdb.ReadDiskTx(prevout.hash, prev))
279 if (prevout.n < prev.vout.size())
282 const CTxOut &vout = prev.vout[prevout.n];
283 CTxDestination address;
284 if (ExtractDestination(vout.scriptPubKey, address))
286 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
287 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
288 strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
290 strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, vout.nValue);
291 strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "</li>";
300 strHTML += "</font></html>";