def run(self): network = Network.get_instance() if not network: self.notify_offline() return for i, p in enumerate(self.DERIVATION_PATHS): if self.aborting: return k = keystore.from_seed(self.seed, '', derivation=p, seed_type=self.seed_type) p_safe = p.replace('/', '_').replace("'", 'h') storage_path = os.path.join( tempfile.gettempdir(), p_safe + '_' + random.getrandbits(32).to_bytes(4, 'big').hex()[:8] + "_not_saved_") tmp_storage = WalletStorage(storage_path, in_memory_only=True) tmp_storage.put('seed_type', self.seed_type) tmp_storage.put('keystore', k.dump()) wallet = Standard_Wallet(tmp_storage) try: wallet.start_threads(network) wallet.synchronize() wallet.print_error("Scanning", p) synched = False for ctr in range(25): try: wallet.wait_until_synchronized(timeout=1.0) synched = True except TimeoutException: wallet.print_error(f'timeout try {ctr+1}/25') if self.aborting: return if not synched: wallet.print_error("Timeout on", p) self.notify_timedout(i) continue while network.is_connecting(): time.sleep(0.1) if self.aborting: return num_tx = len(wallet.get_history()) self.update_table_cb(i, str(num_tx)) finally: wallet.clear_history() wallet.stop_threads()
class LoadRWallet(MessageBoxMixin, PrintError, QWidget): def __init__(self, parent, plugin, wallet_name, recipient_wallet=None, time=None, password=None): QWidget.__init__(self, parent) self.password = password self.wallet = parent.wallet self.utxos = self.wallet.get_spendable_coins(None, parent.config) random.shuffle(self.utxos) # randomize the coins' order for x in range(10): name = 'tmp_wo_wallet' + ''.join( random.choices(string.ascii_letters + string.digits, k=10)) self.file = os.path.join(tempfile.gettempdir(), name) if not os.path.exists(self.file): break else: raise RuntimeError( 'Could not find a unique temp file in tmp directory', tempfile.gettempdir()) self.tmp_pass = ''.join( random.choices(string.ascii_uppercase + string.digits, k=10)) self.storage = None self.recipient_wallet = None self.keystore = None self.plugin = plugin self.network = parent.network self.wallet_name = wallet_name self.keystore = None vbox = QVBoxLayout() self.setLayout(vbox) self.local_xpub = self.wallet.get_master_public_keys() l = QLabel( _("Master Public Key") + _(" of this wallet (used to generate all of your addresses): ")) l2 = QLabel((self.local_xpub and self.local_xpub[0]) or _( "This wallet is <b>non-deterministic</b> and cannot be used as a transfer destination." )) vbox.addWidget(l) vbox.addWidget(l2) l2.setTextInteractionFlags(Qt.TextSelectableByMouse) l = QLabel( _("Master Public Key") + " of the wallet you want to transfer your funds to:") disabled = False if self.wallet.is_watching_only(): l.setText( _("This wallet is <b>watching-only</b> and cannot be used as a transfer source." )) disabled = True elif any([ isinstance(k, Hardware_KeyStore) for k in self.wallet.get_keystores() ]): l.setText( _("This wallet is a <b>hardware wallet</b> and cannot be used as a transfer source." )) disabled = True vbox.addWidget(l) self.xpubkey = None self.xpubkey_wid = QLineEdit() self.xpubkey_wid.textEdited.connect(self.transfer_changed) self.xpubkey_wid.setDisabled(disabled) vbox.addWidget(self.xpubkey_wid) l = QLabel(_("How long the transfer should take (in whole hours): ")) vbox.addWidget(l) l.setDisabled(disabled) self.time_e = QLineEdit() self.time_e.setMaximumWidth(70) self.time_e.textEdited.connect(self.transfer_changed) self.time_e.setDisabled(disabled) hbox = QHBoxLayout() vbox.addLayout(hbox) hbox.addWidget(self.time_e) self.speed = QLabel() hbox.addWidget(self.speed) hbox.addStretch(1) self.transfer_button = QPushButton(_("Transfer")) self.transfer_button.clicked.connect(self.transfer) vbox.addWidget(self.transfer_button) self.transfer_button.setDisabled(True) vbox.addStretch(1) def filter(self, *args): ''' This is here because searchable_list must define a filter method ''' def showEvent(self, e): super().showEvent(e) if not self.network and self.isEnabled(): self.show_warning( _("The Inter-Wallet Transfer plugin cannot function in offline mode. Restart Electron Cash in online mode to proceed." )) self.setDisabled(True) @staticmethod def delete_temp_wallet_file(file): ''' deletes the wallet file ''' if file and os.path.exists(file): try: os.remove(file) print_error("[InterWalletTransfer] Removed temp file", file) except Exception as e: print_error("[InterWalletTransfer] Failed to remove temp file", file, "error: ", repr(e)) def transfer(self): self.show_message( _("You should not use either wallet during the transfer. Leave Electron Cash active. " "The plugin ceases operation and will have to be re-activated if Electron Cash " "is stopped during the operation.")) self.storage = WalletStorage(self.file) self.storage.set_password(self.tmp_pass, encrypt=True) self.storage.put('keystore', self.keystore.dump()) self.recipient_wallet = Standard_Wallet(self.storage) self.recipient_wallet.start_threads(self.network) # comment the below out if you want to disable auto-clean of temp file # otherwise the temp file will be auto-cleaned on app exit or # on the recepient_wallet object's destruction (when refct drops to 0) Weak.finalize(self.recipient_wallet, self.delete_temp_wallet_file, self.file) self.plugin.switch_to(Transfer, self.wallet_name, self.recipient_wallet, float(self.time_e.text()), self.password) def transfer_changed(self): try: assert float(self.time_e.text()) > 0 self.xpubkey = self.xpubkey_wid.text() self.keystore = keystore.from_master_key(self.xpubkey) except: self.speed.setText('') self.transfer_button.setDisabled(True) else: self.transfer_button.setDisabled(False) v = len(self.utxos) / float(self.time_e.text()) self.speed.setText('{0:.2f}'.format(v) + ' tx/h on average')
class NewBatchDialog(QDialog, MessageBoxMixin, PrintError): settings_updated_signal = pyqtSignal() def __init__(self, parent, plugin, wallet_name, password=None): QDialog.__init__(self, parent) self.main_window = parent self.password = password self.wallet = parent.wallet self.plugin = plugin self.network = parent.network self.wallet_name = wallet_name self.batch_label = "BitcoinBiletoj1" self.template_file = '' self.working_directory = self.wallet.storage.get("bileto_path") if self.working_directory: if not os.path.exists(self.working_directory): self.working_directory = None self.number = 0 self.times = 1 self.public_key = '' for x in range(10): name = 'tmp_wo_wallet' + ''.join( random.choices(string.ascii_letters + string.digits, k=10)) self.file = os.path.join(tempfile.gettempdir(), name) if not os.path.exists(self.file): break else: raise RuntimeError( 'Could not find a unique temp file in tmp directory', tempfile.gettempdir()) self.tmp_pass = ''.join( random.choices(string.ascii_uppercase + string.digits, k=10)) from electroncash import mnemonic seed = mnemonic.Mnemonic('en').make_seed('standard') self.keystore = keystore.from_seed(seed, self.tmp_pass, False) self.storage = WalletStorage(self.file) self.storage.set_password(self.tmp_pass, encrypt=True) self.storage.put('keystore', self.keystore.dump()) self.recipient_wallet = Standard_Wallet(self.storage) self.recipient_wallet.start_threads(self.network) Weak.finalize(self.recipient_wallet, self.delete_temp_wallet_file, self.file) vbox = QVBoxLayout() self.setLayout(vbox) hbox = QHBoxLayout() vbox.addLayout(hbox) l = QLabel("<b>%s</b>" % (_("Bitcoin Bileto"))) hbox.addStretch(1) hbox.addWidget(l) hbox.addStretch(1) vbox.addWidget(QLabel("Working directory:")) hbox = QHBoxLayout() vbox.addLayout(hbox) self.wd_label = QLabel(self.working_directory) hbox.addWidget(self.wd_label) b = QPushButton("Set") b.clicked.connect(lambda: self.plugin.settings_dialog( self, self.settings_updated_signal)) self.settings_updated_signal.connect(self.on_settings_updated) hbox.addWidget(b) data = "prywatny klucz do portfela" self.qrw_priv = QRCodeWidget(data) self.qrw_add = QRCodeWidget(data) self.batch_label_wid = QLineEdit() self.batch_label_wid.setPlaceholderText( _("Bitcoin biletoj batch label")) self.batch_label_wid.textEdited.connect(self.batch_info_changed) vbox.addWidget(self.batch_label_wid) grid = QGridLayout() vbox.addLayout(grid) self.number_wid = QLineEdit() self.number_wid.setPlaceholderText(_("Number of biletoj")) self.number_wid.textEdited.connect(self.batch_info_changed) self.times_wid = QLineEdit() self.times_wid.textEdited.connect(self.batch_info_changed) self.times_wid.setText("1") hbox = QHBoxLayout() vbox.addLayout(hbox) hbox.addWidget(self.number_wid) #hbox.addWidget(QLabel("x")) #hbox.addWidget(self.times_wid) hbox.addStretch(1) self.times_wid.setMaximumWidth(120) self.number_wid.setMaximumWidth(140) self.only_qrcodes_checkbox = QCheckBox("Only make QR codes.") self.only_qrcodes_checkbox.stateChanged.connect( self.batch_info_changed) self.encrypt_checkbox = QCheckBox("Encrypt Batch.") vbox.addWidget(self.encrypt_checkbox) vbox.addWidget(self.only_qrcodes_checkbox) #b = QPushButton(_("Load .tex template")) #b.clicked.connect(self.load_template) #b.setMaximumWidth(130) #grid.addWidget(b, 0, 0) #self.template_path_label_wid = QLabel('set path') #grid.addWidget(self.template_path_label_wid, 0, 1) self.public_key_wid = QLineEdit() self.public_key_wid.setPlaceholderText( _("Public Key") + _(" for encryption")) self.public_key_wid.textEdited.connect(self.batch_info_changed) #vbox.addWidget(self.public_key_wid) self.b = QPushButton(_("Generate biletoj")) self.b.clicked.connect(self.generate_biletoj) self.prog_bar = QProgressBar() self.prog_bar.setVisible(False) vbox.addWidget(self.b) vbox.addWidget(self.prog_bar) self.b.setDisabled(True) vbox.addStretch(1) def on_settings_updated(self): self.working_directory = self.wallet.storage.get("bileto_path") self.wd_label.setText(self.working_directory) def save_qrcode(self, qrw, name): p = qrw and qrw.grab() filename = os.path.join(self.working_directory, name) if p and not p.isNull(): if filename: print_error("saving") p.save(filename, 'png') def batch_info_changed(self): # string = self.recipient_wallet.get_unused_address().to_ui_string() try: self.batch_label = str(self.batch_label_wid.text()) self.number = int(self.number_wid.text()) self.times = int(self.times_wid.text()) assert self.times > 0 # self.public_key = str(self.public_key_wid.text()) self.public_key = self.wallet.get_pubkey(False, 0) assert os.path.exists(self.working_directory) #if not self.only_qrcodes_checkbox.isChecked(): #assert os.path.isfile(self.template_file) except AssertionError: self.times_wid.setText("1") self.b.setDisabled(True) except: self.b.setDisabled(True) else: self.b.setDisabled(False) def load_template(self): self.template_file = self.main_window.getOpenFileName( "Load Latex template", "*.tex") self.template_path_label_wid.setText(self.template_file) self.batch_info_changed() def generate_biletoj(self): self.b.setDisabled(True) self.b.setText("In progress...") self.prog_bar.setRange(0, self.number) self.prog_bar.setVisible(True) QCoreApplication.processEvents() try: path_to_latex = check_output(["which", "pdflatex"], shell=False).strip() except: path_to_latex = '/Library/Tex/texbin/pdflatex' batch_privs = self.batch_label + '\n' os.mkdir( os.path.join(self.working_directory, self.batch_label + "_qrcodes")) for i in range(self.number): add = self.recipient_wallet.create_new_address() privkey = self.recipient_wallet.export_private_key(add, None) batch_privs += privkey + '\n' self.qrw_priv.number_label.setText(' ' + str(i + 1)) self.qrw_priv.setData(privkey) self.save_qrcode( self.qrw_priv, self.batch_label + "_qrcodes/priv_key_" + str(i + 1) + ".png") self.qrw_add.number_label.setText(' ' + str(i + 1)) self.qrw_priv.setData("bitcoincash:" + add.to_ui_string()) self.save_qrcode( self.qrw_add, self.batch_label + "_qrcodes/address_" + str(i + 1) + ".png") self.prog_bar.setValue(i + 1) if not self.only_qrcodes_checkbox.isChecked(): self.scripts() call(['chmod', 'u+x', "compile.sh"], cwd=self.working_directory, shell=False) call([ "./compile.sh", '-l', self.batch_label, '-n', str(self.number) ], cwd=self.working_directory, shell=False) filename = os.path.join(self.working_directory, self.batch_label + '_encrypted_private_keys') save_private_keys(batch_privs, self.public_key, filename, self.encrypt_checkbox.isChecked()) self.prog_bar.setVisible(False) self.main_window.show_message("Done!") self.b.setDisabled(False) self.b.setText(_("Generate biletoj")) def filter(self, *args): ''' This is here because searchable_list must define a filter method ''' def scripts(self): for name, scr in script_dict.items(): path = os.path.join(self.working_directory, name) if not os.path.isfile(path): with open(path, 'w') as file: file.write(scr) @staticmethod def delete_temp_wallet_file(file): ''' deletes the wallet file ''' if file and os.path.exists(file): try: os.remove(file) print_error("[BitcoinBileto] Removed temp file", file) except Exception as e: print_error("[BitcoinBileto] Failed to remove temp file", file, "error: ", repr(e)) def closeEvent(self, event): #self.plugin.on_create_dialog_closed(self.wallet_name) event.accept()