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 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, 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>";
228 if (wtx.IsCoinStake())
229 strHTML += QString("<br>") + tr("Staked coins must wait 520 blocks before they can return to balance and be spent. When you generated this proof-of-stake 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 a valid stake. This may occasionally happen if another node generates a proof-of-stake block within a few seconds of yours.") + "<br>";
236 strHTML += "<hr><br>Debug information<br><br>";
237 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
238 if(wallet->IsMine(txin))
239 strHTML += "<b>Debit:</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,-wallet->GetDebit(txin)) + "<br>";
240 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
241 if(wallet->IsMine(txout))
242 strHTML += "<b>Credit:</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,wallet->GetCredit(txout)) + "<br>";
244 strHTML += "<br><b>Transaction:</b><br>";
245 strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
247 CTxDB txdb("r"); // To fetch source txouts
249 strHTML += "<br><b>Inputs:</b>";
253 LOCK(wallet->cs_wallet);
254 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
256 COutPoint prevout = txin.prevout;
259 if(txdb.ReadDiskTx(prevout.hash, prev))
261 if (prevout.n < prev.vout.size())
264 const CTxOut &vout = prev.vout[prevout.n];
265 CBitcoinAddress address;
266 if (ExtractAddress(vout.scriptPubKey, address))
268 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
269 strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
270 strHTML += QString::fromStdString(address.ToString());
272 strHTML = strHTML + " Amount=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,vout.nValue);
273 strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? "true" : "false") + "</li>";
281 strHTML += "</font></html>";