def tx_outputs(self, tx):
        outputs = []

        for type, address, amount in tx.outputs:
            assert type == 'address'
            txoutputtype = types.TxOutputType()
            if self.is_change(address):
                address_path = self.address_id(address)
                address_n = self.get_client().expand_path(address_path)
                txoutputtype.address_n.extend(address_n)
            else:
                txoutputtype.address = address
            txoutputtype.amount = amount
            addrtype, hash_160 = bc_address_to_hash_160(address)
            if addrtype == 48:
                txoutputtype.script_type = types.PAYTOADDRESS
            elif addrtype == 5:
                txoutputtype.script_type = types.PAYTOSCRIPTHASH
            else:
                raise BaseException('addrtype')
            outputs.append(txoutputtype)

        return outputs
    def sign_transaction(self, tx, password):
        if tx.is_complete():
            return
        if tx.error:
            raise BaseException(tx.error)
        self.signing = True
        inputs = []
        inputsPaths = []
        pubKeys = []
        trustedInputs = []
        redeemScripts = []
        signatures = []
        preparedTrustedInputs = []
        changePath = ""
        changeAmount = None
        output = None
        outputAmount = None
        use2FA = False
        pin = ""
        # 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 == "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 == 48:
                        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")

        waitDialog.start("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(outputAmount), format_satoshis(self.get_tx_fee(tx)), changePath
                )
                if firstTransaction:
                    transactionOutput = outputData["outputData"]
                if outputData["confirmationNeeded"]:
                    use2FA = True
                    # TODO : handle different confirmation types. For the time being only supports keyboard 2FA
                    waitDialog.emit(SIGNAL("dongle_done"))
                    confirmed, p, pin = self.password_dialog()
                    if not confirmed:
                        raise Exception("Aborted by user")
                    pin = pin.encode()
                    self.client.bad = True
                    self.device_checked = False
                    self.get_client(True)
                    waitDialog.start("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)