wip lightning
This commit is contained in:
132
electrum/gui/qml/components/Channels.qml
Normal file
132
electrum/gui/qml/components/Channels.qml
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
import QtQuick 2.6
|
||||||
|
import QtQuick.Layouts 1.0
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Controls.Material 2.0
|
||||||
|
|
||||||
|
import org.electrum 1.0
|
||||||
|
|
||||||
|
import "controls"
|
||||||
|
|
||||||
|
Pane {
|
||||||
|
property string title: qsTr("Lightning Channels")
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: layout
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
id: summaryLayout
|
||||||
|
Layout.preferredWidth: parent.width
|
||||||
|
columns: 2
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.columnSpan: 2
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr('You can send:')
|
||||||
|
color: Material.accentColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr('You can receive:')
|
||||||
|
color: Material.accentColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.columnSpan: 2
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr('Open Channel')
|
||||||
|
onClicked: app.stack.push(Qt.resolvedUrl('OpenChannel.qml'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Frame {
|
||||||
|
id: channelsFrame
|
||||||
|
Layout.preferredWidth: parent.width
|
||||||
|
Layout.fillHeight: true
|
||||||
|
verticalPadding: 0
|
||||||
|
horizontalPadding: 0
|
||||||
|
background: PaneInsetBackground {}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.preferredHeight: hitem.height
|
||||||
|
Layout.preferredWidth: parent.width
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Qt.lighter(Material.background, 1.25)
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
id: hitem
|
||||||
|
width: parent.width
|
||||||
|
Label {
|
||||||
|
text: qsTr('Channels')
|
||||||
|
font.pixelSize: constants.fontSizeLarge
|
||||||
|
color: Material.accentColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: listview
|
||||||
|
Layout.preferredWidth: parent.width
|
||||||
|
Layout.fillHeight: true
|
||||||
|
clip: true
|
||||||
|
model: 3 //Daemon.currentWallet.channelsModel
|
||||||
|
|
||||||
|
delegate: ItemDelegate {
|
||||||
|
width: ListView.view.width
|
||||||
|
height: row.height
|
||||||
|
highlighted: ListView.isCurrentItem
|
||||||
|
|
||||||
|
font.pixelSize: constants.fontSizeMedium // set default font size for child controls
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: row
|
||||||
|
spacing: 10
|
||||||
|
x: constants.paddingSmall
|
||||||
|
width: parent.width - 2 * constants.paddingSmall
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: walleticon
|
||||||
|
source: "../../icons/lightning.png"
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
Layout.preferredWidth: constants.iconSizeLarge
|
||||||
|
Layout.preferredHeight: constants.iconSizeLarge
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
font.pixelSize: constants.fontSizeLarge
|
||||||
|
text: index
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollIndicator.vertical: ScrollIndicator { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: Daemon.currentWallet.channelModel.init_model()
|
||||||
|
}
|
||||||
145
electrum/gui/qml/components/OpenChannel.qml
Normal file
145
electrum/gui/qml/components/OpenChannel.qml
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
import QtQuick 2.6
|
||||||
|
import QtQuick.Layouts 1.0
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Controls.Material 2.0
|
||||||
|
|
||||||
|
import org.electrum 1.0
|
||||||
|
|
||||||
|
import "controls"
|
||||||
|
|
||||||
|
Pane {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string title: qsTr("Open Lightning Channel")
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
id: form
|
||||||
|
width: parent.width
|
||||||
|
rowSpacing: constants.paddingSmall
|
||||||
|
columnSpacing: constants.paddingSmall
|
||||||
|
columns: 4
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr('Node')
|
||||||
|
}
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
id: node
|
||||||
|
Layout.columnSpan: 2
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.family: FixedFont
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
placeholderText: qsTr('Paste or scan node uri/pubkey')
|
||||||
|
onActiveFocusChanged: {
|
||||||
|
if (!activeFocus)
|
||||||
|
channelopener.nodeid = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: 0
|
||||||
|
ToolButton {
|
||||||
|
icon.source: '../../icons/paste.png'
|
||||||
|
icon.height: constants.iconSizeMedium
|
||||||
|
icon.width: constants.iconSizeMedium
|
||||||
|
onClicked: {
|
||||||
|
channelopener.nodeid = AppController.clipboardToText()
|
||||||
|
node.text = channelopener.nodeid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ToolButton {
|
||||||
|
icon.source: '../../icons/qrcode.png'
|
||||||
|
icon.height: constants.iconSizeMedium
|
||||||
|
icon.width: constants.iconSizeMedium
|
||||||
|
scale: 1.2
|
||||||
|
onClicked: {
|
||||||
|
var page = app.stack.push(Qt.resolvedUrl('Scan.qml'))
|
||||||
|
page.onFound.connect(function() {
|
||||||
|
channelopener.nodeid = page.scanData
|
||||||
|
node.text = channelopener.nodeid
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr('Amount')
|
||||||
|
}
|
||||||
|
|
||||||
|
BtcField {
|
||||||
|
id: amount
|
||||||
|
fiatfield: amountFiat
|
||||||
|
Layout.preferredWidth: parent.width /2
|
||||||
|
onTextChanged: channelopener.amount = Config.unitsToSats(amount.text)
|
||||||
|
enabled: !is_max.checked
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.columnSpan: 2
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Label {
|
||||||
|
text: Config.baseUnit
|
||||||
|
color: Material.accentColor
|
||||||
|
}
|
||||||
|
Switch {
|
||||||
|
id: is_max
|
||||||
|
text: qsTr('Max')
|
||||||
|
onCheckedChanged: {
|
||||||
|
if (checked) {
|
||||||
|
channelopener.amount = MAX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { width: 1; height: 1; visible: Daemon.fx.enabled }
|
||||||
|
|
||||||
|
FiatField {
|
||||||
|
id: amountFiat
|
||||||
|
btcfield: amount
|
||||||
|
visible: Daemon.fx.enabled
|
||||||
|
Layout.preferredWidth: parent.width /2
|
||||||
|
enabled: !is_max.checked
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
visible: Daemon.fx.enabled
|
||||||
|
text: Daemon.fx.fiatCurrency
|
||||||
|
color: Material.accentColor
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { visible: Daemon.fx.enabled ; height: 1; width: 1 }
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.columnSpan: 4
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: qsTr('Open Channel')
|
||||||
|
enabled: channelopener.valid
|
||||||
|
onClicked: channelopener.open_channel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ChannelOpener {
|
||||||
|
id: channelopener
|
||||||
|
wallet: Daemon.currentWallet
|
||||||
|
onValidationError: {
|
||||||
|
if (code == 'invalid_nodeid') {
|
||||||
|
var dialog = app.messageDialog.createObject(root, { 'text': message })
|
||||||
|
dialog.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onConflictingBackup: {
|
||||||
|
var dialog = app.messageDialog.createObject(root, { 'text': message })
|
||||||
|
dialog.open()
|
||||||
|
dialog.yesClicked.connect(function() {
|
||||||
|
channelopener.open_channel(true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,7 +12,6 @@ Item {
|
|||||||
property bool toolbar: false
|
property bool toolbar: false
|
||||||
|
|
||||||
property string scanData
|
property string scanData
|
||||||
property var invoiceData: undefined
|
|
||||||
property string error
|
property string error
|
||||||
|
|
||||||
signal found
|
signal found
|
||||||
@@ -24,16 +23,6 @@ Item {
|
|||||||
|
|
||||||
onFound: {
|
onFound: {
|
||||||
scanPage.scanData = scanData
|
scanPage.scanData = scanData
|
||||||
var invoice = bitcoin.parse_uri(scanData)
|
|
||||||
if (invoice['error']) {
|
|
||||||
error = invoice['error']
|
|
||||||
console.log(error)
|
|
||||||
app.stack.pop()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
invoiceData = invoice
|
|
||||||
console.log(invoiceData['address'])
|
|
||||||
scanPage.found()
|
scanPage.found()
|
||||||
app.stack.pop()
|
app.stack.pop()
|
||||||
}
|
}
|
||||||
@@ -46,8 +35,4 @@ Item {
|
|||||||
text: 'Cancel'
|
text: 'Cancel'
|
||||||
onClicked: app.stack.pop()
|
onClicked: app.stack.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitcoin {
|
|
||||||
id: bitcoin
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,16 @@ Item {
|
|||||||
icon.source: '../../icons/network.png'
|
icon.source: '../../icons/network.png'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MenuItem {
|
||||||
|
icon.color: 'transparent'
|
||||||
|
action: Action {
|
||||||
|
text: qsTr('Channels');
|
||||||
|
enabled: Daemon.currentWallet.isLightning
|
||||||
|
onTriggered: menu.openPage(Qt.resolvedUrl('Channels.qml'))
|
||||||
|
icon.source: '../../icons/lightning.png'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
icon.color: 'transparent'
|
icon.color: 'transparent'
|
||||||
action: Action {
|
action: Action {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from .qeinvoice import QEInvoice
|
|||||||
from .qetypes import QEAmount
|
from .qetypes import QEAmount
|
||||||
from .qeaddressdetails import QEAddressDetails
|
from .qeaddressdetails import QEAddressDetails
|
||||||
from .qetxdetails import QETxDetails
|
from .qetxdetails import QETxDetails
|
||||||
|
from .qechannelopener import QEChannelOpener
|
||||||
|
|
||||||
notification = None
|
notification = None
|
||||||
|
|
||||||
@@ -143,6 +144,7 @@ class ElectrumQmlApplication(QGuiApplication):
|
|||||||
qmlRegisterType(QEInvoice, 'org.electrum', 1, 0, 'Invoice')
|
qmlRegisterType(QEInvoice, 'org.electrum', 1, 0, 'Invoice')
|
||||||
qmlRegisterType(QEAddressDetails, 'org.electrum', 1, 0, 'AddressDetails')
|
qmlRegisterType(QEAddressDetails, 'org.electrum', 1, 0, 'AddressDetails')
|
||||||
qmlRegisterType(QETxDetails, 'org.electrum', 1, 0, 'TxDetails')
|
qmlRegisterType(QETxDetails, 'org.electrum', 1, 0, 'TxDetails')
|
||||||
|
qmlRegisterType(QEChannelOpener, 'org.electrum', 1, 0, 'ChannelOpener')
|
||||||
|
|
||||||
qmlRegisterUncreatableType(QEAmount, 'org.electrum', 1, 0, 'Amount', 'Amount can only be used as property')
|
qmlRegisterUncreatableType(QEAmount, 'org.electrum', 1, 0, 'Amount', 'Amount can only be used as property')
|
||||||
|
|
||||||
@@ -165,11 +167,13 @@ class ElectrumQmlApplication(QGuiApplication):
|
|||||||
self._qenetwork = QENetwork(daemon.network)
|
self._qenetwork = QENetwork(daemon.network)
|
||||||
self._qedaemon = QEDaemon(daemon)
|
self._qedaemon = QEDaemon(daemon)
|
||||||
self._appController = QEAppController(self._qedaemon)
|
self._appController = QEAppController(self._qedaemon)
|
||||||
|
self._maxAmount = QEAmount(is_max=True)
|
||||||
self.context.setContextProperty('AppController', self._appController)
|
self.context.setContextProperty('AppController', self._appController)
|
||||||
self.context.setContextProperty('Config', self._qeconfig)
|
self.context.setContextProperty('Config', self._qeconfig)
|
||||||
self.context.setContextProperty('Network', self._qenetwork)
|
self.context.setContextProperty('Network', self._qenetwork)
|
||||||
self.context.setContextProperty('Daemon', self._qedaemon)
|
self.context.setContextProperty('Daemon', self._qedaemon)
|
||||||
self.context.setContextProperty('FixedFont', self.fixedFont)
|
self.context.setContextProperty('FixedFont', self.fixedFont)
|
||||||
|
self.context.setContextProperty('MAX', self._maxAmount)
|
||||||
self.context.setContextProperty('BUILD', {
|
self.context.setContextProperty('BUILD', {
|
||||||
'electrum_version': version.ELECTRUM_VERSION,
|
'electrum_version': version.ELECTRUM_VERSION,
|
||||||
'apk_version': version.APK_VERSION,
|
'apk_version': version.APK_VERSION,
|
||||||
|
|||||||
53
electrum/gui/qml/qechannellistmodel.py
Normal file
53
electrum/gui/qml/qechannellistmodel.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
||||||
|
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
|
||||||
|
|
||||||
|
from electrum.logging import get_logger
|
||||||
|
from electrum.util import Satoshis, TxMinedInfo
|
||||||
|
|
||||||
|
from .qetypes import QEAmount
|
||||||
|
|
||||||
|
class QEChannelListModel(QAbstractListModel):
|
||||||
|
def __init__(self, wallet, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.wallet = wallet
|
||||||
|
self.channels = []
|
||||||
|
|
||||||
|
_logger = get_logger(__name__)
|
||||||
|
|
||||||
|
# define listmodel rolemap
|
||||||
|
_ROLE_NAMES=('cid','state','initiator','capacity','can_send','can_receive',
|
||||||
|
'l_csv_delat','r_csv_delay','send_frozen','receive_frozen',
|
||||||
|
'type','node_id','funding_tx')
|
||||||
|
_ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + len(_ROLE_NAMES))
|
||||||
|
_ROLE_MAP = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))
|
||||||
|
_ROLE_RMAP = dict(zip(_ROLE_NAMES, _ROLE_KEYS))
|
||||||
|
|
||||||
|
def rowCount(self, index):
|
||||||
|
return len(self.tx_history)
|
||||||
|
|
||||||
|
def roleNames(self):
|
||||||
|
return self._ROLE_MAP
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
tx = self.tx_history[index.row()]
|
||||||
|
role_index = role - Qt.UserRole
|
||||||
|
value = tx[self._ROLE_NAMES[role_index]]
|
||||||
|
if isinstance(value, (bool, list, int, str, QEAmount)) or value is None:
|
||||||
|
return value
|
||||||
|
if isinstance(value, Satoshis):
|
||||||
|
return value.value
|
||||||
|
if isinstance(value, QEAmount):
|
||||||
|
return value
|
||||||
|
return str(value)
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def init_model(self):
|
||||||
|
if not self.wallet.lnworker:
|
||||||
|
self._logger.warning('lnworker should be defined')
|
||||||
|
return
|
||||||
|
|
||||||
|
channels = self.wallet.lnworker.channels
|
||||||
|
self._logger.debug(repr(channels))
|
||||||
|
#channels = list(lnworker.channels.values()) if lnworker else []
|
||||||
160
electrum/gui/qml/qechannelopener.py
Normal file
160
electrum/gui/qml/qechannelopener.py
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
||||||
|
|
||||||
|
from electrum.logging import get_logger
|
||||||
|
from electrum.util import format_time
|
||||||
|
from electrum.lnutil import extract_nodeid, ConnStringFormatError
|
||||||
|
from electrum.gui import messages
|
||||||
|
|
||||||
|
from .qewallet import QEWallet
|
||||||
|
from .qetypes import QEAmount
|
||||||
|
|
||||||
|
class QEChannelOpener(QObject):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
_logger = get_logger(__name__)
|
||||||
|
|
||||||
|
_wallet = None
|
||||||
|
_nodeid = None
|
||||||
|
_amount = QEAmount()
|
||||||
|
_valid = False
|
||||||
|
_opentx = None
|
||||||
|
|
||||||
|
validationError = pyqtSignal([str,str], arguments=['code','message'])
|
||||||
|
conflictingBackup = pyqtSignal([str], arguments=['message'])
|
||||||
|
|
||||||
|
walletChanged = pyqtSignal()
|
||||||
|
@pyqtProperty(QEWallet, notify=walletChanged)
|
||||||
|
def wallet(self):
|
||||||
|
return self._wallet
|
||||||
|
|
||||||
|
@wallet.setter
|
||||||
|
def wallet(self, wallet: QEWallet):
|
||||||
|
if self._wallet != wallet:
|
||||||
|
self._wallet = wallet
|
||||||
|
self.walletChanged.emit()
|
||||||
|
|
||||||
|
nodeidChanged = pyqtSignal()
|
||||||
|
@pyqtProperty(str, notify=nodeidChanged)
|
||||||
|
def nodeid(self):
|
||||||
|
return self._nodeid
|
||||||
|
|
||||||
|
@nodeid.setter
|
||||||
|
def nodeid(self, nodeid: str):
|
||||||
|
if self._nodeid != nodeid:
|
||||||
|
self._logger.debug('nodeid set -> %s' % nodeid)
|
||||||
|
self._nodeid = nodeid
|
||||||
|
self.nodeidChanged.emit()
|
||||||
|
self.validate()
|
||||||
|
|
||||||
|
amountChanged = pyqtSignal()
|
||||||
|
@pyqtProperty(QEAmount, notify=amountChanged)
|
||||||
|
def amount(self):
|
||||||
|
return self._amount
|
||||||
|
|
||||||
|
@amount.setter
|
||||||
|
def amount(self, amount: QEAmount):
|
||||||
|
if self._amount != amount:
|
||||||
|
self._amount = amount
|
||||||
|
self.amountChanged.emit()
|
||||||
|
self.validate()
|
||||||
|
|
||||||
|
validChanged = pyqtSignal()
|
||||||
|
@pyqtProperty(bool, notify=validChanged)
|
||||||
|
def valid(self):
|
||||||
|
return self._valid
|
||||||
|
|
||||||
|
openTxChanged = pyqtSignal()
|
||||||
|
@pyqtProperty(bool, notify=openTxChanged)
|
||||||
|
def openTx(self):
|
||||||
|
return self._opentx
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
nodeid_valid = False
|
||||||
|
if self._nodeid:
|
||||||
|
try:
|
||||||
|
self._node_pubkey, self._host_port = extract_nodeid(self._nodeid)
|
||||||
|
nodeid_valid = True
|
||||||
|
except ConnStringFormatError as e:
|
||||||
|
self.validationError.emit('invalid_nodeid', repr(e))
|
||||||
|
|
||||||
|
if not nodeid_valid:
|
||||||
|
self._valid = False
|
||||||
|
self.validChanged.emit()
|
||||||
|
return
|
||||||
|
|
||||||
|
self._logger.debug('amount=%s' % str(self._amount))
|
||||||
|
if not self._amount or not (self._amount.satsInt > 0 or self._amount.isMax):
|
||||||
|
self._valid = False
|
||||||
|
self.validChanged.emit()
|
||||||
|
return
|
||||||
|
|
||||||
|
self._valid = True
|
||||||
|
self.validChanged.emit()
|
||||||
|
|
||||||
|
# FIXME "max" button in amount_dialog should enforce LN_MAX_FUNDING_SAT
|
||||||
|
@pyqtSlot()
|
||||||
|
@pyqtSlot(bool)
|
||||||
|
def open_channel(self, confirm_backup_conflict=False):
|
||||||
|
if not self.valid:
|
||||||
|
return
|
||||||
|
|
||||||
|
#if self.use_gossip:
|
||||||
|
#conn_str = self.pubkey
|
||||||
|
#if self.ipport:
|
||||||
|
#conn_str += '@' + self.ipport.strip()
|
||||||
|
#else:
|
||||||
|
#conn_str = str(self.trampolines[self.pubkey])
|
||||||
|
amount = '!' if self._amount.isMax else self._amount.satsInt
|
||||||
|
|
||||||
|
lnworker = self._wallet.wallet.lnworker
|
||||||
|
if lnworker.has_conflicting_backup_with(node_pubkey) and not confirm_backup_conflict:
|
||||||
|
self.conflictingBackup.emit(messages.MGS_CONFLICTING_BACKUP_INSTANCE)
|
||||||
|
return
|
||||||
|
|
||||||
|
coins = self._wallet.wallet.get_spendable_coins(None, nonlocal_only=True)
|
||||||
|
#node_id, rest = extract_nodeid(conn_str)
|
||||||
|
make_tx = lambda rbf: lnworker.mktx_for_open_channel(
|
||||||
|
coins=coins,
|
||||||
|
funding_sat=amount,
|
||||||
|
node_id=self._node_pubkey,
|
||||||
|
fee_est=None)
|
||||||
|
#on_pay = lambda tx: self.app.protected('Create a new channel?', self.do_open_channel, (tx, conn_str))
|
||||||
|
#d = ConfirmTxDialog(
|
||||||
|
#self.app,
|
||||||
|
#amount = amount,
|
||||||
|
#make_tx=make_tx,
|
||||||
|
#on_pay=on_pay,
|
||||||
|
#show_final=False)
|
||||||
|
#d.open()
|
||||||
|
|
||||||
|
#def do_open_channel(self, funding_tx, conn_str, password):
|
||||||
|
## read funding_sat from tx; converts '!' to int value
|
||||||
|
#funding_sat = funding_tx.output_value_for_address(ln_dummy_address())
|
||||||
|
#lnworker = self.app.wallet.lnworker
|
||||||
|
#try:
|
||||||
|
#chan, funding_tx = lnworker.open_channel(
|
||||||
|
#connect_str=conn_str,
|
||||||
|
#funding_tx=funding_tx,
|
||||||
|
#funding_sat=funding_sat,
|
||||||
|
#push_amt_sat=0,
|
||||||
|
#password=password)
|
||||||
|
#except Exception as e:
|
||||||
|
#self.app.logger.exception("Problem opening channel")
|
||||||
|
#self.app.show_error(_('Problem opening channel: ') + '\n' + repr(e))
|
||||||
|
#return
|
||||||
|
## TODO: it would be nice to show this before broadcasting
|
||||||
|
#if chan.has_onchain_backup():
|
||||||
|
#self.maybe_show_funding_tx(chan, funding_tx)
|
||||||
|
#else:
|
||||||
|
#title = _('Save backup')
|
||||||
|
#help_text = _(messages.MSG_CREATED_NON_RECOVERABLE_CHANNEL)
|
||||||
|
#data = lnworker.export_channel_backup(chan.channel_id)
|
||||||
|
#popup = QRDialog(
|
||||||
|
#title, data,
|
||||||
|
#show_text=False,
|
||||||
|
#text_for_clipboard=data,
|
||||||
|
#help_text=help_text,
|
||||||
|
#close_button_text=_('OK'),
|
||||||
|
#on_close=lambda: self.maybe_show_funding_tx(chan, funding_tx))
|
||||||
|
#popup.open()
|
||||||
@@ -17,6 +17,7 @@ from electrum.invoices import (Invoice, InvoiceError,
|
|||||||
from .qeinvoicelistmodel import QEInvoiceListModel, QERequestListModel
|
from .qeinvoicelistmodel import QEInvoiceListModel, QERequestListModel
|
||||||
from .qetransactionlistmodel import QETransactionListModel
|
from .qetransactionlistmodel import QETransactionListModel
|
||||||
from .qeaddresslistmodel import QEAddressListModel
|
from .qeaddresslistmodel import QEAddressListModel
|
||||||
|
from .qechannellistmodel import QEChannelListModel
|
||||||
from .qetypes import QEAmount
|
from .qetypes import QEAmount
|
||||||
|
|
||||||
class QEWallet(QObject):
|
class QEWallet(QObject):
|
||||||
@@ -60,6 +61,7 @@ class QEWallet(QObject):
|
|||||||
self._addressModel = QEAddressListModel(wallet)
|
self._addressModel = QEAddressListModel(wallet)
|
||||||
self._requestModel = QERequestListModel(wallet)
|
self._requestModel = QERequestListModel(wallet)
|
||||||
self._invoiceModel = QEInvoiceListModel(wallet)
|
self._invoiceModel = QEInvoiceListModel(wallet)
|
||||||
|
self._channelModel = None
|
||||||
|
|
||||||
self._historyModel.init_model()
|
self._historyModel.init_model()
|
||||||
self._requestModel.init_model()
|
self._requestModel.init_model()
|
||||||
@@ -192,6 +194,13 @@ class QEWallet(QObject):
|
|||||||
def invoiceModel(self):
|
def invoiceModel(self):
|
||||||
return self._invoiceModel
|
return self._invoiceModel
|
||||||
|
|
||||||
|
channelModelChanged = pyqtSignal()
|
||||||
|
@pyqtProperty(QEChannelListModel, notify=channelModelChanged)
|
||||||
|
def channelModel(self):
|
||||||
|
if self._channelModel is None:
|
||||||
|
self._channelModel = QEChannelListModel(self.wallet)
|
||||||
|
return self._channelModel
|
||||||
|
|
||||||
nameChanged = pyqtSignal()
|
nameChanged = pyqtSignal()
|
||||||
@pyqtProperty('QString', notify=nameChanged)
|
@pyqtProperty('QString', notify=nameChanged)
|
||||||
def name(self):
|
def name(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user