def submit_proposal(self, proposal_name, save=True): """Submit the proposal for proposal_name.""" proposal = self.get_proposal(proposal_name) if not proposal.fee_txid: raise Exception('Proposal has no fee transaction') if proposal.submitted: raise Exception('Proposal has already been submitted') if not self.wallet.network: raise Exception('Not connected') confirmations, _ = self.wallet.get_confirmations(proposal.fee_txid) if confirmations < BUDGET_FEE_CONFIRMATIONS: raise Exception('Collateral requires at least %d confirmations' % BUDGET_FEE_CONFIRMATIONS) payments_count = proposal.get_payments_count() payment_amount = format_satoshis_plain(proposal.payment_amount) params = [ proposal.proposal_name, proposal.proposal_url, payments_count, proposal.start_block, proposal.address, payment_amount, proposal.fee_txid ] errmsg = [] callback = lambda r: self.submit_proposal_callback( proposal.proposal_name, errmsg, r, save) self.network_event.clear() self.wallet.network.send([('masternode.budget.submit', params)], callback) self.network_event.wait() if errmsg: errmsg = errmsg[0] return (errmsg, proposal.submitted)
def fiat_to_btc(self, fiat_amount): if not fiat_amount: return '' rate = self.fx.exchange_rate() if not rate: return '' satoshis = int(pow(10, 8) * Decimal(fiat_amount) / Decimal(rate)) return format_satoshis_plain(satoshis, self.decimal_point())
def get_max_amount(self): inputs = self.wallet.get_spendable_coins(None, self.electrum_config) addr = str( self.send_screen.screen.address) or self.wallet.dummy_address() outputs = [(TYPE_ADDRESS, addr, '!')] tx = self.wallet.make_unsigned_transaction(inputs, outputs, self.electrum_config) amount = tx.output_value() return format_satoshis_plain(amount, self.decimal_point())
def data(self, index, role = Qt.DisplayRole): if not index.isValid(): return None if role not in [Qt.EditRole, Qt.DisplayRole, Qt.ToolTipRole, Qt.FontRole]: return None data = None p = self.proposals[index.row()] c = index.column() if c == self.NAME: data = p.proposal_name elif c == self.URL: data = p.proposal_url elif c == self.YES_COUNT: data = p.yes_count elif c == self.NO_COUNT: data = p.no_count elif c == self.START_BLOCK: data = p.start_block if role == Qt.FontRole: data = util.MONOSPACE_FONT elif c == self.END_BLOCK: data = p.end_block if role == Qt.FontRole: data = util.MONOSPACE_FONT elif c == self.AMOUNT: data = p.payment_amount if role in [Qt.DisplayRole, Qt.EditRole]: data = format_satoshis_plain(data) elif c == self.ADDRESS: data = p.address if role == Qt.FontRole: data = util.MONOSPACE_FONT elif c == self.TXID: data = p.fee_txid if role == Qt.FontRole: data = util.MONOSPACE_FONT return QVariant(data)
def setAmount(self, amount): if amount is None: self.setText(" ") # Space forces repaint in case units changed else: self.setText(format_satoshis_plain(amount, self.decimal_point()))
def sign_transaction(self, tx, password): if tx.is_complete(): return client = self.get_client() self.signing = True inputs = [] inputsPaths = [] pubKeys = [] chipInputs = [] redeemScripts = [] signatures = [] preparedTrustedInputs = [] changePath = "" changeAmount = None output = None outputAmount = None p2shTransaction = False pin = "" self.get_client( ) # prompt for the PIN before displaying the dialog if necessary # Fetch inputs of the transaction to sign derivations = self.get_tx_derivations(tx) for txin in tx.inputs(): if txin['type'] == 'coinbase': self.give_error( "Coinbase not supported") # should never happen if txin['type'] in ['p2sh']: p2shTransaction = True pubkeys, x_pubkeys = tx.get_sorted_pubkeys(txin) for i, x_pubkey in enumerate(x_pubkeys): if x_pubkey in derivations: signingPos = i s = derivations.get(x_pubkey) hwAddress = "%s/%d/%d" % (self.get_derivation()[2:], s[0], s[1]) break else: self.give_error("No matching x_key for sign_transaction" ) # should never happen redeemScript = Transaction.get_preimage_script(txin) inputs.append([ txin['prev_tx'].raw, txin['prevout_n'], redeemScript, txin['prevout_hash'], signingPos, txin.get('sequence', 0xffffffff - 1) ]) inputsPaths.append(hwAddress) pubKeys.append(pubkeys) # Sanity check if p2shTransaction: for txin in tx.inputs(): if txin['type'] != 'p2sh': self.give_error( "P2SH / regular input mixed in same transaction not supported" ) # should never happen txOutput = var_int(len(tx.outputs())) for txout in tx.outputs(): output_type, addr, amount = txout txOutput += int_to_hex(amount, 8) script = tx.pay_script(output_type, addr) txOutput += var_int(len(script) / 2) txOutput += script txOutput = txOutput.decode('hex') # Recognize outputs - only one output and one change is authorized if not p2shTransaction: if not self.get_client_electrum().supports_multi_output(): if len(tx.outputs()) > 2: self.give_error( "Transaction with more than 2 outputs not supported") for _type, address, amount in tx.outputs(): assert _type == TYPE_ADDRESS info = tx.output_info.get(address) if (info is not None) and (len(tx.outputs()) != 1): index, xpubs, m = info changePath = self.get_derivation()[2:] + "/%d/%d" % index changeAmount = amount else: output = address if not self.get_client_electrum().canAlternateCoinVersions: v, h = bc_address_to_hash_160(address) if v == ADDRTYPE_P2PKH: output = hash_160_to_bc_address(h, 0) outputAmount = amount self.handler.show_message( _("Confirm Transaction on your Ledger device...")) try: # Get trusted inputs from the original transactions for utxo in inputs: sequence = int_to_hex(utxo[5], 4) if not p2shTransaction: txtmp = bitcoinTransaction(bytearray( utxo[0].decode('hex'))) trustedInput = self.get_client().getTrustedInput( txtmp, utxo[1]) trustedInput['sequence'] = sequence chipInputs.append(trustedInput) redeemScripts.append(txtmp.outputs[utxo[1]].script) else: tmp = utxo[3].decode('hex')[::-1].encode('hex') tmp += int_to_hex(utxo[1], 4) chipInputs.append({ 'value': tmp.decode('hex'), 'sequence': sequence }) redeemScripts.append(bytearray(utxo[2].decode('hex'))) # Sign all inputs firstTransaction = True inputIndex = 0 rawTx = tx.serialize() self.get_client().enableAlternate2fa(False) while inputIndex < len(inputs): self.get_client().startUntrustedTransaction( firstTransaction, inputIndex, chipInputs, redeemScripts[inputIndex]) if not p2shTransaction: outputData = self.get_client().finalizeInput( output, format_satoshis_plain(outputAmount), format_satoshis_plain(tx.get_fee()), changePath, bytearray(rawTx.decode('hex'))) else: outputData = self.get_client().finalizeInputFull(txOutput) outputData['outputData'] = txOutput if firstTransaction: transactionOutput = outputData['outputData'] if outputData['confirmationNeeded']: outputData['address'] = output self.handler.clear_dialog() pin = self.handler.get_auth( outputData ) # does the authenticate dialog and returns pin if not pin: raise UserWarning() if pin != 'paired': self.handler.show_message( _("Confirmed. Signing Transaction...")) else: # Sign input with the provided PIN inputSignature = self.get_client().untrustedHashSign( inputsPaths[inputIndex], pin, lockTime=tx.locktime) inputSignature[0] = 0x30 # force for 1.4.9+ signatures.append(inputSignature) inputIndex = inputIndex + 1 if pin != 'paired': firstTransaction = False except UserWarning: self.handler.show_error(_('Cancelled by user')) return except BaseException as e: traceback.print_exc(file=sys.stdout) self.give_error(e, True) finally: self.handler.clear_dialog() for i, txin in enumerate(tx.inputs()): signingPos = inputs[i][4] txin['signatures'][signingPos] = str(signatures[i]).encode('hex') tx.raw = tx.serialize() self.signing = False
def format_amount_and_units(self, x): return format_satoshis_plain( x, self.decimal_point()) + ' ' + self.base_unit