QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) { if (!wtx.IsFinal()) { if (wtx.nLockTime < LOCKTIME_THRESHOLD) return tr("Open for %n more block(s)", "", wtx.nLockTime - nBestHeight + 1); else return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime)); } else { int nDepth = wtx.GetDepthInMainChain(); if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) return tr("%1/offline").arg(nDepth); else if (nDepth < 6) return tr("%1/unconfirmed").arg(nDepth); else return tr("%1 confirmations").arg(nDepth); } }
QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) { if (!wtx.IsFinal()) { if (wtx.nLockTime < LOCKTIME_THRESHOLD) return tr("Open for %n block(s)", "", nBestHeight - wtx.nLockTime); else return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime)); } else { int nDepth = wtx.GetDepthInMainChain(); if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) return tr("%1/offline").arg(nDepth); else if (nDepth < TransactionRecord::NumConfirmations)//modified by SuperHashToken to adjust the confirm return tr("%1/unconfirmed").arg(nDepth); else return tr("%1 confirmations").arg(nDepth); } }
/* Return positive answer if transaction should be shown in list. */ bool TransactionRecord::showTransaction(const CWalletTx &wtx) { if (wtx.IsCoinBase()) { // Don't show generated coin until confirmed by at least one block after it // so we don't get the user's hopes up until it looks like it's probably accepted. // // It is not an error when generated blocks are not accepted. By design, // some percentage of blocks, like 10% or more, will end up not accepted. // This is the normal mechanism by which the network copes with latency. // // We display regular transactions right away before any confirmation // because they can always get into some block eventually. Generated coins // are special because if their block is not accepted, they are not valid. // if (wtx.GetDepthInMainChain() < 2) { return false; } } return true; }
//! Check whether transaction has descendant in wallet or mempool, or has been //! mined, or conflicts with a mined transaction. Return a feebumper::Result. static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) { if (wallet->HasWalletSpend(wtx.GetHash())) { errors.push_back("Transaction has descendants in the wallet"); return feebumper::Result::INVALID_PARAMETER; } { LOCK(mempool.cs); auto it_mp = mempool.mapTx.find(wtx.GetHash()); if (it_mp != mempool.mapTx.end() && it_mp->GetCountWithDescendants() > 1) { errors.push_back("Transaction has descendants in the mempool"); return feebumper::Result::INVALID_PARAMETER; } } if (wtx.GetDepthInMainChain() != 0) { errors.push_back("Transaction has been mined, or is conflicted with a mined transaction"); return feebumper::Result::WALLET_ERROR; } return feebumper::Result::OK; }
bool CFeeBumper::preconditionChecks(const CWallet *pWallet, const CWalletTx& wtx) { if (pWallet->HasWalletSpend(wtx.GetHash())) { vErrors.push_back("Transaction has descendants in the wallet"); currentResult = BumpFeeResult::INVALID_PARAMETER; return false; } { LOCK(mempool.cs); auto it_mp = mempool.mapTx.find(wtx.GetHash()); if (it_mp != mempool.mapTx.end() && it_mp->GetCountWithDescendants() > 1) { vErrors.push_back("Transaction has descendants in the mempool"); currentResult = BumpFeeResult::INVALID_PARAMETER; return false; } } if (wtx.GetDepthInMainChain() != 0) { vErrors.push_back("Transaction has been mined, or is conflicted with a mined transaction"); currentResult = BumpFeeResult::WALLET_ERROR; return false; } return true; }
void TransactionRecord::updateStatus(const CWalletTx &wtx) { // Determine transaction status // Find the block the tx is in CBlockIndex* pindex = NULL; std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock); if (mi != mapBlockIndex.end()) pindex = (*mi).second; // Sort order, unrecorded transactions sort to the top status.sortKey = strprintf("%010d-%01d-%010u-%03d", (pindex ? pindex->nHeight : std::numeric_limits<int>::max()), (wtx.IsCoinBase() ? 1 : 0), wtx.nTimeReceived, idx); status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0); status.depth = wtx.GetDepthInMainChain(); status.cur_num_blocks = nBestHeight; if (!wtx.IsFinal()) { if (wtx.nLockTime < LOCKTIME_THRESHOLD) { status.status = TransactionStatus::OpenUntilBlock; status.open_for = nBestHeight - wtx.nLockTime; } else { status.status = TransactionStatus::OpenUntilDate; status.open_for = wtx.nLockTime; } } // For generated transactions, determine maturity else if(type == TransactionRecord::Generated) { if (wtx.GetBlocksToMaturity() > 0) { status.status = TransactionStatus::Immature; if (wtx.IsInMainChain()) { status.matures_in = wtx.GetBlocksToMaturity(); // Check if the block was requested by anyone if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) status.status = TransactionStatus::MaturesWarning; } else { status.status = TransactionStatus::NotAccepted; } } else { status.status = TransactionStatus::Confirmed; } } else { if (status.depth < 0) { status.status = TransactionStatus::Conflicted; } else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) { status.status = TransactionStatus::Offline; } else if (status.depth == 0) { status.status = TransactionStatus::Unconfirmed; } else if (status.depth < RecommendedNumConfirmations) { status.status = TransactionStatus::Confirming; } else { status.status = TransactionStatus::Confirmed; } } }
Value listsinceblock(const Array& params, bool fHelp) { if (fHelp) throw runtime_error( "listsinceblock [blockhash] [target-confirmations]\n" "Get all transactions in blocks since block [blockhash], or all transactions if omitted"); CBlockIndex *pindex = NULL; int target_confirms = 1; if (params.size() > 0) { uint256 blockId = 0; blockId.SetHex(params[0].get_str()); pindex = CBlockLocator(blockId).GetBlockIndex(); } if (params.size() > 1) { target_confirms = params[1].get_int(); if (target_confirms < 1) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); } int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1; Array transactions; for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++) { CWalletTx tx = (*it).second; if (depth == -1 || tx.GetDepthInMainChain() < depth) ListTransactions(tx, "*", 0, true, transactions); } uint256 lastblock; if (target_confirms == 1) { lastblock = hashBestChain; } else { int target_height = pindexBest->nHeight + 1 - target_confirms; CBlockIndex *block; for (block = pindexBest; block && block->nHeight > target_height; block = block->pprev) { } lastblock = block ? block->GetBlockHash() : 0; } Object ret; ret.push_back(Pair("transactions", transactions)); ret.push_back(Pair("lastblock", lastblock.GetHex())); return ret; }
QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) { AssertLockHeld(cs_main); if (!IsFinalTx(wtx, nBestHeight + 1)) { if (wtx.nLockTime < LOCKTIME_THRESHOLD) return tr("Open for %n more block(s)", "", wtx.nLockTime - nBestHeight); else return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime)); } else { int signatures = wtx.GetTransactionLockSignatures(); QString strUsingIX = ""; if(signatures >= 0){ if(signatures >= INSTANTX_SIGNATURES_REQUIRED){ int nDepth = wtx.GetDepthInMainChain(); if (nDepth < 0) return tr("conflicted"); else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) return tr("%1/offline (verified via instantx)").arg(nDepth); else if (nDepth < 10) return tr("%1/confirmed (verified via instantx)").arg(nDepth); else return tr("%1 confirmations (verified via instantx)").arg(nDepth); } else { if(!wtx.IsTransactionLockTimedOut()){ int nDepth = wtx.GetDepthInMainChain(); if (nDepth < 0) return tr("conflicted"); else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) return tr("%1/offline (InstantX verification in progress - %2 of %3 signatures)").arg(nDepth).arg(signatures).arg(INSTANTX_SIGNATURES_TOTAL); else if (nDepth < 10) return tr("%1/confirmed (InstantX verification in progress - %2 of %3 signatures )").arg(nDepth).arg(signatures).arg(INSTANTX_SIGNATURES_TOTAL); else return tr("%1 confirmations (InstantX verification in progress - %2 of %3 signatures)").arg(nDepth).arg(signatures).arg(INSTANTX_SIGNATURES_TOTAL); } else { int nDepth = wtx.GetDepthInMainChain(); if (nDepth < 0) return tr("conflicted"); else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) return tr("%1/offline (InstantX verification failed)").arg(nDepth); else if (nDepth < 10) return tr("%1/confirmed (InstantX verification failed)").arg(nDepth); else return tr("%1 confirmations").arg(nDepth); } } } else { int nDepth = wtx.GetDepthInMainChain(); if (nDepth < 0) return tr("conflicted"); else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0) return tr("%1/offline").arg(nDepth); else if (nDepth < 10) return tr("%1/unconfirmed").arg(nDepth); else return tr("%1 confirmations").arg(nDepth); } } }
QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) { QString strHTML; { LOCK(wallet->cs_wallet); strHTML.reserve(4000); strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>"; int64 nTime = wtx.GetTxTime(); int64 nCredit = wtx.GetCredit(wtx.GetDepthInMainChain()); int64 nDebit = wtx.GetDebit(wtx.GetDepthInMainChain()); int64 nNet = nCredit - nDebit; 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()) { strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>"; } else if (!wtx.mapValue["from"].empty()) { // Online transaction if (!wtx.mapValue["from"].empty()) strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>"; } else { // Offline transaction if (nNet > 0) { // Credit BOOST_FOREACH(const CTxOut& txout, wtx.vout) { if (wallet->IsMine(txout)) { CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { if (wallet->mapAddressBook.count(address)) { strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>"; strHTML += "<b>" + tr("To") + ":</b> "; strHTML += GUIUtil::HtmlEscape(CFreicoinAddress(address).ToString()); if (!wallet->mapAddressBook[address].empty()) strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")"; else strHTML += " (" + tr("own address") + ")"; strHTML += "<br>"; } } break; } } } } // // To // if (!wtx.mapValue["to"].empty()) { // Online transaction std::string strAddress = wtx.mapValue["to"]; strHTML += "<b>" + tr("To") + ":</b> "; CTxDestination dest = CFreicoinAddress(strAddress).Get(); if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " "; strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>"; } // // Amount // if (wtx.IsCoinBase() && nCredit == 0) { // // Coinbase // int64 nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) nUnmatured += wallet->GetCredit(wtx,txout,wtx.GetDepthInMainChain()); strHTML += "<b>" + tr("Credit") + ":</b> "; if (wtx.IsInMainChain()) strHTML += FreicoinUnits::formatWithUnit(FreicoinUnits::FRC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; else strHTML += "(" + tr("not accepted") + ")"; strHTML += "<br>"; }