1 #include "transactiondesc.h"
4 #include "bitcoinunits.h"
8 #include "ui_interface.h"
10 #include "paymentserver.h"
11 #include "transactionrecord.h"
15 QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
19 if (wtx.nLockTime < LOCKTIME_THRESHOLD)
20 return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height() + 1);
22 return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
26 int nDepth = wtx.GetDepthInMainChain();
27 if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
28 return tr("%1/offline").arg(nDepth);
30 return tr("%1/unconfirmed").arg(nDepth);
32 return tr("%1 confirmations").arg(nDepth);
36 QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, int vout, int unit)
41 LOCK(wallet->cs_wallet);
42 strHTML.reserve(4000);
43 strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
45 int64 nTime = wtx.GetTxTime();
46 int64 nCredit = wtx.GetCredit();
47 int64 nDebit = wtx.GetDebit();
48 int64 nNet = nCredit - nDebit;
50 strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx);
51 int nRequests = wtx.GetRequestCount();
55 strHTML += tr(", has not been successfully broadcast yet");
56 else if (nRequests > 0)
57 strHTML += tr(", broadcast through %n node(s)", "", nRequests);
61 strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
68 strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>";
70 else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty())
73 strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
77 // Offline transaction
81 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
83 if (wallet->IsMine(txout))
85 CTxDestination address;
86 if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
88 if (wallet->mapAddressBook.count(address))
90 strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
91 strHTML += "<b>" + tr("To") + ":</b> ";
92 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
93 if (!wallet->mapAddressBook[address].name.empty())
94 strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")";
96 strHTML += " (" + tr("own address") + ")";
109 if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty())
111 // Online transaction
112 std::string strAddress = wtx.mapValue["to"];
113 strHTML += "<b>" + tr("To") + ":</b> ";
114 CTxDestination dest = CBitcoinAddress(strAddress).Get();
115 if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].name.empty())
116 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest].name) + " ";
117 strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
123 if (wtx.IsCoinBase() && nCredit == 0)
128 int64 nUnmatured = 0;
129 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
130 nUnmatured += wallet->GetCredit(txout);
131 strHTML += "<b>" + tr("Credit") + ":</b> ";
132 if (wtx.IsInMainChain())
133 strHTML += BitcoinUnits::formatWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")";
135 strHTML += "(" + tr("not accepted") + ")";
143 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nNet) + "<br>";
147 bool fAllFromMe = true;
148 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
149 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
151 bool fAllToMe = true;
152 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
153 fAllToMe = fAllToMe && wallet->IsMine(txout);
160 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
162 if (wallet->IsMine(txout))
165 if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
167 // Offline transaction
168 CTxDestination address;
169 if (ExtractDestination(txout.scriptPubKey, address))
171 strHTML += "<b>" + tr("To") + ":</b> ";
172 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
173 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
174 strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
179 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -txout.nValue) + "<br>";
185 int64 nChange = wtx.GetChange();
186 int64 nValue = nCredit - nChange;
187 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -nValue) + "<br>";
188 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nValue) + "<br>";
191 int64 nTxFee = nDebit - GetValueOut(wtx);
193 strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -nTxFee) + "<br>";
198 // Mixed debit transaction
200 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
201 if (wallet->IsMine(txin))
202 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin)) + "<br>";
203 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
204 if (wallet->IsMine(txout))
205 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout)) + "<br>";
209 strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nNet, true) + "<br>";
214 if (wtx.mapValue.count("message") && !wtx.mapValue["message"].empty())
215 strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
216 if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
217 strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
219 strHTML += "<b>" + tr("Transaction ID") + ":</b> " + TransactionRecord::formatSubTxId(wtx.GetHash(), vout) + "<br>";
222 // PaymentRequest info:
224 foreach (const PAIRTYPE(string, string)& r, wtx.vOrderForm)
226 if (r.first == "PaymentRequest")
228 PaymentRequestPlus req;
229 req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
231 if (req.getMerchant(PaymentServer::getCertStore(), merchant))
232 strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
236 if (wtx.IsCoinBase())
237 strHTML += "<br>" + tr("Generated coins must mature 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, 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>";
244 strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
245 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
246 if(wallet->IsMine(txin))
247 strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin)) + "<br>";
248 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
249 if(wallet->IsMine(txout))
250 strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout)) + "<br>";
252 strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
253 strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
255 strHTML += "<br><b>" + tr("Inputs") + ":</b>";
259 LOCK(wallet->cs_wallet);
260 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
262 COutPoint prevout = txin.prevout;
265 if(pcoinsTip->GetCoins(prevout.hash, prev))
267 if (prevout.n < prev.vout.size())
270 const CTxOut &vout = prev.vout[prevout.n];
271 CTxDestination address;
272 if (ExtractDestination(vout.scriptPubKey, address))
274 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
275 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
276 strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
278 strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(unit, vout.nValue);
279 strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "</li>";
288 strHTML += "</font></html>";