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)
Example #2
0
 def fiat_to_btc(self, fiat_amount):
     if not fiat_amount:
         return ''
     rate = run_hook('exchange_rate')
     if not rate:
         return ''
     satoshis = int(pow(10,8) * Decimal(fiat_amount) / Decimal(rate))
     return format_satoshis_plain(satoshis, self.decimal_point())
Example #3
0
    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)
Example #4
0
 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()))
Example #5
0
 def format_amount_and_units(self, x):
     return format_satoshis_plain(x, self.decimal_point()) + ' ' + self.base_unit
Example #6
0
 def get_max_amount(self):
     inputs = self.wallet.get_spendable_coins(None)
     addr = str(self.send_screen.screen.address) or self.wallet.dummy_address()
     amount, fee = self.wallet.get_max_amount(self.electrum_config, inputs, addr, None)
     return format_satoshis_plain(amount, self.decimal_point())
Example #7
0
    def sign_transaction(self, tx, password):
        if tx.is_complete():
            return
        client = self.get_client()
        self.signing = True
        inputs = []
        inputsPaths = []
        pubKeys = []
        trustedInputs = []
        redeemScripts = []
        signatures = []
        preparedTrustedInputs = []
        changePath = ""
        changeAmount = None
        output = None
        outputAmount = None
        use2FA = False
        pin = ""
        rawTx = tx.serialize()
        # Fetch inputs of the transaction to sign
        for txinput in tx.inputs():
            if ('is_coinbase' in txinput and txinput['is_coinbase']):
                self.give_error(
                    "Coinbase not supported")  # should never happen
            inputs.append([
                self.transactions[txinput['prevout_hash']].raw,
                txinput['prevout_n']
            ])
            address = txinput['address']
            inputsPaths.append(self.address_id(address))
            pubKeys.append(self.get_public_keys(address))

        # Recognize outputs - only one output and one change is authorized
        if len(tx.outputs()) > 2:  # should never happen
            self.give_error(
                "Transaction with more than 2 outputs not supported")
        for type, address, amount in tx.outputs():
            assert type == TYPE_ADDRESS
            if self.is_change(address):
                changePath = self.address_id(address)
                changeAmount = amount
            else:
                if output <> None:  # should never happen
                    self.give_error(
                        "Multiple outputs with no change not supported")
                output = address
                if not self.canAlternateCoinVersions:
                    v, h = bc_address_to_hash_160(address)
                    if v == PUBKEY_ADDR:
                        output = hash_160_to_bc_address(h, 0)
                outputAmount = amount

        self.get_client(
        )  # prompt for the PIN before displaying the dialog if necessary
        if not self.check_proper_device():
            self.give_error('Wrong device or password')

        self.handler.show_message("Signing Transaction ...")
        try:
            # Get trusted inputs from the original transactions
            for utxo in inputs:
                txtmp = bitcoinTransaction(bytearray(utxo[0].decode('hex')))
                trustedInputs.append(self.get_client().getTrustedInput(
                    txtmp, utxo[1]))
                # TODO : Support P2SH later
                redeemScripts.append(txtmp.outputs[utxo[1]].script)
            # Sign all inputs
            firstTransaction = True
            inputIndex = 0
            while inputIndex < len(inputs):
                self.get_client().startUntrustedTransaction(
                    firstTransaction, inputIndex, trustedInputs,
                    redeemScripts[inputIndex])
                outputData = self.get_client().finalizeInput(
                    output, format_satoshis_plain(outputAmount),
                    format_satoshis_plain(self.get_tx_fee(tx)), changePath,
                    bytearray(rawTx.decode('hex')))
                if firstTransaction:
                    transactionOutput = outputData['outputData']
                if outputData['confirmationNeeded']:
                    # TODO : handle different confirmation types. For the time being only supports keyboard 2FA
                    self.handler.clear_dialog()
                    if 'keycardData' in outputData:
                        pin2 = ""
                        for keycardIndex in range(
                                len(outputData['keycardData'])):
                            msg = "Do not enter your device PIN here !\r\n\r\n" + \
                                "Your Ledger Wallet wants to talk to you and tell you a unique second factor code.\r\n" + \
                                "For this to work, please match the character between stars of the output address using your security card\r\n\r\n" + \
                                "Output address : "
                            for index in range(len(output)):
                                if index == outputData['keycardData'][
                                        keycardIndex]:
                                    msg = msg + "*" + output[index] + "*"
                                else:
                                    msg = msg + output[index]
                            msg = msg + "\r\n"
                            confirmed, p, pin = self.password_dialog(msg)
                            if not confirmed:
                                raise Exception('Aborted by user')
                            try:
                                pin2 = pin2 + chr(int(pin[0], 16))
                            except:
                                raise Exception('Invalid PIN character')
                        pin = pin2
                    else:
                        use2FA = True
                        confirmed, p, pin = self.password_dialog()
                        if not confirmed:
                            raise Exception('Aborted by user')
                        pin = pin.encode()
                        client.bad = True
                        self.device_checked = False
                        self.plugin.get_client(self, True, True)
                    self.handler.show_message("Signing ...")
                else:
                    # Sign input with the provided PIN
                    inputSignature = self.get_client().untrustedHashSign(
                        inputsPaths[inputIndex], pin)
                    inputSignature[0] = 0x30  # force for 1.4.9+
                    signatures.append(inputSignature)
                    inputIndex = inputIndex + 1
                firstTransaction = False
        except Exception, e:
            self.give_error(e, True)