Mercurial > hg > bitcoin
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; |