electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 0938299e9bf858817d3c391ebcdca3d48d5dd3d4
parent e5b6b05482dffb2d6370dad3f0fd21276fff5747
Author: ThomasV <thomasv@gitorious>
Date:   Mon,  1 Jun 2015 13:02:09 +0200

move payment requests logic to wallet, add basic commands

Diffstat:
Mgui/qt/main_window.py | 60+++++++++++++-----------------------------------------------
Mlib/commands.py | 29+++++++++++++++++++++++++++++
Mlib/wallet.py | 40++++++++++++++++++++++++++++++++++++++++
3 files changed, 82 insertions(+), 47 deletions(-)

diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -666,7 +666,7 @@ class ElectrumWindow(QMainWindow): if not self.receive_list.isItemSelected(item): return addr = str(item.text(2)) - req = self.receive_requests[addr] + req = self.wallet.receive_requests[addr] expires = _('Never') if req.get('expiration') is None else format_time(req['time'] + req['expiration']) amount = req['amount'] message = self.wallet.labels.get(addr, '') @@ -680,8 +680,7 @@ class ElectrumWindow(QMainWindow): def delete_payment_request(self, item): addr = str(item.text(2)) - self.receive_requests.pop(addr) - self.wallet.storage.put('receive_requests2', self.receive_requests) + self.wallet.remove_payment_request(addr) self.update_receive_tab() self.clear_receive_tab() @@ -695,7 +694,7 @@ class ElectrumWindow(QMainWindow): def receive_list_menu(self, position): item = self.receive_list.itemAt(position) addr = str(item.text(2)) - req = self.receive_requests[addr] + req = self.wallet.receive_requests[addr] time, amount = req['time'], req['amount'] message = self.wallet.labels.get(addr, '') URI = util.create_URI(addr, amount, message) @@ -713,35 +712,15 @@ class ElectrumWindow(QMainWindow): if not message and not amount: QMessageBox.warning(self, _('Error'), _('No message or amount'), _('OK')) return - self.receive_requests = self.wallet.storage.get('receive_requests2', {}) - if addr in self.receive_requests: - self.receive_requests[addr]['amount'] = amount - else: - now = int(time.time()) - i = self.expires_combo.currentIndex() - expiration = map(lambda x: x[1], expiration_values)[i] - self.receive_requests[addr] = {'time':now, 'amount':amount, 'expiration':expiration} - - self.wallet.storage.put('receive_requests2', self.receive_requests) - self.wallet.set_label(addr, message) + i = self.expires_combo.currentIndex() + expiration = map(lambda x: x[1], expiration_values)[i] + self.wallet.save_payment_request(addr, amount, message, expiration) self.update_receive_tab() self.update_address_tab() self.save_request_button.setEnabled(False) - def make_payment_request(self, addr): - req = self.receive_requests[addr] - time = req['time'] - amount = req['amount'] - expiration = req['expiration'] - message = self.wallet.labels.get(addr, '') - script = Transaction.pay_script('address', addr).decode('hex') - outputs = [(script, amount)] - key_path = self.config.get('ssl_key_path') - cert_path = self.config.get('ssl_cert_path') - return make_payment_request(outputs, message, time, time + expiration, key_path, cert_path) - def export_payment_request(self, addr): - pr = self.make_payment_request(addr) + pr = self.wallet.make_bip70_request(self.config, addr) name = 'request.bip70' fileName = self.getSaveFileName(_("Select where to save your payment request"), name, "*.bip70") if fileName: @@ -750,14 +729,8 @@ class ElectrumWindow(QMainWindow): self.show_message(_("Request saved successfully")) self.saved = True - def get_receive_address(self): - domain = self.wallet.get_account_addresses(self.current_account, include_change=False) - for addr in domain: - if not self.wallet.history.get(addr) and addr not in self.receive_requests.keys(): - return addr - def new_payment_request(self): - addr = self.get_receive_address() + addr = self.wallet.get_unused_address(self.current_account) if addr is None: if isinstance(self.wallet, Imported_Wallet): self.show_message(_('No more addresses in your wallet.')) @@ -777,14 +750,8 @@ class ElectrumWindow(QMainWindow): self.receive_amount_e.setAmount(None) def clear_receive_tab(self): - self.receive_requests = self.wallet.storage.get('receive_requests2',{}) - domain = self.wallet.get_account_addresses(self.current_account, include_change=False) - for addr in domain: - if not self.wallet.history.get(addr) and addr not in self.receive_requests.keys(): - break - else: - addr = '' - self.receive_address_e.setText(addr) + addr = self.wallet.get_unused_address(self.current_account) + self.receive_address_e.setText(addr if addr else '') self.receive_message_e.setText('') self.receive_amount_e.setAmount(None) self.expires_label.hide() @@ -814,10 +781,9 @@ class ElectrumWindow(QMainWindow): self.new_request_button.setEnabled(True) def update_receive_tab(self): - self.receive_requests = self.wallet.storage.get('receive_requests2',{}) # hide receive tab if no receive requests available - b = len(self.receive_requests) > 0 + b = len(self.wallet.receive_requests) > 0 self.receive_list.setVisible(b) self.receive_requests_label.setVisible(b) if not b: @@ -830,14 +796,14 @@ class ElectrumWindow(QMainWindow): # update the receive address if necessary current_address = self.receive_address_e.text() domain = self.wallet.get_account_addresses(self.current_account, include_change=False) - addr = self.get_receive_address() + addr = self.wallet.get_unused_address(self.current_account) if not current_address in domain and addr: self.set_receive_address(addr) self.new_request_button.setEnabled(addr != current_address) # clear the list and fill it again self.receive_list.clear() - for address, req in self.receive_requests.viewitems(): + for address, req in self.wallet.receive_requests.viewitems(): timestamp, amount = req['time'], req['amount'] expiration = req.get('expiration', None) message = self.wallet.labels.get(address, '') diff --git a/lib/commands.py b/lib/commands.py @@ -506,7 +506,34 @@ class Commands: """Decrypt a message encrypted with a public key.""" return self.wallet.decrypt_message(pubkey, encrypted, self.password) + @command('w') + def listrequests(self): + """List the payment requests you made""" + out = [] + for addr, v in self.wallet.receive_requests.items(): + out.append({ + 'address': addr, + 'amount': format_satoshis(v.get('amount')), + 'time': v.get('time'), + 'reason': self.wallet.get_label(addr)[0], + 'expiration': v.get('expiration'), + }) + return out + @command('w') + def addrequest(self, amount, reason='', expiration=60*60): + """Create a payment request""" + addr = self.wallet.get_unused_address(None) + if addr is None: + return False + amount = int(Decimal(amount)*COIN) + self.wallet.save_payment_request(addr, amount, reason, expiration) + return addr + + @command('w') + def removerequest(self, address): + """Remove a payment request""" + return self.wallet.remove_payment_request(address) param_descriptions = { 'privkey': 'Private key. Type \'?\' to get a prompt.', @@ -548,6 +575,8 @@ command_options = { 'unsigned': ("-u", "--unsigned", "Do not sign transaction"), 'domain': ("-D", "--domain", "List of addresses"), 'account': (None, "--account", "Account"), + 'reason': (None, "--reason", "Description of the request"), + 'expiration': (None, "--expiration", "Time in seconds"), } diff --git a/lib/wallet.py b/lib/wallet.py @@ -164,6 +164,9 @@ class Abstract_Wallet(object): self.load_accounts() self.load_transactions() + # load requests + self.receive_requests = self.storage.get('receive_requests2', {}) + # spv self.verifier = None # Transactions pending verification. Each value is the transaction height. Access with self.lock. @@ -1221,6 +1224,43 @@ class Abstract_Wallet(object): def can_change_password(self): return not self.is_watching_only() + def get_unused_address(self, account): + # fixme: use slots from expired requests + domain = self.get_account_addresses(account, include_change=False) + for addr in domain: + if not self.history.get(addr) and addr not in self.receive_requests.keys(): + return addr + + def remove_payment_request(self, addr): + if addr not in self.receive_requests: + return False + self.receive_requests.pop(addr) + self.storage.put('receive_requests2', self.receive_requests) + return True + + def save_payment_request(self, addr, amount, message, expiration): + self.set_label(addr, message) + if addr in self.receive_requests: + self.receive_requests[addr]['amount'] = amount + else: + now = int(time.time()) + self.receive_requests[addr] = {'time':now, 'amount':amount, 'expiration':expiration} + self.storage.put('receive_requests2', self.receive_requests, True) + + def make_bip70_request(self, config, addr): + from paymentrequest import make_payment_request + req = self.receive_requests[addr] + time = req['time'] + amount = req['amount'] + expiration = req['expiration'] + message = self.labels.get(addr, '') + script = Transaction.pay_script('address', addr).decode('hex') + outputs = [(script, amount)] + key_path = config.get('ssl_key_path') + cert_path = config.get('ssl_cert_path') + return make_payment_request(outputs, message, time, time + expiration, key_path, cert_path) + + class Imported_Wallet(Abstract_Wallet): wallet_type = 'imported'