QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) { // individual tx do not affect any representation static const bool fMultiSig = true; QString strHTML; LOCK2(cs_main, wallet->cs_wallet); strHTML.reserve(4000); strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>"; int64_t nTime = wtx.GetTxTime(); std::map<int, int64_t> mapDebit, mapCredit, mapChange, mapNet; // debits wallet->FillDebits(wtx, mapDebit, fMultiSig); // credits (mature) wallet->FillMatures(wtx, mapCredit, fMultiSig); // nets (mature - debits) FillNets(mapDebit, mapCredit, mapNet); strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx); int nRequests = wtx.GetRequestCount(); if (nRequests != -1) { if (nRequests == 0) strHTML += tr(", has not been successfully broadcast yet"); else if (nRequests > 0) strHTML += tr(", broadcast through %n node(s)", "", nRequests); } strHTML += "<br>"; strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>"; // // From // if (wtx.IsCoinBase() || wtx.IsCoinStake()) { strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>"; } else if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty()) { // Online transaction strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>"; } else { // Offline transaction if (ValueMapAllPositive(mapNet)) { // Credit BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if (wallet->IsMine(txout, fMultiSig) & ISMINE_ALL) { CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address) && (IsMine(*wallet, address, fMultiSig) & ISMINE_ALL)) { if (wallet->mapAddressBook.count(address)) { strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>"; strHTML += "<b>" + tr("To") + ":</b> "; CBitcoinAddress addr(address, txout.nColor); strHTML += GUIUtil::HtmlEscape(addr.ToString()); // indicate distinction between own address and watch address if (IsMine(*wallet, address, fMultiSig) & ISMINE_SPENDABLE) { if (!wallet->mapAddressBook[address].empty()) { strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")"; } else { strHTML += " (" + tr("own address") + ")"; } } else { if (!wallet->mapAddressBook[address].empty()) { strHTML += " (" + tr("watch address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")"; } else { strHTML += " (" + tr("watch address") + ")"; } } strHTML += "<br>"; } } break; } } } } // // To // if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty()) { // Online transaction std::string strAddress = wtx.mapValue["to"]; strHTML += "<b>" + tr("To") + ":</b> "; CTxDestination dest = CBitcoinAddress(strAddress).Get(); if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " "; strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>"; } // // Amount // // Coinbase was not mature if (wtx.IsCoinBase() && ValueMapAllZero(mapCredit)) { // // Coinbase // strHTML += "<b>" + tr("Credit") + ":</b> "; if (wtx.IsInMainChain()) { std::map<int, int64_t> mapUnmatured; wallet->FillCredits(wtx, mapUnmatured, fMultiSig); strHTML += ValueMapToHTML(mapUnmatured); strHTML += " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; } else { strHTML += "(" + tr("not accepted") + ")"; } strHTML += "<br>"; } else if (ValueMapAllPositive(mapNet)) { // // Credit // strHTML += "<b>" + tr("Credit") + ":</b> " + ValueMapToHTML(mapNet) + "<br>"; } else { bool fAllFromMe = true; BOOST_FOREACH(const CTxIn& txin, wtx.vin) { fAllFromMe = fAllFromMe && (wallet->IsMine(txin, fMultiSig) & ISMINE_SPENDABLE); if (!fAllFromMe) { break; } } bool fAllToMe = true; BOOST_FOREACH(const CTxOut& txout, wtx.vout) { fAllToMe = fAllToMe && (wallet->IsMine(txout, fMultiSig) & ISMINE_SPENDABLE); if (!fAllToMe) { break; } } if (fAllFromMe) { // // Debit // BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if (wallet->IsMine(txout, fMultiSig) & ISMINE_SPENDABLE) { continue; } if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty()) { // Offline transaction CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address)) { strHTML += "<b>" + tr("To") + ":</b> "; if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " "; strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address, txout.nColor).ToString()); strHTML += "<br>"; } } strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -txout.nValue, txout.nColor) + "<br>"; } std::map<int, int64_t> mapFee, mapDebit, mapValuesOut; if (fAllToMe) { // Payment to self std::map<int, int64_t> mapChange, mapValue; wallet->FillChange(wtx, mapChange); FillNets(mapChange, mapCredit, mapValue); FillNets(mapCredit, mapChange, mapDebit); strHTML += "<b>" + tr("Debit") + ":</b> " + ValueMapToHTML(mapDebit) + "<br>"; strHTML += "<b>" + tr("Credit") + ":</b> " + ValueMapToHTML(mapValue) + "<br>"; } wtx.FillValuesOut(mapValuesOut); wallet->FillDebits(wtx, mapDebit, fMultiSig); FillNets(mapValuesOut, mapDebit, mapFee); if (ValueMapAllPositive(mapFee)) { strHTML += "<b>" + tr("Transaction fee") + ":</b> " + ValueMapToHTML(mapFee) + "<br>"; } } else { // // Mixed debit transaction // BOOST_FOREACH(const CTxIn& txin, wtx.vin) { strHTML += TxInToHTML(txin, wallet); } BOOST_FOREACH(const CTxOut& txout, wtx.vout) { strHTML += TxOutToHTML(txout, wallet); } } }