qt,qml: more regression fixes
This commit is contained in:
@@ -5,8 +5,7 @@ from enum import IntEnum
|
|||||||
|
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
from .util import NoDynamicFeeEstimates, quantize_feerate, format_fee_satoshis
|
from .util import NoDynamicFeeEstimates, quantize_feerate, format_fee_satoshis
|
||||||
from . import util
|
from . import util, constants
|
||||||
from . import constants
|
|
||||||
from .logging import Logger
|
from .logging import Logger
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -132,7 +131,7 @@ class FeePolicy(Logger):
|
|||||||
return self.method in [FeeMethod.ETA, FeeMethod.MEMPOOL]
|
return self.method in [FeeMethod.ETA, FeeMethod.MEMPOOL]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def depth_target(self, slider_pos: int) -> int:
|
def depth_target(cls, slider_pos: int) -> int:
|
||||||
"""Returns mempool depth target in bytes for a fee slider position."""
|
"""Returns mempool depth target in bytes for a fee slider position."""
|
||||||
slider_pos = max(slider_pos, 0)
|
slider_pos = max(slider_pos, 0)
|
||||||
slider_pos = min(slider_pos, len(FEE_DEPTH_TARGETS)-1)
|
slider_pos = min(slider_pos, len(FEE_DEPTH_TARGETS)-1)
|
||||||
@@ -143,7 +142,7 @@ class FeePolicy(Logger):
|
|||||||
return FEE_ETA_TARGETS[slider_pos]
|
return FEE_ETA_TARGETS[slider_pos]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def eta_tooltip(self, x):
|
def eta_tooltip(cls, x):
|
||||||
if x < 0:
|
if x < 0:
|
||||||
return _('Low fee')
|
return _('Low fee')
|
||||||
elif x == 1:
|
elif x == 1:
|
||||||
@@ -191,15 +190,15 @@ class FeePolicy(Logger):
|
|||||||
return _('Fixed rate') + ': ' + target + '\n' + _('Estimate') + ': ' + estimate
|
return _('Fixed rate') + ': ' + target + '\n' + _('Estimate') + ': ' + estimate
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def depth_tooltip(self, depth: Optional[int]) -> str:
|
def depth_tooltip(cls, depth: Optional[int]) -> str:
|
||||||
"""Returns text tooltip for given mempool depth (in vbytes)."""
|
"""Returns text tooltip for given mempool depth (in vbytes)."""
|
||||||
if depth is None:
|
if depth is None:
|
||||||
return "unknown from tip"
|
return "unknown from tip"
|
||||||
depth_mb = self.get_depth_mb_str(depth)
|
depth_mb = cls.get_depth_mb_str(depth)
|
||||||
return _("{} from tip").format(depth_mb)
|
return _("{} from tip").format(depth_mb)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_depth_mb_str(self, depth: int) -> str:
|
def get_depth_mb_str(cls, depth: int) -> str:
|
||||||
# e.g. 500_000 -> "0.50 MB"
|
# e.g. 500_000 -> "0.50 MB"
|
||||||
depth_mb = "{:.2f}".format(depth / 1_000_000) # maybe .rstrip("0") ?
|
depth_mb = "{:.2f}".format(depth / 1_000_000) # maybe .rstrip("0") ?
|
||||||
return f"{depth_mb} {util.UI_UNIT_NAME_MEMPOOL_MB}"
|
return f"{depth_mb} {util.UI_UNIT_NAME_MEMPOOL_MB}"
|
||||||
@@ -264,9 +263,10 @@ class FeePolicy(Logger):
|
|||||||
fee_per_byte = quantize_feerate(fee_per_byte)
|
fee_per_byte = quantize_feerate(fee_per_byte)
|
||||||
return round(fee_per_byte * size)
|
return round(fee_per_byte * size)
|
||||||
|
|
||||||
|
|
||||||
class FixedFeePolicy(FeePolicy):
|
class FixedFeePolicy(FeePolicy):
|
||||||
def __init__(self, fee):
|
def __init__(self, fee):
|
||||||
FeePolicy.__init__(self, 'fixed:%d'%fee)
|
FeePolicy.__init__(self, 'fixed:%d' % fee)
|
||||||
|
|
||||||
|
|
||||||
def impose_hard_limits_on_fee(func):
|
def impose_hard_limits_on_fee(func):
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
|||||||
|
|
||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum.gui import messages
|
from electrum.gui import messages
|
||||||
from electrum.util import bfh, NotEnoughFunds, NoDynamicFeeEstimates
|
from electrum.util import bfh
|
||||||
from electrum.lntransport import extract_nodeid, ConnStringFormatError
|
from electrum.lntransport import extract_nodeid, ConnStringFormatError
|
||||||
from electrum.bitcoin import DummyAddress
|
from electrum.bitcoin import DummyAddress
|
||||||
from electrum.lnworker import hardcoded_trampoline_nodes
|
from electrum.lnworker import hardcoded_trampoline_nodes
|
||||||
from electrum.logging import get_logger
|
from electrum.logging import get_logger
|
||||||
|
from electrum.fee_policy import FeePolicy
|
||||||
|
|
||||||
from .auth import AuthMixin, auth_protect
|
from .auth import AuthMixin, auth_protect
|
||||||
from .qetxfinalizer import QETxFinalizer
|
from .qetxfinalizer import QETxFinalizer
|
||||||
@@ -169,12 +170,13 @@ class QEChannelOpener(QObject, AuthMixin):
|
|||||||
self._logger.debug('amount = %s' % str(amount))
|
self._logger.debug('amount = %s' % str(amount))
|
||||||
|
|
||||||
coins = self._wallet.wallet.get_spendable_coins(None, nonlocal_only=True)
|
coins = self._wallet.wallet.get_spendable_coins(None, nonlocal_only=True)
|
||||||
|
fee_policy = FeePolicy(self._wallet.wallet.config.FEE_POLICY)
|
||||||
|
|
||||||
mktx = lambda amt: lnworker.mktx_for_open_channel(
|
mktx = lambda amt: lnworker.mktx_for_open_channel(
|
||||||
coins=coins,
|
coins=coins,
|
||||||
funding_sat=amt,
|
funding_sat=amt,
|
||||||
node_id=self._node_pubkey,
|
node_id=self._node_pubkey,
|
||||||
fee_est=None)
|
fee_policy=fee_policy)
|
||||||
|
|
||||||
acpt = lambda tx: self.do_open_channel(tx, self._connect_str_resolved, self._wallet.password)
|
acpt = lambda tx: self.do_open_channel(tx, self._connect_str_resolved, self._wallet.password)
|
||||||
|
|
||||||
@@ -244,11 +246,11 @@ class QEChannelOpener(QObject, AuthMixin):
|
|||||||
try:
|
try:
|
||||||
coins = self._wallet.wallet.get_spendable_coins(None, nonlocal_only=True)
|
coins = self._wallet.wallet.get_spendable_coins(None, nonlocal_only=True)
|
||||||
dummy_nodeid = ecc.GENERATOR.get_public_key_bytes(compressed=True)
|
dummy_nodeid = ecc.GENERATOR.get_public_key_bytes(compressed=True)
|
||||||
make_tx = lambda amt: self._wallet.wallet.lnworker.mktx_for_open_channel(
|
make_tx = lambda fee_policy: self._wallet.wallet.lnworker.mktx_for_open_channel(
|
||||||
coins=coins,
|
coins=coins,
|
||||||
funding_sat='!',
|
funding_sat='!',
|
||||||
node_id=dummy_nodeid,
|
node_id=dummy_nodeid,
|
||||||
fee_est=None)
|
fee_policy=fee_policy)
|
||||||
|
|
||||||
amount, message = self._wallet.determine_max(mktx=make_tx)
|
amount, message = self._wallet.determine_max(mktx=make_tx)
|
||||||
if amount is None:
|
if amount is None:
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ from electrum.payment_identifier import (PaymentIdentifier, PaymentIdentifierSta
|
|||||||
from .qetypes import QEAmount
|
from .qetypes import QEAmount
|
||||||
from .qewallet import QEWallet
|
from .qewallet import QEWallet
|
||||||
from .util import status_update_timer_interval, QtEventListener, event_listener
|
from .util import status_update_timer_interval, QtEventListener, event_listener
|
||||||
|
from ...fee_policy import FeePolicy
|
||||||
|
|
||||||
|
|
||||||
class QEInvoice(QObject, QtEventListener):
|
class QEInvoice(QObject, QtEventListener):
|
||||||
@@ -413,10 +414,10 @@ class QEInvoice(QObject, QtEventListener):
|
|||||||
def calc_max(address):
|
def calc_max(address):
|
||||||
try:
|
try:
|
||||||
outputs = [PartialTxOutput(scriptpubkey=address_to_script(address), value='!')]
|
outputs = [PartialTxOutput(scriptpubkey=address_to_script(address), value='!')]
|
||||||
make_tx = lambda fee_est, *, confirmed_only=False: self._wallet.wallet.make_unsigned_transaction(
|
make_tx = lambda fee_policy, *, confirmed_only=False: self._wallet.wallet.make_unsigned_transaction(
|
||||||
coins=self._wallet.wallet.get_spendable_coins(None),
|
coins=self._wallet.wallet.get_spendable_coins(None),
|
||||||
outputs=outputs,
|
outputs=outputs,
|
||||||
fee=fee_est,
|
fee_policy=fee_policy,
|
||||||
is_sweep=False)
|
is_sweep=False)
|
||||||
amount, message = self._wallet.determine_max(mktx=make_tx)
|
amount, message = self._wallet.determine_max(mktx=make_tx)
|
||||||
if amount is None:
|
if amount is None:
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ from .qeinvoicelistmodel import QEInvoiceListModel, QERequestListModel
|
|||||||
from .qetransactionlistmodel import QETransactionListModel
|
from .qetransactionlistmodel import QETransactionListModel
|
||||||
from .qetypes import QEAmount
|
from .qetypes import QEAmount
|
||||||
from .util import QtEventListener, qt_event_listener
|
from .util import QtEventListener, qt_event_listener
|
||||||
|
from ...fee_policy import FeePolicy
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from electrum.wallet import Abstract_Wallet
|
from electrum.wallet import Abstract_Wallet
|
||||||
@@ -820,16 +821,18 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
|
|||||||
sig = self.wallet.sign_message(address, message, self.password)
|
sig = self.wallet.sign_message(address, message, self.password)
|
||||||
return base64.b64encode(sig).decode('ascii')
|
return base64.b64encode(sig).decode('ascii')
|
||||||
|
|
||||||
def determine_max(self, *, mktx: Callable[[Optional[int]], PartialTransaction]) -> Tuple[Optional[int], Optional[str]]:
|
def determine_max(self, *, mktx: Callable[[FeePolicy], PartialTransaction]) -> Tuple[Optional[int], Optional[str]]:
|
||||||
# TODO: merge with SendTab.spend_max() and move to backend wallet
|
# TODO: merge with SendTab.spend_max() and move to backend wallet
|
||||||
amount = message = None
|
amount = message = None
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
tx = mktx(None)
|
fee_policy = FeePolicy(self.wallet.config.FEE_POLICY)
|
||||||
|
tx = mktx(fee_policy)
|
||||||
except (NotEnoughFunds, NoDynamicFeeEstimates) as e:
|
except (NotEnoughFunds, NoDynamicFeeEstimates) as e:
|
||||||
# Check if we had enough funds excluding fees,
|
# Check if we had enough funds excluding fees,
|
||||||
# if so, still provide opportunity to set lower fees.
|
# if so, still provide opportunity to set lower fees.
|
||||||
tx = mktx(0)
|
fee_policy = FeePolicy('fixed:0')
|
||||||
|
tx = mktx(fee_policy)
|
||||||
amount = tx.output_value()
|
amount = tx.output_value()
|
||||||
except NotEnoughFunds as e:
|
except NotEnoughFunds as e:
|
||||||
self._logger.debug(str(e))
|
self._logger.debug(str(e))
|
||||||
|
|||||||
@@ -1388,7 +1388,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener):
|
|||||||
def make_tx(fee_policy, *, confirmed_only=False, base_tx=None):
|
def make_tx(fee_policy, *, confirmed_only=False, base_tx=None):
|
||||||
assert base_tx is None
|
assert base_tx is None
|
||||||
return self.wallet.lnworker.mktx_for_open_channel(
|
return self.wallet.lnworker.mktx_for_open_channel(
|
||||||
coins = self.get_coins(nonlocal_only=True, confirmed_only=confirmed_only),
|
coins=self.get_coins(nonlocal_only=True, confirmed_only=confirmed_only),
|
||||||
funding_sat=funding_sat,
|
funding_sat=funding_sat,
|
||||||
node_id=node_id,
|
node_id=node_id,
|
||||||
fee_policy=fee_policy)
|
fee_policy=fee_policy)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from typing import TYPE_CHECKING, Optional
|
from typing import TYPE_CHECKING, Optional
|
||||||
from PyQt6.QtWidgets import QLabel, QVBoxLayout, QGridLayout, QPushButton, QComboBox, QLineEdit, QSpacerItem, QWidget, QHBoxLayout
|
from PyQt6.QtWidgets import QLabel, QVBoxLayout, QGridLayout, QPushButton, QComboBox, QLineEdit, QHBoxLayout
|
||||||
|
|
||||||
import electrum_ecc as ecc
|
import electrum_ecc as ecc
|
||||||
|
|
||||||
@@ -7,6 +7,7 @@ from electrum.i18n import _
|
|||||||
from electrum.lnutil import MIN_FUNDING_SAT
|
from electrum.lnutil import MIN_FUNDING_SAT
|
||||||
from electrum.lnworker import hardcoded_trampoline_nodes
|
from electrum.lnworker import hardcoded_trampoline_nodes
|
||||||
from electrum.util import NotEnoughFunds, NoDynamicFeeEstimates
|
from electrum.util import NotEnoughFunds, NoDynamicFeeEstimates
|
||||||
|
from electrum.fee_policy import FeePolicy
|
||||||
|
|
||||||
from .util import (WindowModalDialog, Buttons, OkButton, CancelButton,
|
from .util import (WindowModalDialog, Buttons, OkButton, CancelButton,
|
||||||
EnterButton, WWLabel, char_width_in_lineedit)
|
EnterButton, WWLabel, char_width_in_lineedit)
|
||||||
@@ -119,7 +120,7 @@ class NewChannelDialog(WindowModalDialog):
|
|||||||
dummy_nodeid = ecc.GENERATOR.get_public_key_bytes(compressed=True)
|
dummy_nodeid = ecc.GENERATOR.get_public_key_bytes(compressed=True)
|
||||||
make_tx = self.window.mktx_for_open_channel(funding_sat='!', node_id=dummy_nodeid)
|
make_tx = self.window.mktx_for_open_channel(funding_sat='!', node_id=dummy_nodeid)
|
||||||
try:
|
try:
|
||||||
tx = make_tx(None)
|
tx = make_tx(FeePolicy(self.config.FEE_POLICY))
|
||||||
except (NotEnoughFunds, NoDynamicFeeEstimates) as e:
|
except (NotEnoughFunds, NoDynamicFeeEstimates) as e:
|
||||||
self.max_button.setChecked(False)
|
self.max_button.setChecked(False)
|
||||||
self.amount_e.setFrozen(False)
|
self.amount_e.setFrozen(False)
|
||||||
|
|||||||
@@ -5,10 +5,9 @@
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import Optional, TYPE_CHECKING, Sequence, List, Callable, Union, Mapping
|
from typing import Optional, TYPE_CHECKING, Sequence, List, Callable, Union, Mapping
|
||||||
|
|
||||||
from PyQt6.QtCore import pyqtSignal, QPoint, QSize, Qt
|
from PyQt6.QtCore import pyqtSignal, QPoint, Qt
|
||||||
from PyQt6.QtWidgets import (QLabel, QVBoxLayout, QGridLayout, QHBoxLayout,
|
from PyQt6.QtWidgets import (QLabel, QVBoxLayout, QGridLayout, QHBoxLayout,
|
||||||
QWidget, QToolTip, QPushButton, QApplication)
|
QWidget, QToolTip, QPushButton, QApplication)
|
||||||
from PyQt6.QtGui import QMovie, QColor
|
|
||||||
|
|
||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum.logging import Logger
|
from electrum.logging import Logger
|
||||||
@@ -21,11 +20,12 @@ from electrum.network import TxBroadcastError, BestEffortRequestFailed
|
|||||||
from electrum.payment_identifier import (PaymentIdentifierType, PaymentIdentifier, invoice_from_payment_identifier,
|
from electrum.payment_identifier import (PaymentIdentifierType, PaymentIdentifier, invoice_from_payment_identifier,
|
||||||
payment_identifier_from_invoice)
|
payment_identifier_from_invoice)
|
||||||
from electrum.submarine_swaps import SwapServerError
|
from electrum.submarine_swaps import SwapServerError
|
||||||
|
from electrum.fee_policy import FeePolicy
|
||||||
|
|
||||||
from .amountedit import AmountEdit, BTCAmountEdit, SizedFreezableLineEdit
|
from .amountedit import AmountEdit, BTCAmountEdit, SizedFreezableLineEdit
|
||||||
from .paytoedit import InvalidPaymentIdentifier
|
from .paytoedit import InvalidPaymentIdentifier
|
||||||
from .util import (WaitingDialog, HelpLabel, MessageBoxMixin, EnterButton, char_width_in_lineedit,
|
from .util import (WaitingDialog, HelpLabel, MessageBoxMixin, EnterButton, char_width_in_lineedit,
|
||||||
get_iconname_camera, read_QIcon, ColorScheme, icon_path, IconLabel, Spinner)
|
get_iconname_camera, read_QIcon, ColorScheme, IconLabel, Spinner)
|
||||||
from .invoice_list import InvoiceList
|
from .invoice_list import InvoiceList
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -260,11 +260,11 @@ class SendTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
is_sweep=False)
|
is_sweep=False)
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
tx = make_tx(None)
|
tx = make_tx(FeePolicy(self.config.FEE_POLICY))
|
||||||
except (NotEnoughFunds, NoDynamicFeeEstimates) as e:
|
except (NotEnoughFunds, NoDynamicFeeEstimates) as e:
|
||||||
# Check if we had enough funds excluding fees,
|
# Check if we had enough funds excluding fees,
|
||||||
# if so, still provide opportunity to set lower fees.
|
# if so, still provide opportunity to set lower fees.
|
||||||
tx = make_tx(0)
|
tx = make_tx(FeePolicy('fixed:0'))
|
||||||
except NotEnoughFunds as e:
|
except NotEnoughFunds as e:
|
||||||
self.max_button.setChecked(False)
|
self.max_button.setChecked(False)
|
||||||
text = self.wallet.get_text_not_enough_funds_mentioning_frozen()
|
text = self.wallet.get_text_not_enough_funds_mentioning_frozen()
|
||||||
|
|||||||
Reference in New Issue
Block a user