def sign_transaction(
            self,
            tx: Transaction,
            password,
            *,
            ignore_warnings: bool = False
    ) -> Optional[PartialTransaction]:
        """ returns tx if successful else None """
        if self.is_watching_only():
            return
        if not isinstance(tx, PartialTransaction):
            return
        if any(DummyAddress.is_dummy_address(txout.address) for txout in tx.outputs()):
            raise DummyAddressUsedInTxException("tried to sign tx with dummy address!")

        # check if signing is dangerous
        sh_danger = self.check_sighash(tx)
        if sh_danger.needs_reject():
            raise TransactionDangerousException('Not signing transaction:\n' + sh_danger.get_long_message())
        if sh_danger.needs_confirm() and not ignore_warnings:
            raise TransactionPotentiallyDangerousException('Not signing transaction:\n' + sh_danger.get_long_message())

        # find out if we are replacing a txbatcher transaction
        prevout_str = tx.inputs()[0].prevout.to_str()
        batch = self.txbatcher.find_batch_by_prevout(prevout_str)
        if batch:
            batch.add_sweep_info_to_tx(tx)

        # sign with make_witness
        for i, txin in enumerate(tx.inputs()):
            if hasattr(txin, 'make_witness'):
                self.logger.info(f'sign_transaction: adding witness using make_witness')
                privkey = txin.privkey
                sig = tx.sign_txin(i, privkey)
                txin.script_sig = b''
                txin.witness = txin.make_witness(sig)
                assert txin.is_complete()

        # add info to a temporary tx copy; including xpubs
        # and full derivation paths as hw keystores might want them
        tmp_tx = copy.deepcopy(tx)
        tmp_tx.add_info_from_wallet(self, include_xpubs=True)
        # sign. start with ready keystores.
        # note: ks.ready_to_sign() side-effect: we trigger pairings with potential hw devices.
        #       We only do this once, before the loop, however we could rescan after each iteration,
        #       to see if the user connected/disconnected devices in the meantime.
        for k in sorted(self.get_keystores(), key=lambda ks: ks.ready_to_sign(), reverse=True):
            try:
                if k.can_sign(tmp_tx):
                    k.sign_transaction(tmp_tx, password)
            except UserCancelled:
                continue
        # remove sensitive info; then copy back details from temporary tx
        tmp_tx.remove_xpubs_and_bip32_paths()
        tx.combine_with_other_psbt(tmp_tx)
        tx.add_info_from_wallet(self, include_xpubs=False)
        return tx
 returns tx if successful else None 
electrum/wallet.py