reintroduce separate request types for lightning and onchain
cmdline: add_request has a --lightning option
This commit is contained in:
@@ -1074,17 +1074,20 @@ class Commands(Logger):
|
|||||||
return wallet.get_unused_address()
|
return wallet.get_unused_address()
|
||||||
|
|
||||||
@command('w')
|
@command('w')
|
||||||
async def add_request(self, amount, memo='', expiry=3600, force=False, wallet: Abstract_Wallet = None):
|
async def add_request(self, amount, memo='', expiry=3600, lightning=False, force=False, wallet: Abstract_Wallet = None):
|
||||||
"""Create a payment request, using the first unused address of the wallet.
|
"""Create a payment request, using the first unused address of the wallet.
|
||||||
The address will be considered as used after this operation.
|
The address will be considered as used after this operation.
|
||||||
If no payment is received, the address will be considered as unused if the payment request is deleted from the wallet."""
|
If no payment is received, the address will be considered as unused if the payment request is deleted from the wallet."""
|
||||||
addr = wallet.get_unused_address()
|
|
||||||
if addr is None:
|
|
||||||
if force:
|
|
||||||
addr = wallet.create_new_address(False)
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
amount = satoshis(amount)
|
amount = satoshis(amount)
|
||||||
|
if not lightning:
|
||||||
|
addr = wallet.get_unused_address()
|
||||||
|
if addr is None:
|
||||||
|
if force:
|
||||||
|
addr = wallet.create_new_address(False)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
addr = None
|
||||||
expiry = int(expiry) if expiry else None
|
expiry = int(expiry) if expiry else None
|
||||||
key = wallet.create_request(amount, memo, expiry, addr)
|
key = wallet.create_request(amount, memo, expiry, addr)
|
||||||
req = wallet.get_request(key)
|
req = wallet.get_request(key)
|
||||||
@@ -1586,6 +1589,8 @@ command_options = {
|
|||||||
'addtransaction': (None,'Whether transaction is to be used for broadcasting afterwards. Adds transaction to the wallet'),
|
'addtransaction': (None,'Whether transaction is to be used for broadcasting afterwards. Adds transaction to the wallet'),
|
||||||
'domain': ("-D", "List of addresses"),
|
'domain': ("-D", "List of addresses"),
|
||||||
'memo': ("-m", "Description of the request"),
|
'memo': ("-m", "Description of the request"),
|
||||||
|
'amount': (None, "Requested amount (in btc)"),
|
||||||
|
'lightning': (None, "Create lightning request"),
|
||||||
'expiry': (None, "Time in seconds"),
|
'expiry': (None, "Time in seconds"),
|
||||||
'timeout': (None, "Timeout in seconds"),
|
'timeout': (None, "Timeout in seconds"),
|
||||||
'force': (None, "Create new address beyond gap limit, if no more addresses are available."),
|
'force': (None, "Create new address beyond gap limit, if no more addresses are available."),
|
||||||
|
|||||||
@@ -11,12 +11,13 @@ import "controls"
|
|||||||
ElDialog {
|
ElDialog {
|
||||||
id: dialog
|
id: dialog
|
||||||
|
|
||||||
title: qsTr('Receive payment')
|
title: qsTr('Create Invoice')
|
||||||
iconSource: Qt.resolvedUrl('../../icons/tab_receive.png')
|
iconSource: Qt.resolvedUrl('../../icons/tab_receive.png')
|
||||||
|
|
||||||
property alias amount: amountBtc.text
|
property alias amount: amountBtc.text
|
||||||
property alias description: message.text
|
property alias description: message.text
|
||||||
property alias expiry: expires.currentValue
|
property alias expiry: expires.currentValue
|
||||||
|
property bool isLightning: false
|
||||||
|
|
||||||
padding: 0
|
padding: 0
|
||||||
|
|
||||||
@@ -93,11 +94,22 @@ ElDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FlatButton {
|
GridLayout {
|
||||||
Layout.fillWidth: true
|
width: parent.width
|
||||||
text: qsTr('Create request')
|
columns: 2
|
||||||
icon.source: '../../icons/confirmed.png'
|
|
||||||
onClicked: doAccept()
|
FlatButton {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr('Onchain')
|
||||||
|
icon.source: '../../icons/bitcoin.png'
|
||||||
|
onClicked: { dialog.isLightning = false; doAccept() }
|
||||||
|
}
|
||||||
|
FlatButton {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr('Lightning')
|
||||||
|
icon.source: '../../icons/lightning.png'
|
||||||
|
onClicked: { dialog.isLightning = true; doAccept() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -109,63 +109,6 @@ ElDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonContainer {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
showSeparator: false
|
|
||||||
Component {
|
|
||||||
id: _ind
|
|
||||||
Rectangle {
|
|
||||||
color: Material.dialogColor
|
|
||||||
opacity: parent.checked ? 1 : 0
|
|
||||||
radius: 5
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation { duration: 200 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TabButton {
|
|
||||||
id: bolt11Button
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredWidth: 1
|
|
||||||
text: qsTr('Lightning')
|
|
||||||
enabled: _bolt11
|
|
||||||
checked: rootLayout.state == 'bolt11'
|
|
||||||
indicator: _ind.createObject()
|
|
||||||
onClicked: {
|
|
||||||
rootLayout.state = 'bolt11'
|
|
||||||
Config.preferredRequestType = 'bolt11'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TabButton {
|
|
||||||
id: bip21Button
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredWidth: 1
|
|
||||||
text: qsTr('URI')
|
|
||||||
enabled: _bip21uri
|
|
||||||
checked: rootLayout.state == 'bip21uri'
|
|
||||||
indicator: _ind.createObject()
|
|
||||||
onClicked: {
|
|
||||||
rootLayout.state = 'bip21uri'
|
|
||||||
Config.preferredRequestType = 'bip21uri'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TabButton {
|
|
||||||
id: addressButton
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredWidth: 1
|
|
||||||
text: qsTr('Address')
|
|
||||||
checked: rootLayout.state == 'address'
|
|
||||||
indicator: _ind.createObject()
|
|
||||||
onClicked: {
|
|
||||||
rootLayout.state = 'address'
|
|
||||||
Config.preferredRequestType = 'address'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,9 +126,9 @@ Item {
|
|||||||
dialog.open()
|
dialog.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
function createRequest(lightning_only, reuse_address) {
|
function createRequest(lightning, reuse_address) {
|
||||||
var qamt = Config.unitsToSats(_request_amount)
|
var qamt = Config.unitsToSats(_request_amount)
|
||||||
Daemon.currentWallet.createRequest(qamt, _request_description, _request_expiry, lightning_only, reuse_address)
|
Daemon.currentWallet.createRequest(qamt, _request_description, _request_expiry, lightning, reuse_address)
|
||||||
}
|
}
|
||||||
|
|
||||||
function startSweep() {
|
function startSweep() {
|
||||||
@@ -596,7 +596,7 @@ Item {
|
|||||||
_request_amount = _receiveDetailsDialog.amount
|
_request_amount = _receiveDetailsDialog.amount
|
||||||
_request_description = _receiveDetailsDialog.description
|
_request_description = _receiveDetailsDialog.description
|
||||||
_request_expiry = _receiveDetailsDialog.expiry
|
_request_expiry = _receiveDetailsDialog.expiry
|
||||||
createRequest(false, false)
|
createRequest(_receiveDetailsDialog.isLightning, false)
|
||||||
}
|
}
|
||||||
onRejected: {
|
onRejected: {
|
||||||
console.log('rejected')
|
console.log('rejected')
|
||||||
|
|||||||
@@ -664,24 +664,25 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
|
|||||||
@pyqtSlot(QEAmount, str, int, bool)
|
@pyqtSlot(QEAmount, str, int, bool)
|
||||||
@pyqtSlot(QEAmount, str, int, bool, bool)
|
@pyqtSlot(QEAmount, str, int, bool, bool)
|
||||||
@pyqtSlot(QEAmount, str, int, bool, bool, bool)
|
@pyqtSlot(QEAmount, str, int, bool, bool, bool)
|
||||||
def createRequest(self, amount: QEAmount, message: str, expiration: int, lightning_only: bool = False, reuse_address: bool = False):
|
def createRequest(self, amount: QEAmount, message: str, expiration: int, lightning: bool = False, reuse_address: bool = False):
|
||||||
self.deleteExpiredRequests()
|
self.deleteExpiredRequests()
|
||||||
try:
|
try:
|
||||||
amount = amount.satsInt
|
amount = amount.satsInt
|
||||||
addr = self.wallet.get_unused_address()
|
if not lightning:
|
||||||
if addr is None:
|
addr = self.wallet.get_unused_address()
|
||||||
if reuse_address:
|
if addr is None:
|
||||||
addr = self.wallet.get_receiving_address()
|
if reuse_address:
|
||||||
elif lightning_only:
|
addr = self.wallet.get_receiving_address()
|
||||||
addr = None
|
else:
|
||||||
else:
|
msg = [
|
||||||
msg = [
|
_('No address available.'),
|
||||||
_('No address available.'),
|
_('All your addresses are used in pending requests.'),
|
||||||
_('All your addresses are used in pending requests.'),
|
_('To see the list, press and hold the Receive button.'),
|
||||||
_('To see the list, press and hold the Receive button.'),
|
]
|
||||||
]
|
self.requestCreateError.emit(' '.join(msg))
|
||||||
self.requestCreateError.emit(' '.join(msg))
|
return
|
||||||
return
|
else:
|
||||||
|
addr = None
|
||||||
|
|
||||||
key = self.wallet.create_request(amount, message, expiration, addr)
|
key = self.wallet.create_request(amount, message, expiration, addr)
|
||||||
except InvoiceError as e:
|
except InvoiceError as e:
|
||||||
|
|||||||
@@ -69,13 +69,21 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
|
|
||||||
self.clear_invoice_button = QPushButton(_('Clear'))
|
self.clear_invoice_button = QPushButton(_('Clear'))
|
||||||
self.clear_invoice_button.clicked.connect(self.do_clear)
|
self.clear_invoice_button.clicked.connect(self.do_clear)
|
||||||
self.create_invoice_button = QPushButton(_('Create Request'))
|
text = _('Onchain') if self.wallet.has_lightning() else _('Request')
|
||||||
self.create_invoice_button.clicked.connect(lambda: self.create_invoice())
|
self.create_onchain_invoice_button = QPushButton(text)
|
||||||
|
self.create_onchain_invoice_button.setIcon(read_QIcon("bitcoin.png"))
|
||||||
|
self.create_onchain_invoice_button.clicked.connect(lambda: self.create_invoice(False))
|
||||||
|
self.create_lightning_invoice_button = QPushButton(_('Lightning'))
|
||||||
|
self.create_lightning_invoice_button.setIcon(read_QIcon("lightning.png"))
|
||||||
|
self.create_lightning_invoice_button.clicked.connect(lambda: self.create_invoice(True))
|
||||||
|
self.create_lightning_invoice_button.setVisible(self.wallet.has_lightning())
|
||||||
|
|
||||||
self.receive_buttons = buttons = QHBoxLayout()
|
self.receive_buttons = buttons = QHBoxLayout()
|
||||||
buttons.addStretch(1)
|
|
||||||
buttons.addWidget(self.clear_invoice_button)
|
buttons.addWidget(self.clear_invoice_button)
|
||||||
buttons.addWidget(self.create_invoice_button)
|
buttons.addStretch(1)
|
||||||
grid.addLayout(buttons, 4, 0, 1, -1)
|
buttons.addWidget(self.create_onchain_invoice_button)
|
||||||
|
buttons.addWidget(self.create_lightning_invoice_button)
|
||||||
|
grid.addLayout(buttons, 4, 1, 1, -1)
|
||||||
|
|
||||||
self.receive_e = QTextEdit()
|
self.receive_e = QTextEdit()
|
||||||
self.receive_e.setFont(QFont(MONOSPACE_FONT))
|
self.receive_e.setFont(QFont(MONOSPACE_FONT))
|
||||||
@@ -116,6 +124,7 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
|
|
||||||
self.receive_widget = ReceiveWidget(
|
self.receive_widget = ReceiveWidget(
|
||||||
self, self.receive_e, self.receive_qr, self.receive_help_widget)
|
self, self.receive_e, self.receive_qr, self.receive_help_widget)
|
||||||
|
#self.receive_widget.mouseReleaseEvent = lambda x: self.toggle_receive_qr()
|
||||||
|
|
||||||
receive_widget_sp = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.MinimumExpanding)
|
receive_widget_sp = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.MinimumExpanding)
|
||||||
receive_widget_sp.setRetainSizeWhenHidden(True)
|
receive_widget_sp.setRetainSizeWhenHidden(True)
|
||||||
@@ -138,12 +147,6 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
self.toggle_qr_button.setEnabled(False)
|
self.toggle_qr_button.setEnabled(False)
|
||||||
self.toolbar.insertWidget(2, self.toggle_qr_button)
|
self.toolbar.insertWidget(2, self.toggle_qr_button)
|
||||||
|
|
||||||
self.toggle_view_button = QPushButton('')
|
|
||||||
self.toggle_view_button.setToolTip(_('switch between view'))
|
|
||||||
self.toggle_view_button.clicked.connect(self.toggle_view)
|
|
||||||
self.toggle_view_button.setEnabled(False)
|
|
||||||
self.update_view_button()
|
|
||||||
self.toolbar.insertWidget(2, self.toggle_view_button)
|
|
||||||
# menu
|
# menu
|
||||||
menu.addConfig(self.config.cv.WALLET_BOLT11_FALLBACK, callback=self.on_toggle_bolt11_fallback)
|
menu.addConfig(self.config.cv.WALLET_BOLT11_FALLBACK, callback=self.on_toggle_bolt11_fallback)
|
||||||
menu.addConfig(self.config.cv.WALLET_BIP21_LIGHTNING, callback=self.update_current_request)
|
menu.addConfig(self.config.cv.WALLET_BIP21_LIGHTNING, callback=self.update_current_request)
|
||||||
@@ -204,24 +207,6 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
self.wallet.lnworker.clear_invoices_cache()
|
self.wallet.lnworker.clear_invoices_cache()
|
||||||
self.update_current_request()
|
self.update_current_request()
|
||||||
|
|
||||||
def update_view_button(self):
|
|
||||||
i = self.config.GUI_QT_RECEIVE_TABS_INDEX
|
|
||||||
if i == 0:
|
|
||||||
icon, text = read_QIcon("link.png"), _('Bitcoin URI')
|
|
||||||
elif i == 1:
|
|
||||||
icon, text = read_QIcon("bitcoin.png"), _('Address')
|
|
||||||
elif i == 2:
|
|
||||||
icon, text = read_QIcon("lightning.png"), _('Lightning')
|
|
||||||
self.toggle_view_button.setText(text)
|
|
||||||
self.toggle_view_button.setIcon(icon)
|
|
||||||
|
|
||||||
def toggle_view(self):
|
|
||||||
i = self.config.GUI_QT_RECEIVE_TABS_INDEX
|
|
||||||
i = (i + 1) % (3 if self.wallet.has_lightning() else 2)
|
|
||||||
self.config.GUI_QT_RECEIVE_TABS_INDEX = i
|
|
||||||
self.update_current_request()
|
|
||||||
self.update_view_button()
|
|
||||||
|
|
||||||
def on_tab_changed(self):
|
def on_tab_changed(self):
|
||||||
text, data, help_text, title = self.get_tab_data()
|
text, data, help_text, title = self.get_tab_data()
|
||||||
self.window.do_copy(text, title=title)
|
self.window.do_copy(text, title=title)
|
||||||
@@ -277,16 +262,14 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
# always show
|
# always show
|
||||||
self.receive_widget.setVisible(True)
|
self.receive_widget.setVisible(True)
|
||||||
self.toggle_qr_button.setEnabled(True)
|
self.toggle_qr_button.setEnabled(True)
|
||||||
self.toggle_view_button.setEnabled(True)
|
|
||||||
self.update_receive_qr_window()
|
self.update_receive_qr_window()
|
||||||
|
|
||||||
def get_tab_data(self):
|
def get_tab_data(self):
|
||||||
i = self.config.GUI_QT_RECEIVE_TABS_INDEX
|
if self.URI:
|
||||||
if i == 0:
|
|
||||||
out = self.URI, self.URI, self.URI_help, _('Bitcoin URI')
|
out = self.URI, self.URI, self.URI_help, _('Bitcoin URI')
|
||||||
elif i == 1:
|
elif self.addr:
|
||||||
out = self.addr, self.addr, self.address_help, _('Address')
|
out = self.addr, self.addr, self.address_help, _('Address')
|
||||||
elif i == 2:
|
else:
|
||||||
# encode lightning invoices as uppercase so QR encoding can use
|
# encode lightning invoices as uppercase so QR encoding can use
|
||||||
# alphanumeric mode; resulting in smaller QR codes
|
# alphanumeric mode; resulting in smaller QR codes
|
||||||
out = self.lnaddr, self.lnaddr.upper(), self.ln_help, _('Lightning Request')
|
out = self.lnaddr, self.lnaddr.upper(), self.ln_help, _('Lightning Request')
|
||||||
@@ -297,17 +280,16 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
text, data, help_text, title = self.get_tab_data()
|
text, data, help_text, title = self.get_tab_data()
|
||||||
self.window.qr_window.qrw.setData(data)
|
self.window.qr_window.qrw.setData(data)
|
||||||
|
|
||||||
def create_invoice(self):
|
def create_invoice(self, is_lightning: bool):
|
||||||
amount_sat = self.receive_amount_e.get_amount()
|
amount_sat = self.receive_amount_e.get_amount()
|
||||||
message = self.receive_message_e.text()
|
message = self.receive_message_e.text()
|
||||||
expiry = self.config.WALLET_PAYREQ_EXPIRY_SECONDS
|
expiry = self.config.WALLET_PAYREQ_EXPIRY_SECONDS
|
||||||
|
if is_lightning:
|
||||||
if amount_sat and amount_sat < self.wallet.dust_threshold():
|
|
||||||
address = None
|
address = None
|
||||||
if not self.wallet.has_lightning():
|
else:
|
||||||
|
if amount_sat and amount_sat < self.wallet.dust_threshold():
|
||||||
self.show_error(_('Amount too small to be received onchain'))
|
self.show_error(_('Amount too small to be received onchain'))
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
address = self.get_bitcoin_address_for_request(amount_sat)
|
address = self.get_bitcoin_address_for_request(amount_sat)
|
||||||
if not address:
|
if not address:
|
||||||
return
|
return
|
||||||
@@ -358,7 +340,6 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
self.address_help = self.URI_help = self.ln_help = ''
|
self.address_help = self.URI_help = self.ln_help = ''
|
||||||
self.receive_widget.setVisible(False)
|
self.receive_widget.setVisible(False)
|
||||||
self.toggle_qr_button.setEnabled(False)
|
self.toggle_qr_button.setEnabled(False)
|
||||||
self.toggle_view_button.setEnabled(False)
|
|
||||||
self.receive_message_e.setText('')
|
self.receive_message_e.setText('')
|
||||||
self.receive_amount_e.setAmount(None)
|
self.receive_amount_e.setAmount(None)
|
||||||
self.request_list.clearSelection()
|
self.request_list.clearSelection()
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ class RequestList(MyTreeView):
|
|||||||
#items[self.Columns.DATE].setData(request_type, ROLE_REQUEST_TYPE)
|
#items[self.Columns.DATE].setData(request_type, ROLE_REQUEST_TYPE)
|
||||||
items[self.Columns.DATE].setData(key, ROLE_KEY)
|
items[self.Columns.DATE].setData(key, ROLE_KEY)
|
||||||
items[self.Columns.DATE].setData(timestamp, ROLE_SORT_ORDER)
|
items[self.Columns.DATE].setData(timestamp, ROLE_SORT_ORDER)
|
||||||
|
items[self.Columns.DATE].setIcon(read_QIcon("lightning" if req.is_lightning() else "bitcoin"))
|
||||||
items[self.Columns.AMOUNT].setData(amount_str_nots.strip(), self.ROLE_CLIPBOARD_DATA)
|
items[self.Columns.AMOUNT].setData(amount_str_nots.strip(), self.ROLE_CLIPBOARD_DATA)
|
||||||
items[self.Columns.STATUS].setIcon(read_QIcon(pr_icons.get(status)))
|
items[self.Columns.STATUS].setIcon(read_QIcon(pr_icons.get(status)))
|
||||||
self.std_model.insertRow(self.std_model.rowCount(), items)
|
self.std_model.insertRow(self.std_model.rowCount(), items)
|
||||||
|
|||||||
@@ -109,12 +109,14 @@ class SendTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
+ _('Keyboard shortcut: type "!" to send all your coins.'))
|
+ _('Keyboard shortcut: type "!" to send all your coins.'))
|
||||||
amount_label = HelpLabel(_('Amount'), msg)
|
amount_label = HelpLabel(_('Amount'), msg)
|
||||||
grid.addWidget(amount_label, 3, 0)
|
grid.addWidget(amount_label, 3, 0)
|
||||||
grid.addWidget(self.amount_e, 3, 1)
|
|
||||||
|
amount_widgets = QHBoxLayout()
|
||||||
|
amount_widgets.addWidget(self.amount_e)
|
||||||
|
|
||||||
self.fiat_send_e = AmountEdit(self.fx.get_currency if self.fx else '')
|
self.fiat_send_e = AmountEdit(self.fx.get_currency if self.fx else '')
|
||||||
if not self.fx or not self.fx.is_enabled():
|
if not self.fx or not self.fx.is_enabled():
|
||||||
self.fiat_send_e.setVisible(False)
|
self.fiat_send_e.setVisible(False)
|
||||||
grid.addWidget(self.fiat_send_e, 3, 2)
|
amount_widgets.addWidget(self.fiat_send_e)
|
||||||
self.amount_e.frozen.connect(
|
self.amount_e.frozen.connect(
|
||||||
lambda: self.fiat_send_e.setFrozen(self.amount_e.isReadOnly()))
|
lambda: self.fiat_send_e.setFrozen(self.amount_e.isReadOnly()))
|
||||||
|
|
||||||
@@ -125,20 +127,20 @@ class SendTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
self.max_button.setFixedWidth(btn_width)
|
self.max_button.setFixedWidth(btn_width)
|
||||||
self.max_button.setCheckable(True)
|
self.max_button.setCheckable(True)
|
||||||
self.max_button.setEnabled(False)
|
self.max_button.setEnabled(False)
|
||||||
grid.addWidget(self.max_button, 3, 3)
|
amount_widgets.addWidget(self.max_button)
|
||||||
|
amount_widgets.addStretch(1)
|
||||||
|
grid.addLayout(amount_widgets, 3, 1, 1, -1)
|
||||||
|
|
||||||
invoice_error_icon = read_QIcon("warning.png")
|
invoice_error_icon = read_QIcon("warning.png")
|
||||||
self.invoice_error = IconLabel(reverse=True, hide_if_empty=True)
|
self.invoice_error = IconLabel(reverse=True, hide_if_empty=True)
|
||||||
self.invoice_error.setIcon(invoice_error_icon)
|
self.invoice_error.setIcon(invoice_error_icon)
|
||||||
grid.addWidget(self.invoice_error, 3, 4, Qt.AlignmentFlag.AlignRight)
|
grid.addWidget(self.invoice_error, 3, 4, Qt.AlignmentFlag.AlignRight)
|
||||||
|
|
||||||
self.paste_button = QPushButton()
|
self.paste_button = QPushButton(_('Paste'))
|
||||||
self.paste_button.clicked.connect(self.do_paste)
|
self.paste_button.clicked.connect(self.do_paste)
|
||||||
self.paste_button.setIcon(read_QIcon('copy.png'))
|
self.paste_button.setIcon(read_QIcon('copy.png'))
|
||||||
self.paste_button.setToolTip(_('Paste invoice from clipboard'))
|
self.paste_button.setToolTip(_('Paste invoice from clipboard'))
|
||||||
self.paste_button.setMaximumWidth(35)
|
|
||||||
self.paste_button.setFocusPolicy(Qt.FocusPolicy.NoFocus)
|
self.paste_button.setFocusPolicy(Qt.FocusPolicy.NoFocus)
|
||||||
grid.addWidget(self.paste_button, 0, 5)
|
|
||||||
|
|
||||||
self.spinner = QMovie(icon_path('spinner.gif'))
|
self.spinner = QMovie(icon_path('spinner.gif'))
|
||||||
self.spinner.setScaledSize(QSize(24, 24))
|
self.spinner.setScaledSize(QSize(24, 24))
|
||||||
@@ -155,10 +157,16 @@ class SendTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
self.send_button.setEnabled(False)
|
self.send_button.setEnabled(False)
|
||||||
self.clear_button = EnterButton(_("Clear"), self.do_clear)
|
self.clear_button = EnterButton(_("Clear"), self.do_clear)
|
||||||
|
|
||||||
buttons = QHBoxLayout()
|
#buttons1 = QHBoxLayout()
|
||||||
buttons.addStretch(1)
|
#buttons1.addWidget(self.paste_button)
|
||||||
|
#buttons1.addWidget(self.clear_button)
|
||||||
|
#buttons1.addStretch(1)
|
||||||
|
#grid.addLayout(buttons1, 0, 1, 1, 4)
|
||||||
|
|
||||||
|
buttons = QHBoxLayout()
|
||||||
|
buttons.addWidget(self.paste_button)
|
||||||
buttons.addWidget(self.clear_button)
|
buttons.addWidget(self.clear_button)
|
||||||
|
buttons.addStretch(1)
|
||||||
buttons.addWidget(self.save_button)
|
buttons.addWidget(self.save_button)
|
||||||
buttons.addWidget(self.send_button)
|
buttons.addWidget(self.send_button)
|
||||||
grid.addLayout(buttons, 6, 1, 1, 4)
|
grid.addLayout(buttons, 6, 1, 1, 4)
|
||||||
|
|||||||
@@ -344,8 +344,9 @@ class Request(BaseInvoice):
|
|||||||
) -> Optional[str]:
|
) -> Optional[str]:
|
||||||
addr = self.get_address()
|
addr = self.get_address()
|
||||||
amount = self.get_amount_sat()
|
amount = self.get_amount_sat()
|
||||||
if amount is not None:
|
if amount is None:
|
||||||
amount = int(amount)
|
return
|
||||||
|
amount = int(amount)
|
||||||
message = self.message
|
message = self.message
|
||||||
extra = {}
|
extra = {}
|
||||||
if self.time and self.exp:
|
if self.time and self.exp:
|
||||||
|
|||||||
@@ -1097,7 +1097,6 @@ Warning: setting this to too low will result in lots of payment failures."""),
|
|||||||
'gui_qt_tx_dialog_export_include_global_xpubs', default=False, type_=bool,
|
'gui_qt_tx_dialog_export_include_global_xpubs', default=False, type_=bool,
|
||||||
short_desc=lambda: _('For hardware device; include xpubs'),
|
short_desc=lambda: _('For hardware device; include xpubs'),
|
||||||
)
|
)
|
||||||
GUI_QT_RECEIVE_TABS_INDEX = ConfigVar('receive_tabs_index', default=0, type_=int)
|
|
||||||
GUI_QT_RECEIVE_TAB_QR_VISIBLE = ConfigVar('receive_qr_visible', default=False, type_=bool)
|
GUI_QT_RECEIVE_TAB_QR_VISIBLE = ConfigVar('receive_qr_visible', default=False, type_=bool)
|
||||||
GUI_QT_TX_EDITOR_SHOW_IO = ConfigVar(
|
GUI_QT_TX_EDITOR_SHOW_IO = ConfigVar(
|
||||||
'show_tx_io', default=False, type_=bool,
|
'show_tx_io', default=False, type_=bool,
|
||||||
|
|||||||
@@ -2833,6 +2833,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
|||||||
return invoice
|
return invoice
|
||||||
|
|
||||||
def create_request(self, amount_sat: Optional[int], message: Optional[str], exp_delay: Optional[int], address: Optional[str]):
|
def create_request(self, amount_sat: Optional[int], message: Optional[str], exp_delay: Optional[int], address: Optional[str]):
|
||||||
|
""" will create a lightning request if address is None """
|
||||||
# for receiving
|
# for receiving
|
||||||
amount_sat = amount_sat or 0
|
amount_sat = amount_sat or 0
|
||||||
assert isinstance(amount_sat, int), f"{amount_sat!r}"
|
assert isinstance(amount_sat, int), f"{amount_sat!r}"
|
||||||
@@ -2841,9 +2842,11 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
|||||||
address = address or None # converts "" to None
|
address = address or None # converts "" to None
|
||||||
exp_delay = exp_delay or 0
|
exp_delay = exp_delay or 0
|
||||||
timestamp = int(Request._get_cur_time())
|
timestamp = int(Request._get_cur_time())
|
||||||
payment_hash = None # type: Optional[bytes]
|
if address is None:
|
||||||
if self.has_lightning():
|
assert self.has_lightning()
|
||||||
payment_hash = self.lnworker.create_payment_info(amount_msat=amount_msat, write_to_disk=False)
|
payment_hash = self.lnworker.create_payment_info(amount_msat=amount_msat, write_to_disk=False)
|
||||||
|
else:
|
||||||
|
payment_hash = None
|
||||||
outputs = [PartialTxOutput.from_address_and_value(address, amount_sat)] if address else []
|
outputs = [PartialTxOutput.from_address_and_value(address, amount_sat)] if address else []
|
||||||
height = self.adb.get_local_height()
|
height = self.adb.get_local_height()
|
||||||
req = Request(
|
req = Request(
|
||||||
|
|||||||
@@ -133,12 +133,12 @@ if [[ $1 == "breach" ]]; then
|
|||||||
channel=$($alice open_channel $bob_node 0.15 --password='')
|
channel=$($alice open_channel $bob_node 0.15 --password='')
|
||||||
new_blocks 3
|
new_blocks 3
|
||||||
wait_until_channel_open alice
|
wait_until_channel_open alice
|
||||||
request=$($bob add_request 0.01 -m "blah" | jq -r ".lightning_invoice")
|
request=$($bob add_request 0.01 --lightning -m "blah" | jq -r ".lightning_invoice")
|
||||||
echo "alice pays"
|
echo "alice pays"
|
||||||
$alice lnpay $request
|
$alice lnpay $request
|
||||||
sleep 2
|
sleep 2
|
||||||
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
||||||
request=$($bob add_request 0.01 -m "blah2" | jq -r ".lightning_invoice")
|
request=$($bob add_request 0.01 --lightning -m "blah2" | jq -r ".lightning_invoice")
|
||||||
echo "alice pays again"
|
echo "alice pays again"
|
||||||
$alice lnpay $request
|
$alice lnpay $request
|
||||||
echo "alice broadcasts old ctx"
|
echo "alice broadcasts old ctx"
|
||||||
@@ -289,7 +289,7 @@ if [[ $1 == "extract_preimage" ]]; then
|
|||||||
wait_until_channel_open alice
|
wait_until_channel_open alice
|
||||||
chan_id=$($alice list_channels | jq -r ".[0].channel_point")
|
chan_id=$($alice list_channels | jq -r ".[0].channel_point")
|
||||||
# alice pays bob
|
# alice pays bob
|
||||||
invoice=$($bob add_request 0.04 -m "test" | jq -r ".lightning_invoice")
|
invoice=$($bob add_request 0.04 --lightning -m "test" | jq -r ".lightning_invoice")
|
||||||
screen -S alice_payment -dm -L -Logfile /tmp/alice/screen.log $alice lnpay $invoice --timeout=600
|
screen -S alice_payment -dm -L -Logfile /tmp/alice/screen.log $alice lnpay $invoice --timeout=600
|
||||||
sleep 1
|
sleep 1
|
||||||
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
||||||
@@ -319,7 +319,7 @@ if [[ $1 == "redeem_htlcs" ]]; then
|
|||||||
new_blocks 3
|
new_blocks 3
|
||||||
wait_until_channel_open alice
|
wait_until_channel_open alice
|
||||||
# alice pays bob
|
# alice pays bob
|
||||||
invoice=$($bob add_request 0.04 -m "test" | jq -r ".lightning_invoice")
|
invoice=$($bob add_request 0.04 --lightning -m "test" | jq -r ".lightning_invoice")
|
||||||
$alice lnpay $invoice --timeout=1 || true
|
$alice lnpay $invoice --timeout=1 || true
|
||||||
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
||||||
if [[ "$unsettled" == "0" ]]; then
|
if [[ "$unsettled" == "0" ]]; then
|
||||||
@@ -361,7 +361,7 @@ if [[ $1 == "breach_with_unspent_htlc" ]]; then
|
|||||||
new_blocks 3
|
new_blocks 3
|
||||||
wait_until_channel_open alice
|
wait_until_channel_open alice
|
||||||
echo "alice pays bob"
|
echo "alice pays bob"
|
||||||
invoice=$($bob add_request 0.04 -m "test" | jq -r ".lightning_invoice")
|
invoice=$($bob add_request 0.04 --lightning -m "test" | jq -r ".lightning_invoice")
|
||||||
$alice lnpay $invoice --timeout=1 || true
|
$alice lnpay $invoice --timeout=1 || true
|
||||||
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
||||||
if [[ "$unsettled" == "0" ]]; then
|
if [[ "$unsettled" == "0" ]]; then
|
||||||
@@ -390,7 +390,7 @@ if [[ $1 == "breach_with_spent_htlc" ]]; then
|
|||||||
new_blocks 3
|
new_blocks 3
|
||||||
wait_until_channel_open alice
|
wait_until_channel_open alice
|
||||||
echo "alice pays bob"
|
echo "alice pays bob"
|
||||||
invoice=$($bob add_request 0.04 -m "test" | jq -r ".lightning_invoice")
|
invoice=$($bob add_request 0.04 --lightning -m "test" | jq -r ".lightning_invoice")
|
||||||
$alice lnpay $invoice --timeout=1 || true
|
$alice lnpay $invoice --timeout=1 || true
|
||||||
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
||||||
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
||||||
@@ -453,11 +453,11 @@ if [[ $1 == "watchtower" ]]; then
|
|||||||
new_blocks 3
|
new_blocks 3
|
||||||
wait_until_channel_open alice
|
wait_until_channel_open alice
|
||||||
echo "alice pays bob"
|
echo "alice pays bob"
|
||||||
invoice1=$($bob add_request 0.01 -m "invoice1" | jq -r ".lightning_invoice")
|
invoice1=$($bob add_request 0.01 --lightning -m "invoice1" | jq -r ".lightning_invoice")
|
||||||
$alice lnpay $invoice1
|
$alice lnpay $invoice1
|
||||||
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
||||||
echo "alice pays bob again"
|
echo "alice pays bob again"
|
||||||
invoice2=$($bob add_request 0.01 -m "invoice2" | jq -r ".lightning_invoice")
|
invoice2=$($bob add_request 0.01 --lightning -m "invoice2" | jq -r ".lightning_invoice")
|
||||||
$alice lnpay $invoice2
|
$alice lnpay $invoice2
|
||||||
bob_ctn=$($bob list_channels | jq '.[0].local_ctn')
|
bob_ctn=$($bob list_channels | jq '.[0].local_ctn')
|
||||||
msg="waiting until watchtower is synchronized"
|
msg="waiting until watchtower is synchronized"
|
||||||
@@ -492,7 +492,7 @@ if [[ $1 == "just_in_time" ]]; then
|
|||||||
wait_until_channel_open carol
|
wait_until_channel_open carol
|
||||||
echo "carol pays alice"
|
echo "carol pays alice"
|
||||||
# note: set amount to 0.001 to test failure: 'payment too low'
|
# note: set amount to 0.001 to test failure: 'payment too low'
|
||||||
invoice=$($alice add_request 0.01 -m "invoice" | jq -r ".lightning_invoice")
|
invoice=$($alice add_request 0.01 --lightning -m "invoice" | jq -r ".lightning_invoice")
|
||||||
$carol lnpay $invoice
|
$carol lnpay $invoice
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
|
|||||||
self.assertTrue(wallet1.has_lightning())
|
self.assertTrue(wallet1.has_lightning())
|
||||||
# create payreq
|
# create payreq
|
||||||
addr = wallet1.get_unused_address()
|
addr = wallet1.get_unused_address()
|
||||||
pr_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr, exp_delay=86400)
|
pr_key = wallet1.create_request(amount_sat=10000, message="msg", address=None, exp_delay=86400)
|
||||||
pr = wallet1.get_request(pr_key)
|
pr = wallet1.get_request(pr_key)
|
||||||
self.assertIsNotNone(pr)
|
self.assertIsNotNone(pr)
|
||||||
self.assertTrue(pr.is_lightning())
|
self.assertTrue(pr.is_lightning())
|
||||||
@@ -66,7 +66,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
|
|||||||
pr_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr, exp_delay=86400)
|
pr_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr, exp_delay=86400)
|
||||||
pr = wallet1.get_request(pr_key)
|
pr = wallet1.get_request(pr_key)
|
||||||
self.assertIsNotNone(pr)
|
self.assertIsNotNone(pr)
|
||||||
self.assertTrue(pr.is_lightning())
|
self.assertTrue(not pr.is_lightning())
|
||||||
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr))
|
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr))
|
||||||
self.assertEqual(1000, pr.height)
|
self.assertEqual(1000, pr.height)
|
||||||
# get paid onchain
|
# get paid onchain
|
||||||
@@ -126,7 +126,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
|
|||||||
pr_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr, exp_delay=86400)
|
pr_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr, exp_delay=86400)
|
||||||
pr = wallet1.get_request(pr_key)
|
pr = wallet1.get_request(pr_key)
|
||||||
self.assertIsNotNone(pr)
|
self.assertIsNotNone(pr)
|
||||||
self.assertTrue(pr.is_lightning())
|
self.assertTrue(not pr.is_lightning())
|
||||||
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr))
|
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr))
|
||||||
self.assertEqual(1000, pr.height)
|
self.assertEqual(1000, pr.height)
|
||||||
# get paid onchain
|
# get paid onchain
|
||||||
@@ -143,59 +143,6 @@ class TestWalletPaymentRequests(ElectrumTestCase):
|
|||||||
wallet1.adb.add_verified_tx(tx.txid(), tx_info)
|
wallet1.adb.add_verified_tx(tx.txid(), tx_info)
|
||||||
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr))
|
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr))
|
||||||
|
|
||||||
async def test_wallet_reuse_unused_fallback_onchain_addr_when_getting_paid_with_lightning(self):
|
|
||||||
text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver'
|
|
||||||
d = restore_wallet_from_text(text, path=self.wallet1_path, gap_limit=5, config=self.config)
|
|
||||||
wallet1 = d['wallet'] # type: Standard_Wallet
|
|
||||||
self.assertIsNotNone(wallet1.lnworker)
|
|
||||||
self.assertTrue(wallet1.has_lightning())
|
|
||||||
# create payreq1
|
|
||||||
addr1 = wallet1.get_unused_address()
|
|
||||||
pr1_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr1, exp_delay=86400)
|
|
||||||
pr1 = wallet1.get_request(pr1_key)
|
|
||||||
self.assertTrue(pr1.is_lightning())
|
|
||||||
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr1))
|
|
||||||
self.assertEqual(addr1, pr1.get_address())
|
|
||||||
self.assertFalse(pr1.has_expired())
|
|
||||||
|
|
||||||
# create payreq2
|
|
||||||
addr2 = wallet1.get_unused_address()
|
|
||||||
self.assertNotEqual(addr1, addr2)
|
|
||||||
pr2_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr2, exp_delay=86400)
|
|
||||||
pr2 = wallet1.get_request(pr2_key)
|
|
||||||
self.assertTrue(pr2.is_lightning())
|
|
||||||
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr2))
|
|
||||||
self.assertEqual(addr2, pr2.get_address())
|
|
||||||
|
|
||||||
# pr1 gets paid on LN
|
|
||||||
wallet1.lnworker.set_request_status(bytes.fromhex(pr1.rhash), PR_PAID)
|
|
||||||
self.assertEqual(PR_PAID, wallet1.get_invoice_status(pr1))
|
|
||||||
|
|
||||||
# create payreq3, which should auto-reuse addr1
|
|
||||||
addr3 = wallet1.get_unused_address()
|
|
||||||
self.assertEqual(addr1, addr3)
|
|
||||||
pr3_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr3, exp_delay=86400)
|
|
||||||
pr3 = wallet1.get_request(pr3_key)
|
|
||||||
self.assertTrue(pr3.is_lightning())
|
|
||||||
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr3))
|
|
||||||
self.assertEqual(addr3, pr3.get_address())
|
|
||||||
|
|
||||||
# pr2 gets paid onchain
|
|
||||||
wallet2 = self.create_wallet2() # type: Standard_Wallet
|
|
||||||
outputs = [PartialTxOutput.from_address_and_value(pr2.get_address(), pr2.get_amount_sat())]
|
|
||||||
tx = wallet2.create_transaction(outputs=outputs, fee=5000)
|
|
||||||
wallet1.adb.receive_tx_callback(tx, TX_HEIGHT_UNCONFIRMED)
|
|
||||||
self.assertEqual(PR_UNCONFIRMED, wallet1.get_invoice_status(pr2))
|
|
||||||
|
|
||||||
# create payreq4, which should not reuse addr2
|
|
||||||
addr4 = wallet1.get_unused_address()
|
|
||||||
self.assertEqual(3, len({addr1, addr2, addr3, addr4}))
|
|
||||||
pr4_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr4, exp_delay=86400)
|
|
||||||
pr4 = wallet1.get_request(pr4_key)
|
|
||||||
self.assertTrue(pr4.is_lightning())
|
|
||||||
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr4))
|
|
||||||
self.assertEqual(addr4, pr4.get_address())
|
|
||||||
|
|
||||||
async def test_wallet_reuse_addr_of_expired_request(self):
|
async def test_wallet_reuse_addr_of_expired_request(self):
|
||||||
text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver'
|
text = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver'
|
||||||
d = restore_wallet_from_text(text, path=self.wallet1_path, gap_limit=3, config=self.config)
|
d = restore_wallet_from_text(text, path=self.wallet1_path, gap_limit=3, config=self.config)
|
||||||
@@ -206,7 +153,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
|
|||||||
addr1 = wallet1.get_unused_address()
|
addr1 = wallet1.get_unused_address()
|
||||||
pr1_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr1, exp_delay=86400)
|
pr1_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr1, exp_delay=86400)
|
||||||
pr1 = wallet1.get_request(pr1_key)
|
pr1 = wallet1.get_request(pr1_key)
|
||||||
self.assertTrue(pr1.is_lightning())
|
self.assertTrue(not pr1.is_lightning())
|
||||||
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr1))
|
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr1))
|
||||||
self.assertEqual(addr1, pr1.get_address())
|
self.assertEqual(addr1, pr1.get_address())
|
||||||
self.assertFalse(pr1.has_expired())
|
self.assertFalse(pr1.has_expired())
|
||||||
@@ -219,7 +166,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
|
|||||||
self.assertEqual(addr1, addr2)
|
self.assertEqual(addr1, addr2)
|
||||||
pr2_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr2, exp_delay=86400)
|
pr2_key = wallet1.create_request(amount_sat=10000, message="msg", address=addr2, exp_delay=86400)
|
||||||
pr2 = wallet1.get_request(pr2_key)
|
pr2 = wallet1.get_request(pr2_key)
|
||||||
self.assertTrue(pr2.is_lightning())
|
self.assertTrue(not pr2.is_lightning())
|
||||||
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr2))
|
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr2))
|
||||||
self.assertEqual(addr2, pr2.get_address())
|
self.assertEqual(addr2, pr2.get_address())
|
||||||
self.assertFalse(pr2.has_expired())
|
self.assertFalse(pr2.has_expired())
|
||||||
|
|||||||
Reference in New Issue
Block a user