comparison src/qt/walletmodel.cpp @ 1187:5c41b03dc484 draft

add sendmany support
author Wladimir J. van der Laan <laanwj@gmail.com>
date Sat, 16 Jul 2011 19:01:05 +0200
parents b1a09eca2755
children bc546d3c46d2
comparison
equal deleted inserted replaced
1186:69323e942d0e 1187:5c41b03dc484
5 #include "transactiontablemodel.h" 5 #include "transactiontablemodel.h"
6 6
7 #include "headers.h" 7 #include "headers.h"
8 8
9 #include <QTimer> 9 #include <QTimer>
10 #include <QSet>
10 11
11 WalletModel::WalletModel(CWallet *wallet, QObject *parent) : 12 WalletModel::WalletModel(CWallet *wallet, QObject *parent) :
12 QObject(parent), wallet(wallet), optionsModel(0), addressTableModel(0), 13 QObject(parent), wallet(wallet), optionsModel(0), addressTableModel(0),
13 transactionTableModel(0) 14 transactionTableModel(0)
14 { 15 {
52 emit numTransactionsChanged(getNumTransactions()); 53 emit numTransactionsChanged(getNumTransactions());
53 54
54 addressTableModel->update(); 55 addressTableModel->update();
55 } 56 }
56 57
57 WalletModel::StatusCode WalletModel::sendCoins(const QString &payTo, qint64 payAmount, const QString &addToAddressBookAs) 58 bool WalletModel::validateAddress(const QString &address)
58 { 59 {
59 uint160 hash160 = 0; 60 uint160 hash160 = 0;
60 bool valid = false;
61 61
62 if(!AddressToHash160(payTo.toUtf8().constData(), hash160)) 62 return AddressToHash160(address.toStdString(), hash160);
63 }
64
65 WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipient> &recipients)
66 {
67 qint64 total = 0;
68 QSet<QString> setAddress;
69 QString hex;
70
71 if(recipients.empty())
63 { 72 {
64 return InvalidAddress; 73 return OK;
65 } 74 }
66 75
67 if(payAmount <= 0) 76 // Pre-check input data for validity
77 foreach(const SendCoinsRecipient &rcp, recipients)
68 { 78 {
69 return InvalidAmount; 79 uint160 hash160 = 0;
80
81 if(!AddressToHash160(rcp.address.toUtf8().constData(), hash160))
82 {
83 return InvalidAddress;
84 }
85 setAddress.insert(rcp.address);
86
87 if(rcp.amount <= 0)
88 {
89 return InvalidAmount;
90 }
91 total += rcp.amount;
70 } 92 }
71 93
72 if(payAmount > getBalance()) 94 if(recipients.size() > setAddress.size())
95 {
96 return DuplicateAddress;
97 }
98
99 if(total > getBalance())
73 { 100 {
74 return AmountExceedsBalance; 101 return AmountExceedsBalance;
75 } 102 }
76 103
77 if((payAmount + nTransactionFee) > getBalance()) 104 if((total + nTransactionFee) > getBalance())
78 { 105 {
79 return AmountWithFeeExceedsBalance; 106 return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee);
80 } 107 }
81 108
82 CRITICAL_BLOCK(cs_main) 109 CRITICAL_BLOCK(cs_main)
110 CRITICAL_BLOCK(wallet->cs_mapWallet)
83 { 111 {
84 // Send to bitcoin address 112 // Sendmany
113 std::vector<std::pair<CScript, int64> > vecSend;
114 foreach(const SendCoinsRecipient &rcp, recipients)
115 {
116 CScript scriptPubKey;
117 scriptPubKey.SetBitcoinAddress(rcp.address.toStdString());
118 vecSend.push_back(make_pair(scriptPubKey, rcp.amount));
119 }
120
85 CWalletTx wtx; 121 CWalletTx wtx;
86 CScript scriptPubKey; 122 CReserveKey keyChange(wallet);
87 scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; 123 int64 nFeeRequired = 0;
124 bool fCreated = wallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired);
88 125
89 std::string strError = wallet->SendMoney(scriptPubKey, payAmount, wtx, true); 126 if(!fCreated)
90 if (strError == "")
91 { 127 {
92 // OK 128 if((total + nFeeRequired) > wallet->GetBalance())
129 {
130 return SendCoinsReturn(AmountWithFeeExceedsBalance, nFeeRequired);
131 }
132 return TransactionCreationFailed;
93 } 133 }
94 else if (strError == "ABORTED") 134 if(!ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString(), NULL))
95 { 135 {
96 return Aborted; 136 return Aborted;
97 } 137 }
98 else 138 if(!wallet->CommitTransaction(wtx, keyChange))
99 { 139 {
100 emit error(tr("Sending..."), QString::fromStdString(strError)); 140 return TransactionCommitFailed;
101 return MiscError; 141 }
142 hex = QString::fromStdString(wtx.GetHash().GetHex());
143 }
144
145 // Add addresses that we've sent to to the address book
146 foreach(const SendCoinsRecipient &rcp, recipients)
147 {
148 std::string strAddress = rcp.address.toStdString();
149 CRITICAL_BLOCK(wallet->cs_mapAddressBook)
150 {
151 if (!wallet->mapAddressBook.count(strAddress))
152 wallet->SetAddressBookName(strAddress, rcp.label.toStdString());
102 } 153 }
103 } 154 }
104 155
105 // Add addresses that we've sent to to the address book 156 return SendCoinsReturn(OK, 0, hex);
106 std::string strAddress = payTo.toStdString();
107 CRITICAL_BLOCK(wallet->cs_mapAddressBook)
108 {
109 if (!wallet->mapAddressBook.count(strAddress))
110 wallet->SetAddressBookName(strAddress, addToAddressBookAs.toStdString());
111 }
112
113 return OK;
114 } 157 }
115 158
116 OptionsModel *WalletModel::getOptionsModel() 159 OptionsModel *WalletModel::getOptionsModel()
117 { 160 {
118 return optionsModel; 161 return optionsModel;