git / moonbite-core / src/wallet/txrecord.cpp · raw
#include <wallet/txrecord.h>#include <wallet/wallet.h>#include <wallet/txrecord.h>#include <wallet/wallet.h>#include <chain.h>#include <core_io.h>#include <interfaces/chain.h>#include <key_io.h>#include <util/check.h>#include <chrono>using namespace std::chrono;bool WalletTxRecord::UpdateStatusIfNeeded(const uint256& block_hash){ assert(!block_hash.IsNull()); // Check if update is needed if (status.m_cur_block_hash == block_hash && !status.needsUpdate) { return false; } // Try locking the wallet TRY_LOCK(m_pWallet->cs_wallet, locked_wallet); if (!locked_wallet) { return false; } const int last_block_height = m_pWallet->GetLastBlockHeight(); int64_t block_time = -1; CHECK_NONFATAL(m_pWallet->chain().findBlock(m_pWallet->GetLastBlockHash(), interfaces::FoundBlock().time(block_time))); // Sort order, unrecorded transactions sort to the top // Sub-components sorted with standard outputs first, MWEB outputs second, then MWEB pegouts third. std::string idx = strprintf("0%03d", 0); if (index) { if (index->type() == typeid(int)) { idx = strprintf("0%03d", boost::get<int>(*index)); } else if (index->type() == typeid(mw::Hash)) { idx = "1" + boost::get<mw::Hash>(*index).ToHex(); } else { const PegoutIndex& pegout_idx = boost::get<PegoutIndex>(*index); idx = "2" + pegout_idx.kernel_id.ToHex() + strprintf("%03d", pegout_idx.pos); } } int block_height = m_wtx->m_confirm.block_height > 0 ? m_wtx->m_confirm.block_height : std::numeric_limits<int>::max(); int blocks_to_maturity = m_wtx->GetBlocksToMaturity(); status.sortKey = strprintf("%010d-%01d-%010u-%s", block_height, m_wtx->IsCoinBase() ? 1 : 0, m_wtx->nTimeReceived, idx); status.countsForBalance = m_wtx->IsTrusted() && !(blocks_to_maturity > 0); status.depth = m_wtx->GetDepthInMainChain(); status.m_cur_block_hash = block_hash; if (m_wtx->IsInMainChain()) { status.matures_in = blocks_to_maturity; } const int64_t time_since_epoch = (int64_t)duration_cast<seconds>(system_clock::now().time_since_epoch()).count(); const bool up_to_date = (time_since_epoch - block_time < MAX_BLOCK_TIME_GAP); if (up_to_date && !m_wtx->IsFinal()) { if (m_wtx->tx->nLockTime < LOCKTIME_THRESHOLD) { status.status = WalletTxStatus::OpenUntilBlock; status.open_for = m_wtx->tx->nLockTime - last_block_height; } else { status.status = WalletTxStatus::OpenUntilDate; status.open_for = m_wtx->tx->nLockTime; } } // For generated transactions, determine maturity else if (type == WalletTxRecord::Type::Generated || m_wtx->IsHogEx()) { if (blocks_to_maturity > 0) { status.status = WalletTxStatus::Immature; if (!m_wtx->IsInMainChain()) { status.status = WalletTxStatus::NotAccepted; } } else { status.status = WalletTxStatus::Confirmed; } } else { if (status.depth < 0) { status.status = WalletTxStatus::Conflicted; } else if (status.depth == 0) { status.status = WalletTxStatus::Unconfirmed; if (m_wtx->isAbandoned()) status.status = WalletTxStatus::Abandoned; } else if (status.depth < RecommendedNumConfirmations) { status.status = WalletTxStatus::Confirming; } else { status.status = WalletTxStatus::Confirmed; } } status.needsUpdate = false; return true;}const uint256& WalletTxRecord::GetTxHash() const{ assert(m_wtx != nullptr); return m_wtx->GetHash();}std::string WalletTxRecord::GetTxString() const{ assert(m_wtx != nullptr); if (m_wtx->IsPartialMWEB()) { if (m_wtx->mweb_wtx_info->received_coin) { const mw::Coin& received_coin = *m_wtx->mweb_wtx_info->received_coin; return strprintf("MWEB Output(ID=%s, amount=%d)", received_coin.output_id.ToHex(), received_coin.amount); } else if (m_wtx->mweb_wtx_info->spent_input) { return strprintf("MWEB Input(ID=%s)\n", m_wtx->mweb_wtx_info->spent_input->ToHex()); } } return m_wtx->tx->ToString();}int64_t WalletTxRecord::GetTxTime() const{ assert(m_wtx != nullptr); return m_wtx->GetTxTime();}std::string WalletTxRecord::GetComponentIndex() const{ std::string idx; if (this->index) { if (this->index->type() == typeid(int)) { idx = std::to_string(boost::get<int>(*index)); } else if (index->type() == typeid(mw::Hash)) { idx = "MWEB Output (" + boost::get<mw::Hash>(*index).ToHex() + ")"; } else { const PegoutIndex& pegout_idx = boost::get<PegoutIndex>(*index); idx = "Pegout (" + pegout_idx.kernel_id.ToHex() + ":" + std::to_string(pegout_idx.pos) + ")"; } } return idx;}std::string WalletTxRecord::GetType() const{ switch (this->type) { case Other: return "Other"; case Generated: return "Generated"; case SendToAddress: return "SendToAddress"; case SendToOther: return "SendToOther"; case RecvWithAddress: return "RecvWithAddress"; case RecvFromOther: return "RecvFromOther"; case SendToSelf: return "SendToSelf"; } assert(false);}UniValue WalletTxRecord::ToUniValue() const{ UniValue entry(UniValue::VOBJ); entry.pushKV("type", GetType()); entry.pushKV("amount", ValueFromAmount(GetAmount())); entry.pushKV("net", ValueFromAmount(GetNet())); CTxDestination destination = DecodeDestination(this->address); if (m_wtx->IsFromMe(ISMINE_WATCH_ONLY) || (IsValidDestination(destination) && (m_pWallet->IsMine(destination) & ISMINE_WATCH_ONLY))) { entry.pushKV("involvesWatchonly", true); } if (IsValidDestination(destination)) { const auto* address_book_entry = m_pWallet->FindAddressBookEntry(destination); if (address_book_entry) { entry.pushKV("label", address_book_entry->GetLabel()); } } if (!this->address.empty()) { entry.pushKV("address", this->address); } if (this->index) { if (this->index->type() == typeid(int)) { entry.pushKV("vout", boost::get<int>(*this->index)); } else if (this->index->type() == typeid(mw::Hash)) { entry.pushKV("mweb_out", boost::get<mw::Hash>(*this->index).ToHex()); } else { const PegoutIndex& pegout_idx = boost::get<PegoutIndex>(*index); entry.pushKV("pegout", pegout_idx.kernel_id.ToHex() + ":" + std::to_string(pegout_idx.pos)); } } if (this->debit > 0) { entry.pushKV("fee", ValueFromAmount(-this->fee)); entry.pushKV("abandoned", m_wtx->isAbandoned()); } return entry;}