3 #include "transactionrecord.h"
7 /* Return positive answer if transaction should be shown in list.
9 bool TransactionRecord::showTransaction(const CWalletTx &wtx)
13 // Don't show generated coin until confirmed by at least one block after it
14 // so we don't get the user's hopes up until it looks like it's probably accepted.
16 // It is not an error when generated blocks are not accepted. By design,
17 // some percentage of blocks, like 10% or more, will end up not accepted.
18 // This is the normal mechanism by which the network copes with latency.
20 // We display regular transactions right away before any confirmation
21 // because they can always get into some block eventually. Generated coins
22 // are special because if their block is not accepted, they are not valid.
24 if (wtx.GetDepthInMainChain() < 2)
33 * Decompose CWallet transaction to model transaction records.
35 QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx)
37 QList<TransactionRecord> parts;
38 qint64 nTime = wtx.nTimeDisplayed = wtx.GetTxTime();
39 qint64 nCredit = wtx.GetCredit(true);
40 qint64 nDebit = wtx.GetDebit();
41 qint64 nNet = nCredit - nDebit;
42 uint256 hash = wtx.GetHash();
43 std::map<std::string, std::string> mapValue = wtx.mapValue;
45 if (showTransaction(wtx))
47 if (nNet > 0 || wtx.IsCoinBase())
52 TransactionRecord sub(hash, nTime);
59 sub.type = TransactionRecord::Generated;
63 qint64 nUnmatured = 0;
64 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
65 nUnmatured += wallet->GetCredit(txout);
66 sub.credit = nUnmatured;
69 else if (!mapValue["from"].empty() || !mapValue["message"].empty())
71 // Received by IP connection
72 sub.type = TransactionRecord::RecvFromIP;
73 if (!mapValue["from"].empty())
74 sub.address = mapValue["from"];
78 // Received by Bitcoin Address
79 sub.type = TransactionRecord::RecvWithAddress;
80 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
82 if(wallet->IsMine(txout))
84 CBitcoinAddress address;
85 if (ExtractAddress(txout.scriptPubKey, wallet, address))
87 sub.address = address.ToString();
97 bool fAllFromMe = true;
98 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
99 fAllFromMe = fAllFromMe && wallet->IsMine(txin);
101 bool fAllToMe = true;
102 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
103 fAllToMe = fAllToMe && wallet->IsMine(txout);
105 if (fAllFromMe && fAllToMe)
108 qint64 nChange = wtx.GetChange();
110 parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "",
111 -(nDebit - nChange), nCredit - nChange));
118 qint64 nTxFee = nDebit - wtx.GetValueOut();
120 for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
122 const CTxOut& txout = wtx.vout[nOut];
123 TransactionRecord sub(hash, nTime);
124 sub.idx = parts.size();
126 if(wallet->IsMine(txout))
128 // Ignore parts sent to self, as this is usually the change
129 // from a transaction sent back to our own address.
132 else if(!mapValue["to"].empty())
135 sub.type = TransactionRecord::SendToIP;
136 sub.address = mapValue["to"];
140 // Sent to Bitcoin Address
141 sub.type = TransactionRecord::SendToAddress;
142 CBitcoinAddress address;
143 if (ExtractAddress(txout.scriptPubKey, 0, address))
145 sub.address = address.ToString();
149 qint64 nValue = txout.nValue;
150 /* Add fee to first output */
164 // Mixed debit transaction, can't break down payees
166 bool fAllMine = true;
167 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
168 fAllMine = fAllMine && wallet->IsMine(txout);
169 BOOST_FOREACH(const CTxIn& txin, wtx.vin)
170 fAllMine = fAllMine && wallet->IsMine(txin);
172 parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0));
180 void TransactionRecord::updateStatus(const CWalletTx &wtx)
182 // Determine transaction status
184 // Find the block the tx is in
185 CBlockIndex* pindex = NULL;
186 std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock);
187 if (mi != mapBlockIndex.end())
188 pindex = (*mi).second;
190 // Sort order, unrecorded transactions sort to the top
191 status.sortKey = strprintf("%010d-%01d-%010u-%03d",
192 (pindex ? pindex->nHeight : std::numeric_limits<int>::max()),
193 (wtx.IsCoinBase() ? 1 : 0),
196 status.confirmed = wtx.IsConfirmed();
197 status.depth = wtx.GetDepthInMainChain();
198 status.cur_num_blocks = nBestHeight;
202 if (wtx.nLockTime < LOCKTIME_THRESHOLD)
204 status.status = TransactionStatus::OpenUntilBlock;
205 status.open_for = nBestHeight - wtx.nLockTime;
209 status.status = TransactionStatus::OpenUntilDate;
210 status.open_for = wtx.nLockTime;
215 if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
217 status.status = TransactionStatus::Offline;
219 else if (status.depth < NumConfirmations)
221 status.status = TransactionStatus::Unconfirmed;
225 status.status = TransactionStatus::HaveConfirmations;
229 // For generated transactions, determine maturity
230 if(type == TransactionRecord::Generated)
232 qint64 nCredit = wtx.GetCredit(true);
235 status.maturity = TransactionStatus::Immature;
237 if (wtx.IsInMainChain())
239 status.matures_in = wtx.GetBlocksToMaturity();
241 // Check if the block was requested by anyone
242 if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
243 status.maturity = TransactionStatus::MaturesWarning;
247 status.maturity = TransactionStatus::NotAccepted;
252 status.maturity = TransactionStatus::Mature;
257 bool TransactionRecord::statusUpdateNeeded()
259 return status.cur_num_blocks != nBestHeight;
262 std::string TransactionRecord::getTxID()
264 return hash.ToString() + strprintf("-%03d", idx);