1 #include "transactiondesc.h"
4 #include "bitcoinunits.h"
9 #include "ui_interface.h"
15 QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
19 if (wtx.nLockTime < LOCKTIME_THRESHOLD)
20 return tr("Open for %1 blocks").arg(nBestHeight - wtx.nLockTime);
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)
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 += tr("<b>Status:</b> ") + FormatTxStatus(wtx);
51 int nRequests = wtx.GetRequestCount();
55 strHTML += tr(", has not been successfully broadcast yet");
56 else if (nRequests == 1)
57 strHTML += tr(", broadcast through %1 node").arg(nRequests);
59 strHTML += tr(", broadcast through %1 nodes").arg(nRequests);
63 strHTML += tr("<b>Date:</b> ") + (nTime ? GUIUtil::dateTimeStr(nTime) : QString("")) + "<br>";
70 strHTML += tr("<b>Source:</b> Generated<br>");
72 else if (!wtx.mapValue["from"].empty())
75 if (!wtx.mapValue["from"].empty())
76 strHTML += tr("<b>From:</b> ") + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
80 // Offline transaction
84 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
86 if (wallet->IsMine(txout))
88 CBitcoinAddress address;
89 if (ExtractAddress(txout.scriptPubKey, address) && wallet->HaveKey(address))
91 if (wallet->mapAddressBook.count(address))
93 strHTML += tr("<b>From:</b> ") + tr("unknown") + "<br>";
94 strHTML += tr("<b>To:</b> ");
95 strHTML += GUIUtil::HtmlEscape(address.ToString());
96 if (!wallet->mapAddressBook[address].empty())
97 strHTML += tr(" (yours, label: ") + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")";
99 strHTML += tr(" (yours)");
113 if (!wtx.mapValue["to"].empty())
115 // Online transaction
116 strAddress = wtx.mapValue["to"];
117 strHTML += tr("<b>To:</b> ");
118 if (wallet->mapAddressBook.count(strAddress) && !wallet->mapAddressBook[strAddress].empty())
119 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[strAddress]) + " ";
120 strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
126 if (wtx.IsCoinBase() && nCredit == 0)
131 int64 nUnmatured = 0;
132 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
133 nUnmatured += wallet->GetCredit(txout);
134 strHTML += tr("<b>Credit:</b> ");
135 if (wtx.IsInMainChain())
136 strHTML += tr("(%1 matures in %2 more blocks)")
137 .arg(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured))
138 .arg(wtx.GetBlocksToMaturity());
140 strHTML += tr("(not accepted)");
148 strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nNet) + "<br>";
152 bool fAllFromMe = true;
153 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
154 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
156 bool fAllToMe = true;
157 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
158 fAllToMe = fAllToMe && wallet->IsMine(txout);
165 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
167 if (wallet->IsMine(txout))
170 if (wtx.mapValue["to"].empty())
172 // Offline transaction
173 CBitcoinAddress address;
174 if (ExtractAddress(txout.scriptPubKey, address))
176 strHTML += tr("<b>To:</b> ");
177 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
178 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
179 strHTML += GUIUtil::HtmlEscape(address.ToString());
184 strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue) + "<br>";
190 int64 nChange = wtx.GetChange();
191 int64 nValue = nCredit - nChange;
192 strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -nValue) + "<br>";
193 strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nValue) + "<br>";
196 int64 nTxFee = nDebit - wtx.GetValueOut();
198 strHTML += tr("<b>Transaction fee:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-nTxFee) + "<br>";
203 // Mixed debit transaction
205 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
206 if (wallet->IsMine(txin))
207 strHTML += tr("<b>Debit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-wallet->GetDebit(txin)) + "<br>";
208 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
209 if (wallet->IsMine(txout))
210 strHTML += tr("<b>Credit:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,wallet->GetCredit(txout)) + "<br>";
214 strHTML += tr("<b>Net amount:</b> ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,nNet, true) + "<br>";
219 if (!wtx.mapValue["message"].empty())
220 strHTML += QString("<br><b>") + tr("Message:") + "</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
221 if (!wtx.mapValue["comment"].empty())
222 strHTML += QString("<br><b>") + tr("Comment:") + "</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
224 strHTML += QString("<b>") + tr("Transaction ID:") + "</b> " + wtx.GetHash().ToString().c_str() + "<br>";
226 if (wtx.IsCoinBase())
227 strHTML += QString("<br>") + tr("Generated coins must wait 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, it will change to \"not accepted\" and not be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.") + "<br>";
234 strHTML += "<hr><br>Debug information<br><br>";
235 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
236 if(wallet->IsMine(txin))
237 strHTML += "<b>Debit:</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-wallet->GetDebit(txin)) + "<br>";
238 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
239 if(wallet->IsMine(txout))
240 strHTML += "<b>Credit:</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,wallet->GetCredit(txout)) + "<br>";
242 strHTML += "<br><b>Transaction:</b><br>";
243 strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
245 CTxDB txdb("r"); // To fetch source txouts
247 strHTML += "<br><b>Inputs:</b>";
251 LOCK(wallet->cs_wallet);
252 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
254 COutPoint prevout = txin.prevout;
257 if(txdb.ReadDiskTx(prevout.hash, prev))
259 if (prevout.n < prev.vout.size())
262 const CTxOut &vout = prev.vout[prevout.n];
263 CBitcoinAddress address;
264 if (ExtractAddress(vout.scriptPubKey, address))
266 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
267 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
268 strHTML += QString::fromStdString(address.ToString());
270 strHTML = strHTML + " Amount=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,vout.nValue);
271 strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? "true" : "false") + "</li>";
279 strHTML += "</font></html>";