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()
|
||||
|
||||
@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.
|
||||
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."""
|
||||
addr = wallet.get_unused_address()
|
||||
if addr is None:
|
||||
if force:
|
||||
addr = wallet.create_new_address(False)
|
||||
else:
|
||||
return False
|
||||
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
|
||||
key = wallet.create_request(amount, memo, expiry, addr)
|
||||
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'),
|
||||
'domain': ("-D", "List of addresses"),
|
||||
'memo': ("-m", "Description of the request"),
|
||||
'amount': (None, "Requested amount (in btc)"),
|
||||
'lightning': (None, "Create lightning request"),
|
||||
'expiry': (None, "Time in seconds"),
|
||||
'timeout': (None, "Timeout in seconds"),
|
||||
'force': (None, "Create new address beyond gap limit, if no more addresses are available."),
|
||||
|
||||
@@ -11,12 +11,13 @@ import "controls"
|
||||
ElDialog {
|
||||
id: dialog
|
||||
|
||||
title: qsTr('Receive payment')
|
||||
title: qsTr('Create Invoice')
|
||||
iconSource: Qt.resolvedUrl('../../icons/tab_receive.png')
|
||||
|
||||
property alias amount: amountBtc.text
|
||||
property alias description: message.text
|
||||
property alias expiry: expires.currentValue
|
||||
property bool isLightning: false
|
||||
|
||||
padding: 0
|
||||
|
||||
@@ -93,11 +94,22 @@ ElDialog {
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
Layout.fillWidth: true
|
||||
text: qsTr('Create request')
|
||||
icon.source: '../../icons/confirmed.png'
|
||||
onClicked: doAccept()
|
||||
GridLayout {
|
||||
width: parent.width
|
||||
columns: 2
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
function createRequest(lightning_only, reuse_address) {
|
||||
function createRequest(lightning, reuse_address) {
|
||||
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() {
|
||||
@@ -596,7 +596,7 @@ Item {
|
||||
_request_amount = _receiveDetailsDialog.amount
|
||||
_request_description = _receiveDetailsDialog.description
|
||||
_request_expiry = _receiveDetailsDialog.expiry
|
||||
createRequest(false, false)
|
||||
createRequest(_receiveDetailsDialog.isLightning, false)
|
||||
}
|
||||
onRejected: {
|
||||
console.log('rejected')
|
||||
|
||||
@@ -664,24 +664,25 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
|
||||
@pyqtSlot(QEAmount, str, int, bool)
|
||||
@pyqtSlot(QEAmount, str, int, 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()
|
||||
try:
|
||||
amount = amount.satsInt
|
||||
addr = self.wallet.get_unused_address()
|
||||
if addr is None:
|
||||
if reuse_address:
|
||||
addr = self.wallet.get_receiving_address()
|
||||
elif lightning_only:
|
||||
addr = None
|
||||
else:
|
||||
msg = [
|
||||
_('No address available.'),
|
||||
_('All your addresses are used in pending requests.'),
|
||||
_('To see the list, press and hold the Receive button.'),
|
||||
]
|
||||
self.requestCreateError.emit(' '.join(msg))
|
||||
return
|
||||
if not lightning:
|
||||
addr = self.wallet.get_unused_address()
|
||||
if addr is None:
|
||||
if reuse_address:
|
||||
addr = self.wallet.get_receiving_address()
|
||||
else:
|
||||
msg = [
|
||||
_('No address available.'),
|
||||
_('All your addresses are used in pending requests.'),
|
||||
_('To see the list, press and hold the Receive button.'),
|
||||
]
|
||||
self.requestCreateError.emit(' '.join(msg))
|
||||
return
|
||||
else:
|
||||
addr = None
|
||||
|
||||
key = self.wallet.create_request(amount, message, expiration, addr)
|
||||
except InvoiceError as e:
|
||||
|
||||
@@ -69,13 +69,21 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
||||
|
||||
self.clear_invoice_button = QPushButton(_('Clear'))
|
||||
self.clear_invoice_button.clicked.connect(self.do_clear)
|
||||
self.create_invoice_button = QPushButton(_('Create Request'))
|
||||
self.create_invoice_button.clicked.connect(lambda: self.create_invoice())
|
||||
text = _('Onchain') if self.wallet.has_lightning() else _('Request')
|
||||
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()
|
||||
buttons.addStretch(1)
|
||||
buttons.addWidget(self.clear_invoice_button)
|
||||
buttons.addWidget(self.create_invoice_button)
|
||||
grid.addLayout(buttons, 4, 0, 1, -1)
|
||||
buttons.addStretch(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.setFont(QFont(MONOSPACE_FONT))
|
||||
@@ -116,6 +124,7 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
||||
|
||||
self.receive_widget = ReceiveWidget(
|
||||
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.setRetainSizeWhenHidden(True)
|
||||
@@ -138,12 +147,6 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
||||
self.toggle_qr_button.setEnabled(False)
|
||||
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.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)
|
||||
@@ -204,24 +207,6 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
||||
self.wallet.lnworker.clear_invoices_cache()
|
||||
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):
|
||||
text, data, help_text, title = self.get_tab_data()
|
||||
self.window.do_copy(text, title=title)
|
||||
@@ -277,16 +262,14 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
||||
# always show
|
||||
self.receive_widget.setVisible(True)
|
||||
self.toggle_qr_button.setEnabled(True)
|
||||
self.toggle_view_button.setEnabled(True)
|
||||
self.update_receive_qr_window()
|
||||
|
||||
def get_tab_data(self):
|
||||
i = self.config.GUI_QT_RECEIVE_TABS_INDEX
|
||||
if i == 0:
|
||||
if self.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')
|
||||
elif i == 2:
|
||||
else:
|
||||
# encode lightning invoices as uppercase so QR encoding can use
|
||||
# alphanumeric mode; resulting in smaller QR codes
|
||||
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()
|
||||
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()
|
||||
message = self.receive_message_e.text()
|
||||
expiry = self.config.WALLET_PAYREQ_EXPIRY_SECONDS
|
||||
|
||||
if amount_sat and amount_sat < self.wallet.dust_threshold():
|
||||
if is_lightning:
|
||||
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'))
|
||||
return
|
||||
else:
|
||||
address = self.get_bitcoin_address_for_request(amount_sat)
|
||||
if not address:
|
||||
return
|
||||
@@ -358,7 +340,6 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
||||
self.address_help = self.URI_help = self.ln_help = ''
|
||||
self.receive_widget.setVisible(False)
|
||||
self.toggle_qr_button.setEnabled(False)
|
||||
self.toggle_view_button.setEnabled(False)
|
||||
self.receive_message_e.setText('')
|
||||
self.receive_amount_e.setAmount(None)
|
||||
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(key, ROLE_KEY)
|
||||
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.STATUS].setIcon(read_QIcon(pr_icons.get(status)))
|
||||
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.'))
|
||||
amount_label = HelpLabel(_('Amount'), msg)
|
||||
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 '')
|
||||
if not self.fx or not self.fx.is_enabled():
|
||||
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(
|
||||
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.setCheckable(True)
|
||||
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")
|
||||
self.invoice_error = IconLabel(reverse=True, hide_if_empty=True)
|
||||
self.invoice_error.setIcon(invoice_error_icon)
|
||||
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.setIcon(read_QIcon('copy.png'))
|
||||
self.paste_button.setToolTip(_('Paste invoice from clipboard'))
|
||||
self.paste_button.setMaximumWidth(35)
|
||||
self.paste_button.setFocusPolicy(Qt.FocusPolicy.NoFocus)
|
||||
grid.addWidget(self.paste_button, 0, 5)
|
||||
|
||||
self.spinner = QMovie(icon_path('spinner.gif'))
|
||||
self.spinner.setScaledSize(QSize(24, 24))
|
||||
@@ -155,10 +157,16 @@ class SendTab(QWidget, MessageBoxMixin, Logger):
|
||||
self.send_button.setEnabled(False)
|
||||
self.clear_button = EnterButton(_("Clear"), self.do_clear)
|
||||
|
||||
buttons = QHBoxLayout()
|
||||
buttons.addStretch(1)
|
||||
#buttons1 = QHBoxLayout()
|
||||
#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.addStretch(1)
|
||||
buttons.addWidget(self.save_button)
|
||||
buttons.addWidget(self.send_button)
|
||||
grid.addLayout(buttons, 6, 1, 1, 4)
|
||||
|
||||
@@ -344,8 +344,9 @@ class Request(BaseInvoice):
|
||||
) -> Optional[str]:
|
||||
addr = self.get_address()
|
||||
amount = self.get_amount_sat()
|
||||
if amount is not None:
|
||||
amount = int(amount)
|
||||
if amount is None:
|
||||
return
|
||||
amount = int(amount)
|
||||
message = self.message
|
||||
extra = {}
|
||||
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,
|
||||
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_TX_EDITOR_SHOW_IO = ConfigVar(
|
||||
'show_tx_io', default=False, type_=bool,
|
||||
|
||||
@@ -2833,6 +2833,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
return invoice
|
||||
|
||||
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
|
||||
amount_sat = amount_sat or 0
|
||||
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
|
||||
exp_delay = exp_delay or 0
|
||||
timestamp = int(Request._get_cur_time())
|
||||
payment_hash = None # type: Optional[bytes]
|
||||
if self.has_lightning():
|
||||
if address is None:
|
||||
assert self.has_lightning()
|
||||
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 []
|
||||
height = self.adb.get_local_height()
|
||||
req = Request(
|
||||
|
||||
@@ -133,12 +133,12 @@ if [[ $1 == "breach" ]]; then
|
||||
channel=$($alice open_channel $bob_node 0.15 --password='')
|
||||
new_blocks 3
|
||||
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"
|
||||
$alice lnpay $request
|
||||
sleep 2
|
||||
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"
|
||||
$alice lnpay $request
|
||||
echo "alice broadcasts old ctx"
|
||||
@@ -289,7 +289,7 @@ if [[ $1 == "extract_preimage" ]]; then
|
||||
wait_until_channel_open alice
|
||||
chan_id=$($alice list_channels | jq -r ".[0].channel_point")
|
||||
# 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
|
||||
sleep 1
|
||||
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
||||
@@ -319,7 +319,7 @@ if [[ $1 == "redeem_htlcs" ]]; then
|
||||
new_blocks 3
|
||||
wait_until_channel_open alice
|
||||
# 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
|
||||
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
||||
if [[ "$unsettled" == "0" ]]; then
|
||||
@@ -361,7 +361,7 @@ if [[ $1 == "breach_with_unspent_htlc" ]]; then
|
||||
new_blocks 3
|
||||
wait_until_channel_open alice
|
||||
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
|
||||
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
||||
if [[ "$unsettled" == "0" ]]; then
|
||||
@@ -390,7 +390,7 @@ if [[ $1 == "breach_with_spent_htlc" ]]; then
|
||||
new_blocks 3
|
||||
wait_until_channel_open alice
|
||||
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
|
||||
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
||||
unsettled=$($alice list_channels | jq '.[] | .local_unsettled_sent')
|
||||
@@ -453,11 +453,11 @@ if [[ $1 == "watchtower" ]]; then
|
||||
new_blocks 3
|
||||
wait_until_channel_open alice
|
||||
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
|
||||
ctx=$($alice get_channel_ctx $channel --iknowwhatimdoing)
|
||||
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
|
||||
bob_ctn=$($bob list_channels | jq '.[0].local_ctn')
|
||||
msg="waiting until watchtower is synchronized"
|
||||
@@ -492,7 +492,7 @@ if [[ $1 == "just_in_time" ]]; then
|
||||
wait_until_channel_open carol
|
||||
echo "carol pays alice"
|
||||
# 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
|
||||
fi
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
|
||||
self.assertTrue(wallet1.has_lightning())
|
||||
# create payreq
|
||||
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)
|
||||
self.assertIsNotNone(pr)
|
||||
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 = wallet1.get_request(pr_key)
|
||||
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(1000, pr.height)
|
||||
# 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 = wallet1.get_request(pr_key)
|
||||
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(1000, pr.height)
|
||||
# get paid onchain
|
||||
@@ -143,59 +143,6 @@ class TestWalletPaymentRequests(ElectrumTestCase):
|
||||
wallet1.adb.add_verified_tx(tx.txid(), tx_info)
|
||||
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):
|
||||
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)
|
||||
@@ -206,7 +153,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
|
||||
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.assertTrue(not pr1.is_lightning())
|
||||
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr1))
|
||||
self.assertEqual(addr1, pr1.get_address())
|
||||
self.assertFalse(pr1.has_expired())
|
||||
@@ -219,7 +166,7 @@ class TestWalletPaymentRequests(ElectrumTestCase):
|
||||
self.assertEqual(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.assertTrue(not pr2.is_lightning())
|
||||
self.assertEqual(PR_UNPAID, wallet1.get_invoice_status(pr2))
|
||||
self.assertEqual(addr2, pr2.get_address())
|
||||
self.assertFalse(pr2.has_expired())
|
||||
|
||||
Reference in New Issue
Block a user