rendered paste bodyIndex: rpc.cpp===================================================================--- rpc.cpp (revision 117)+++ rpc.cpp (working copy)@@ -342,7 +342,172 @@ return "sent"; } +enum txn_classification+{+ txn_unknown,+ txn_generated,+ txn_credit,+ txn_debit,+}; +static const char *txn_class_str[] = {+ "unknown",+ "generated",+ "credit",+ "debit",+};++struct txnitem+{+ uint160 hash160;+ int64 nAmount;+ int nConf;+ enum txn_classification txnClass;+ txnitem()+ {+ hash160 = 0;+ nAmount = 0;+ nConf = INT_MAX;+ txnClass = txn_unknown;+ }+};++bool txnitem_cmp(const txnitem& a, const txnitem &b)+{+ return a.nConf < b.nConf;+}++Value ListTransactions(int64 nCount, bool fGenerated)+{+ vector<txnitem> tv;+ CRITICAL_BLOCK(cs_mapWallet)+ {+ for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)+ {+ const CWalletTx& wtx = (*it).second;+ int64 nCredit = wtx.GetCredit(true);+ int64 nDebit = wtx.GetDebit();+ int64 nNet = nCredit - nDebit;++ bool gen = wtx.IsCoinBase();+ if (gen) {+ if (!fGenerated)+ continue;+ if (!wtx.IsInMainChain())+ continue;+ }++ int nDepth = wtx.GetDepthInMainChain();++ if (nNet > 0)+ {+ foreach(const CTxOut& txout, wtx.vout)+ {+ uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160();++ if (!txout.IsMine())+ continue;++ txnitem item;+ item.hash160 = hash160;+ item.nAmount = txout.nValue;+ item.nConf = min(item.nConf, nDepth);+ if (gen)+ item.txnClass = txn_generated;+ else+ item.txnClass = txn_credit;++ tv.push_back(item);+ }+ }+ else+ {+ bool fAllFromMe = true;+ foreach(const CTxIn& txin, wtx.vin)+ fAllFromMe = fAllFromMe && txin.IsMine();++ bool fAllToMe = true;+ foreach(const CTxOut& txout, wtx.vout)+ fAllToMe = fAllToMe && txout.IsMine();++ if (fAllFromMe && fAllToMe) // payment to self+ {+ // FIXME+ }+ else if (fAllFromMe) // debit+ {+ int64 nTxFee = nDebit - wtx.GetValueOut();+ for (int nOut = 0; nOut < wtx.vout.size(); nOut++)+ {+ const CTxOut& txout = wtx.vout[nOut];+ if (txout.IsMine())+ continue;++ uint160 hash160;+ ExtractHash160(txout.scriptPubKey, hash160);++ int64 nValue = txout.nValue;+ if (nTxFee > 0)+ {+ nValue += nTxFee;+ nTxFee = 0;+ }++ txnitem item;+ item.hash160 = hash160;+ item.nAmount = nValue;+ item.nConf = min(item.nConf, nDepth);+ item.txnClass = txn_debit;++ tv.push_back(item);+ }+ }+ else // mixed debit txn+ {+ // FIXME+ }+ }+ }+ }++ std::sort(tv.begin(), tv.end(), txnitem_cmp);++ // Reply+ Array ret;+ int64 returned = 0;+ CRITICAL_BLOCK(cs_mapAddressBook)+ {+ foreach(const txnitem& txn, tv)+ {+ if (returned >= nCount)+ break;++ string strAddress = Hash160ToAddress(txn.hash160);+ string strLabel, strClass;+ int64 nAmount = txn.nAmount;+ int nConf = txn.nConf;++ map<string, string>::iterator mi = mapAddressBook.find(strAddress);+ if (mi != mapAddressBook.end())+ strLabel = (*mi).second;++ strClass = txn_class_str[txn.txnClass];++ Object obj;+ obj.push_back(Pair("address", strAddress));+ obj.push_back(Pair("label", strLabel));+ obj.push_back(Pair("class", strClass));+ obj.push_back(Pair("amount", (double)nAmount /(double)COIN));+ obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 :nConf)));+ ret.push_back(obj);++ returned++;+ }+ }++ return ret;+}+ Value listtransactions(const Array& params, bool fHelp) { if (fHelp || params.size() > 2)@@ -357,10 +522,7 @@ if (params.size() > 1) fGenerated = params[1].get_bool(); - Array ret;- //// not finished- ret.push_back("not implemented yet");- return ret;+ return ListTransactions(nCount, fGenerated); } @@ -638,6 +800,7 @@ make_pair("getreceivedbylabel", &getreceivedbylabel), make_pair("listreceivedbyaddress", &listreceivedbyaddress), make_pair("listreceivedbylabel", &listreceivedbylabel),+ make_pair("listtransactions", &listtransactions), }; map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));