2023-07-17 10:49:06 +02:00
import QtQuick
import QtQuick . Controls
import QtQuick . Layouts
import QtQuick . Controls . Material
import QtQml
2021-04-01 19:54:53 +02:00
2022-09-23 12:14:19 +02:00
import org . electrum 1.0
import "controls"
2021-04-01 19:54:53 +02:00
Item {
2022-09-23 12:14:19 +02:00
id: mainView
2021-04-06 01:53:46 +02:00
2023-03-02 12:54:59 +01:00
property string title: Daemon . currentWallet ? Daemon.currentWallet.name : qsTr ( 'no wallet loaded' )
2021-04-01 19:54:53 +02:00
2023-10-26 11:17:22 +02:00
property var _sendDialog
2023-02-27 12:20:51 +01:00
property string _intentUri
2022-10-18 18:31:59 +02:00
2023-03-18 10:56:25 +01:00
property string _request_amount
property string _request_description
property string _request_expiry
2023-03-17 23:02:43 +01:00
2022-10-04 16:33:22 +02:00
function openInvoice ( key ) {
2023-04-04 16:13:00 +02:00
invoice . key = key
var dialog = invoiceDialog . createObject ( app , { invoice: invoice } )
2022-10-04 16:33:22 +02:00
dialog . open ( )
return dialog
}
2023-02-24 14:47:28 +01:00
function openRequest ( key ) {
var dialog = receiveDialog . createObject ( app , { key: key } )
dialog . open ( )
return dialog
}
2022-10-18 18:31:59 +02:00
function openSendDialog ( ) {
2023-10-26 11:17:22 +02:00
// Qt based send dialog if not on android
if ( ! AppController . isAndroid ( ) ) {
_sendDialog = qtSendDialog . createObject ( mainView , { invoiceParser: invoiceParser } )
_sendDialog . open ( )
return
}
// Android based send dialog if on android
2023-10-11 11:02:40 +00:00
var scanner = app . scanDialog . createObject ( mainView , {
2024-06-10 15:07:02 +02:00
hint: Daemon . currentWallet . isLightning
? qsTr ( 'Scan an Invoice, an Address, an LNURL-pay, a PSBT or a Channel Backup' )
: qsTr ( 'Scan an Invoice, an Address, an LNURL-pay or a PSBT' )
2023-10-11 11:02:40 +00:00
} )
scanner . onFound . connect ( function ( ) {
var data = scanner . scanData
data = data . trim ( )
if ( bitcoin . isRawTx ( data ) ) {
app . stack . push ( Qt . resolvedUrl ( 'TxDetails.qml' ) , { rawtx: data } )
} else if ( Daemon . currentWallet . isValidChannelBackup ( data ) ) {
var dialog = app . messageDialog . createObject ( app , {
2024-06-10 15:07:02 +02:00
title: qsTr ( 'Import Channel Backup?' ) ,
2023-10-11 11:02:40 +00:00
yesno: true
} )
dialog . accepted . connect ( function ( ) {
Daemon . currentWallet . importChannelBackup ( data )
} )
dialog . open ( )
} else {
invoiceParser . recipient = data
}
//scanner.destroy() // TODO
} )
scanner . open ( )
2022-10-18 18:31:59 +02:00
}
2023-10-26 11:17:22 +02:00
function closeSendDialog ( ) {
if ( ! AppController . isAndroid ( ) ) {
if ( _sendDialog ) {
_sendDialog . doClose ( )
_sendDialog = null
}
}
}
2022-10-18 18:31:59 +02:00
function restartSendDialog ( ) {
2023-10-26 11:17:22 +02:00
if ( ! AppController . isAndroid ( ) ) {
if ( _sendDialog ) {
_sendDialog . restart ( )
}
return
} else {
openSendDialog ( )
}
2022-10-18 18:31:59 +02:00
}
2023-03-31 10:49:36 +02:00
function showExport ( data , helptext ) {
2023-03-30 12:26:28 +02:00
var dialog = exportTxDialog . createObject ( app , {
2023-03-31 10:49:36 +02:00
text: data [ 0 ] ,
text_qr: data [ 1 ] ,
text_help: helptext ,
text_warn: data [ 2 ]
? ''
2023-11-13 11:35:30 +01:00
: [ qsTr ( 'Warning: Some data (prev txs / "full utxos") was left out of the QR code as it would not fit.' ) ,
qsTr ( 'This might cause issues if signing offline.' ) ,
qsTr ( 'As a workaround, copy to clipboard or use the Share option instead.' ) ] . join ( ' ' )
2023-03-30 12:26:28 +02:00
} )
dialog . open ( )
}
2025-03-24 12:10:41 +01:00
function payOnchain ( invoicedialog , invoice ) {
2023-09-01 15:02:17 +02:00
var dialog = confirmPaymentDialog . createObject ( mainView , {
address: invoice . address ,
satoshis: invoice . amountOverride . isEmpty
? invoice . amount
: invoice . amountOverride ,
message: invoice . message
} )
var canComplete = ! Daemon . currentWallet . isWatchOnly && Daemon . currentWallet . canSignWithoutCosigner
dialog . accepted . connect ( function ( ) {
if ( ! canComplete ) {
if ( Daemon . currentWallet . isWatchOnly ) {
dialog . finalizer . saveOrShow ( )
} else {
dialog . finalizer . sign ( )
}
} else {
2025-03-24 12:10:41 +01:00
// store txid in invoicedialog so the dialog can detect broadcast success
invoicedialog . broadcastTxid = dialog . finalizer . finalizedTxid
2023-09-01 15:02:17 +02:00
dialog . finalizer . signAndSend ( )
}
} )
dialog . open ( )
}
2025-02-23 12:21:41 +01:00
function createRequest ( lightning , reuse_address ) {
2023-10-26 11:17:22 +02:00
var qamt = Config . unitsToSats ( _request_amount )
2025-02-23 12:21:41 +01:00
Daemon . currentWallet . createRequest ( qamt , _request_description , _request_expiry , lightning , reuse_address )
2023-10-26 11:17:22 +02:00
}
2024-09-17 13:22:05 +02:00
function startSweep ( ) {
var dialog = sweepDialog . createObject ( app )
dialog . accepted . connect ( function ( ) {
var finalizerDialog = confirmSweepDialog . createObject ( mainView , {
privateKeys: dialog . privateKeys ,
message: qsTr ( 'Sweep transaction' ) ,
showOptions: false ,
amountLabelText: qsTr ( 'Total sweep amount' ) ,
2025-04-05 12:25:20 +02:00
sendButtonText: Daemon . currentWallet . isWatchOnly
? qsTr ( 'Sweep...' )
: qsTr ( 'Sweep' )
2024-09-17 13:22:05 +02:00
} )
finalizerDialog . accepted . connect ( function ( ) {
2024-10-09 17:45:40 +02:00
if ( Daemon . currentWallet . isWatchOnly ) {
var confirmdialog = app . messageDialog . createObject ( mainView , {
title: qsTr ( 'Confirm Sweep' ) ,
text: qsTr ( 'Current wallet is watch-only. You might not be able to spend from these addresses.\n\nAre you sure?' ) ,
yesno: true
} )
confirmdialog . accepted . connect ( function ( ) {
finalizerDialog . finalizer . send ( )
close ( )
} )
confirmdialog . open ( )
return
}
2024-09-17 13:22:05 +02:00
console . log ( "Sending sweep transaction" )
finalizerDialog . finalizer . send ( )
} )
finalizerDialog . open ( )
} )
dialog . open ( )
}
2021-04-05 12:24:45 +02:00
property QtObject menu: Menu {
2023-04-24 17:24:22 +02:00
id: menu
2022-10-31 17:17:44 +01:00
parent: Overlay . overlay
dim: true
2023-01-06 14:05:49 +01:00
modal: true
Overlay.modal: Rectangle {
2022-10-31 17:17:44 +01:00
color: "#44000000"
}
2023-11-15 17:35:08 +01:00
property int implicitChildrenWidth: 64
width: implicitChildrenWidth + 60 + constants . paddingLarge
2023-03-02 10:49:01 +01:00
2022-03-23 13:59:46 +01:00
MenuItem {
2023-04-17 15:35:39 +02:00
icon.color: action . enabled ? 'transparent' : Material . iconDisabledColor
icon.source: '../../icons/wallet.png'
2022-03-23 13:59:46 +01:00
action: Action {
2023-03-02 10:49:01 +01:00
text: qsTr ( 'Wallet details' )
2023-04-17 15:35:39 +02:00
enabled: Daemon . currentWallet && app . stack . currentItem . objectName != 'WalletDetails'
2023-03-02 12:54:59 +01:00
onTriggered: menu . openPage ( Qt . resolvedUrl ( 'WalletDetails.qml' ) )
2022-05-12 16:53:44 +02:00
}
}
MenuItem {
2023-04-17 15:35:39 +02:00
icon.color: action . enabled ? 'transparent' : Material . iconDisabledColor
icon.source: '../../icons/tab_addresses.png'
2022-03-23 13:59:46 +01:00
action: Action {
2023-11-01 17:17:16 +01:00
text: qsTr ( 'Addresses/Coins' ) ;
2023-03-02 12:54:59 +01:00
onTriggered: menu . openPage ( Qt . resolvedUrl ( 'Addresses.qml' ) ) ;
2023-04-17 15:35:39 +02:00
enabled: Daemon . currentWallet && app . stack . currentItem . objectName != 'Addresses'
2022-03-23 13:59:46 +01:00
}
}
2022-05-10 17:11:16 +02:00
MenuItem {
2023-04-17 15:35:39 +02:00
icon.color: action . enabled ? 'transparent' : Material . iconDisabledColor
icon.source: '../../icons/lightning.png'
2022-05-10 17:11:16 +02:00
action: Action {
2023-03-02 12:54:59 +01:00
text: qsTr ( 'Channels' ) ;
2023-04-17 15:35:39 +02:00
enabled: Daemon . currentWallet && Daemon . currentWallet . isLightning && app . stack . currentItem . objectName != 'Channels'
2023-03-02 12:54:59 +01:00
onTriggered: menu . openPage ( Qt . resolvedUrl ( 'Channels.qml' ) )
2022-05-10 17:11:16 +02:00
}
}
2023-09-25 15:35:47 +02:00
MenuItem {
icon.color: action . enabled ? 'transparent' : Material . iconDisabledColor
icon.source: '../../icons/pen.png'
action: Action {
text: Daemon . currentWallet . canSignMessage
? qsTr ( 'Sign/Verify Message' )
: qsTr ( 'Verify Message' )
onTriggered: {
var dialog = app . signVerifyMessageDialog . createObject ( app )
dialog . open ( )
menu . deselect ( )
}
}
}
2024-09-17 13:22:05 +02:00
MenuItem {
icon.color: action . enabled ? 'transparent' : Material . iconDisabledColor
2024-10-08 12:16:19 +02:00
icon.source: '../../icons/sweep.png'
2024-09-17 13:22:05 +02:00
action: Action {
2025-04-05 12:25:20 +02:00
text: qsTr ( 'Sweep key(s)' )
2024-09-17 13:22:05 +02:00
onTriggered: {
startSweep ( )
menu . deselect ( )
}
}
}
2023-03-02 12:54:59 +01:00
MenuSeparator { }
MenuItem {
2023-04-17 15:35:39 +02:00
icon.color: action . enabled ? 'transparent' : Material . iconDisabledColor
icon.source: '../../icons/file.png'
2023-03-02 12:54:59 +01:00
action: Action {
2023-04-17 15:35:39 +02:00
text: qsTr ( 'Other wallets' )
enabled: app . stack . currentItem . objectName != 'Wallets'
2023-03-02 12:54:59 +01:00
onTriggered: menu . openPage ( Qt . resolvedUrl ( 'Wallets.qml' ) )
2023-03-02 10:49:01 +01:00
}
2023-03-02 12:54:59 +01:00
}
function openPage ( url ) {
stack . pushOnRoot ( url )
2023-09-25 15:35:47 +02:00
deselect ( )
}
function deselect ( ) {
2022-03-23 13:59:46 +01:00
currentIndex = - 1
}
2023-11-15 17:35:08 +01:00
// determine widest element and store in implicitChildrenWidth
function updateImplicitWidth ( ) {
for ( let i = 0 ; i < menu . count ; i ++ ) {
var item = menu . itemAt ( i )
var txt = item . text
var txtwidth = fontMetrics . advanceWidth ( txt )
if ( txtwidth > menu . implicitChildrenWidth ) {
menu . implicitChildrenWidth = txtwidth
}
}
}
FontMetrics {
id: fontMetrics
font: menu . font
}
Component.onCompleted: updateImplicitWidth ( )
2022-03-11 13:19:51 +01:00
}
ColumnLayout {
2023-01-27 14:54:45 +01:00
anchors.fill: parent
2023-02-23 21:49:23 +01:00
spacing: 0
2023-01-27 14:54:45 +01:00
History {
id: history
visible: Daemon . currentWallet
Layout.fillWidth: true
Layout.fillHeight: true
2022-03-11 13:19:51 +01:00
}
2023-01-27 14:54:45 +01:00
ColumnLayout {
2022-03-11 13:19:51 +01:00
Layout.alignment: Qt . AlignHCenter
2023-01-27 14:54:45 +01:00
Layout.fillHeight: true
spacing: 2 * constants . paddingXLarge
visible: ! Daemon . currentWallet
Item {
Layout.fillHeight: true
2023-01-09 18:16:07 +01:00
}
2023-01-27 14:54:45 +01:00
Label {
Layout.alignment: Qt . AlignHCenter
text: qsTr ( 'No wallet loaded' )
font.pixelSize: constants . fontSizeXXLarge
}
Pane {
Layout.alignment: Qt . AlignHCenter
padding: 0
background: Rectangle {
color: Material . dialogColor
}
FlatButton {
text: qsTr ( 'Open/Create Wallet' )
icon.source: '../../icons/wallet.png'
onClicked: {
if ( Daemon . availableWallets . rowCount ( ) > 0 ) {
stack . push ( Qt . resolvedUrl ( 'Wallets.qml' ) )
} else {
var newww = app . newWalletWizard . createObject ( app )
newww . walletCreated . connect ( function ( ) {
Daemon . availableWallets . reload ( )
// and load the new wallet
2023-04-25 13:40:16 +02:00
Daemon . loadWallet ( newww . path , newww . wizard_data [ 'password' ] )
2023-01-27 14:54:45 +01:00
} )
newww . open ( )
}
2023-01-09 18:16:07 +01:00
}
2022-10-04 15:09:37 +02:00
}
2022-03-11 13:19:51 +01:00
}
2023-01-27 14:54:45 +01:00
Item {
Layout.fillHeight: true
}
2022-09-23 12:14:19 +02:00
}
2023-02-03 13:33:17 +01:00
ButtonContainer {
2023-02-23 21:49:23 +01:00
id: buttonContainer
2023-02-03 13:33:17 +01:00
Layout.fillWidth: true
2022-09-23 12:14:19 +02:00
FlatButton {
2023-02-23 21:49:23 +01:00
id: receiveButton
2023-01-27 14:54:45 +01:00
visible: Daemon . currentWallet
2022-09-23 12:14:19 +02:00
Layout.fillWidth: true
Layout.preferredWidth: 1
2022-09-27 09:55:06 +02:00
icon.source: '../../icons/tab_receive.png'
2022-09-23 12:14:19 +02:00
text: qsTr ( 'Receive' )
onClicked: {
2023-03-18 10:56:25 +01:00
var dialog = receiveDetailsDialog . createObject ( mainView )
2022-09-23 12:14:19 +02:00
dialog . open ( )
2021-04-07 16:50:34 +02:00
}
2023-03-30 15:16:23 +02:00
onPressAndHold: {
2023-04-03 10:26:03 +02:00
Config . userKnowsPressAndHold = true
2023-04-25 13:33:15 +02:00
Daemon . currentWallet . deleteExpiredRequests ( )
2023-03-30 15:16:23 +02:00
app . stack . push ( Qt . resolvedUrl ( 'ReceiveRequests.qml' ) )
2023-04-04 16:13:00 +02:00
AppController . haptic ( )
2023-03-30 15:16:23 +02:00
}
2021-04-07 16:50:34 +02:00
}
2023-01-17 16:32:40 +01:00
FlatButton {
2023-01-27 14:54:45 +01:00
visible: Daemon . currentWallet
2023-01-17 16:32:40 +01:00
Layout.fillWidth: true
Layout.preferredWidth: 1
icon.source: '../../icons/tab_send.png'
text: qsTr ( 'Send' )
2023-11-15 13:36:36 +01:00
enabled: ! invoiceParser . busy
2023-01-17 16:32:40 +01:00
onClicked: openSendDialog ( )
2023-03-30 15:16:23 +02:00
onPressAndHold: {
2023-04-03 10:27:33 +02:00
Config . userKnowsPressAndHold = true
2023-03-30 15:16:23 +02:00
app . stack . push ( Qt . resolvedUrl ( 'Invoices.qml' ) )
2023-04-04 16:13:00 +02:00
AppController . haptic ( )
2023-03-30 15:16:23 +02:00
}
2023-01-17 16:32:40 +01:00
}
2022-09-23 12:14:19 +02:00
}
}
2021-04-01 19:54:53 +02:00
2023-04-04 16:13:00 +02:00
Invoice {
id: invoice
wallet: Daemon . currentWallet
}
2022-09-23 12:14:19 +02:00
InvoiceParser {
id: invoiceParser
wallet: Daemon . currentWallet
2023-09-27 21:05:26 +02:00
onValidationError: ( code , message ) = > {
var dialog = app . messageDialog . createObject ( app , {
2023-11-15 13:36:36 +01:00
title: qsTr ( 'Error' ) ,
2023-12-19 12:17:54 +01:00
iconSource: Qt . resolvedUrl ( '../../icons/warning.png' ) ,
2023-09-27 21:05:26 +02:00
text: message
} )
2022-09-27 15:09:06 +02:00
dialog . closed . connect ( function ( ) {
2022-10-18 18:31:59 +02:00
restartSendDialog ( )
2022-09-27 15:09:06 +02:00
} )
2022-09-23 12:14:19 +02:00
dialog . open ( )
}
2023-09-27 21:05:26 +02:00
onValidationWarning: ( code , message ) = > {
2022-09-23 12:14:19 +02:00
if ( code == 'no_channels' ) {
2023-09-27 21:05:26 +02:00
var dialog = app . messageDialog . createObject ( app , {
text: message
} )
2023-04-25 22:23:24 +00:00
dialog . closed . connect ( function ( ) {
restartSendDialog ( )
} )
2022-09-23 12:14:19 +02:00
dialog . open ( )
// TODO: ask user to open a channel, if funds allow
// and maybe store invoice if expiry allows
}
}
onValidationSuccess: {
2023-10-26 11:17:22 +02:00
closeSendDialog ( )
2023-09-27 21:05:26 +02:00
var dialog = invoiceDialog . createObject ( app , {
invoice: invoiceParser ,
payImmediately: invoiceParser . isLnurlPay
} )
2022-09-27 17:10:05 +02:00
dialog . open ( )
2022-09-23 12:14:19 +02:00
}
2023-09-27 21:05:26 +02:00
onInvoiceCreateError: ( code , message ) = > {
console . log ( code + ' ' + message )
}
2021-04-07 16:50:34 +02:00
2022-09-28 18:05:45 +02:00
onLnurlRetrieved: {
2023-10-26 11:17:22 +02:00
closeSendDialog ( )
2023-09-27 21:05:26 +02:00
var dialog = lnurlPayDialog . createObject ( app , {
invoiceParser: invoiceParser
} )
2022-09-28 18:05:45 +02:00
dialog . open ( )
}
2023-09-27 21:05:26 +02:00
onLnurlError: ( code , message ) = > {
var dialog = app . messageDialog . createObject ( app , {
title: qsTr ( 'Error' ) ,
2023-12-19 12:17:54 +01:00
iconSource: Qt . resolvedUrl ( '../../icons/warning.png' ) ,
text: message
} )
2023-03-31 13:21:11 +02:00
dialog . open ( )
}
2022-09-23 12:14:19 +02:00
}
2023-10-11 11:02:40 +00:00
Bitcoin {
id: bitcoin
}
2022-10-18 18:31:59 +02:00
Connections {
target: AppController
function onUriReceived ( uri ) {
2023-02-27 12:20:51 +01:00
console . log ( 'uri received: ' + uri )
if ( ! Daemon . currentWallet ) {
console . log ( 'No wallet open, deferring' )
_intentUri = uri
return
}
2022-10-18 18:31:59 +02:00
invoiceParser . recipient = uri
}
}
2023-02-27 12:20:51 +01:00
Connections {
target: Daemon
function onWalletLoaded ( ) {
2025-03-24 20:20:55 +01:00
infobanner . hide ( ) // start hidden when switching wallets
2023-02-27 14:42:26 +01:00
if ( _intentUri ) {
2023-02-27 12:20:51 +01:00
invoiceParser . recipient = _intentUri
2023-02-27 14:42:26 +01:00
_intentUri = ''
}
2023-02-27 12:20:51 +01:00
}
}
2023-03-17 23:02:43 +01:00
Connections {
target: Daemon . currentWallet
function onRequestCreateSuccess ( key ) {
2023-03-18 10:56:25 +01:00
openRequest ( key )
2023-03-17 23:02:43 +01:00
}
2023-03-31 10:19:43 +02:00
function onRequestCreateError ( error ) {
console . log ( error )
2023-12-19 12:17:54 +01:00
var dialog = app . messageDialog . createObject ( app , {
title: qsTr ( 'Error' ) ,
iconSource: Qt . resolvedUrl ( '../../icons/warning.png' ) ,
text: error
} )
2023-03-17 23:02:43 +01:00
dialog . open ( )
}
2023-03-13 18:22:51 +01:00
function onOtpRequested ( ) {
console . log ( 'OTP requested' )
var dialog = otpDialog . createObject ( mainView )
dialog . open ( )
}
2023-03-10 13:31:41 +01:00
function onBroadcastFailed ( txid , code , message ) {
var dialog = app . messageDialog . createObject ( app , {
2023-12-19 12:17:54 +01:00
title: qsTr ( 'Error' ) ,
iconSource: Qt . resolvedUrl ( '../../icons/warning.png' ) ,
2023-03-10 13:31:41 +01:00
text: message
} )
dialog . open ( )
}
2023-05-15 11:56:40 +02:00
function onPaymentFailed ( invoice_id , message ) {
var dialog = app . messageDialog . createObject ( app , {
2023-12-19 12:17:54 +01:00
title: qsTr ( 'Error' ) ,
iconSource: Qt . resolvedUrl ( '../../icons/warning.png' ) ,
2025-01-17 13:02:28 +01:00
text: message ? message : qsTr ( 'Payment failed' )
2023-05-15 11:56:40 +02:00
} )
dialog . open ( )
}
2023-08-10 14:46:00 +00:00
function onImportChannelBackupFailed ( message ) {
2023-12-19 12:17:54 +01:00
var dialog = app . messageDialog . createObject ( app , {
title: qsTr ( 'Error' ) ,
iconSource: Qt . resolvedUrl ( '../../icons/warning.png' ) ,
text: message
} )
2023-08-10 14:46:00 +00:00
dialog . open ( )
}
2025-03-24 20:20:55 +01:00
function onBalanceChanged ( ) {
// ln low reserve warning
if ( Daemon . currentWallet . isLowReserve ) {
var message = [
qsTr ( 'You do not have enough on-chain funds to protect your Lightning channels.' ) ,
qsTr ( 'You should have at least %1 on-chain in order to be able to sweep channel outputs.' ) . arg ( Config . formatSats ( Config . lnUtxoReserve ) + ' ' + Config . baseUnit )
] . join ( ' ' )
infobanner . show ( message , function ( ) {
var dialog = app . messageDialog . createObject ( app , {
text: message + '\n\n' + qsTr ( 'Do you want to perform a swap?' ) ,
yesno: true
} )
dialog . accepted . connect ( function ( ) {
app . startSwap ( )
} )
dialog . open ( )
} )
} else {
infobanner . hide ( )
}
}
2023-03-10 13:31:41 +01:00
}
2022-09-23 12:14:19 +02:00
Component {
id: invoiceDialog
2022-09-26 15:41:16 +02:00
InvoiceDialog {
2023-03-30 12:26:28 +02:00
id: _invoiceDialog
2022-09-27 15:09:06 +02:00
width: parent . width
height: parent . height
2022-09-26 15:41:16 +02:00
onDoPay: {
2023-09-01 15:02:17 +02:00
var lninvoiceButPayOnchain = false
if ( invoice . invoiceType == Invoice . LightningInvoice && invoice . address ) {
// ln invoice with fallback
var amountToSend = invoice . amountOverride . isEmpty
? invoice . amount . satsInt
: invoice . amountOverride . satsInt
if ( amountToSend > Daemon . currentWallet . lightningCanSend . satsInt ) {
lninvoiceButPayOnchain = true
}
}
2023-09-01 15:08:01 +02:00
if ( invoice . invoiceType == Invoice . OnchainInvoice ) {
2025-03-24 12:10:41 +01:00
payOnchain ( _invoiceDialog , invoice )
2022-09-26 15:41:16 +02:00
} else if ( invoice . invoiceType == Invoice . LightningInvoice ) {
2023-09-01 15:08:01 +02:00
if ( lninvoiceButPayOnchain ) {
var dialog = app . messageDialog . createObject ( mainView , {
title: qsTr ( 'Insufficient balance to pay over Lightning. Pay on-chain instead?' ) ,
yesno: true
} )
dialog . accepted . connect ( function ( ) {
2025-03-24 12:10:41 +01:00
payOnchain ( _invoiceDialog , invoice )
2023-09-01 15:08:01 +02:00
} )
dialog . open ( )
} else {
console . log ( 'About to pay lightning invoice' )
invoice . payLightningInvoice ( )
}
2021-04-07 16:50:34 +02:00
}
2021-04-06 01:53:46 +02:00
}
2023-01-13 21:26:10 +01:00
2022-09-27 15:09:06 +02:00
onClosed: destroy ( )
2023-03-30 12:26:28 +02:00
Connections {
target: Daemon . currentWallet
function onSaveTxSuccess ( txid ) {
_invoiceDialog . close ( )
}
}
2021-04-06 01:53:46 +02:00
}
2022-09-23 12:14:19 +02:00
}
2022-09-26 15:41:16 +02:00
2023-10-26 11:17:22 +02:00
Component {
id: qtSendDialog
SendDialog {
width: parent . width
height: parent . height
2024-06-10 15:07:02 +02:00
onTxFound: ( data ) = > {
2023-10-26 11:17:22 +02:00
app . stack . push ( Qt . resolvedUrl ( 'TxDetails.qml' ) , { rawtx: data } )
close ( )
}
2024-06-10 15:07:02 +02:00
onChannelBackupFound: ( data ) = > {
if ( ! Daemon . currentWallet . isLightning ) {
var dialog = app . messageDialog . createObject ( app , {
title: qsTr ( 'Cannot import Channel Backup, Lightning not enabled.' )
} )
dialog . open ( )
return
}
2023-10-26 11:17:22 +02:00
var dialog = app . messageDialog . createObject ( app , {
2024-06-10 15:07:02 +02:00
title: qsTr ( 'Import Channel Backup?' ) ,
2023-10-26 11:17:22 +02:00
yesno: true
} )
dialog . accepted . connect ( function ( ) {
Daemon . currentWallet . importChannelBackup ( data )
close ( )
} )
dialog . rejected . connect ( function ( ) {
close ( )
} )
dialog . open ( )
}
onClosed: destroy ( )
}
2023-03-17 23:02:43 +01:00
}
Component {
2023-03-18 10:56:25 +01:00
id: receiveDetailsDialog
2023-03-17 23:02:43 +01:00
ReceiveDetailsDialog {
2023-03-18 10:56:25 +01:00
id: _receiveDetailsDialog
2023-03-17 23:02:43 +01:00
width: parent . width * 0.9
anchors.centerIn: parent
onAccepted: {
console . log ( 'accepted' )
2023-03-18 10:56:25 +01:00
_request_amount = _receiveDetailsDialog . amount
_request_description = _receiveDetailsDialog . description
_request_expiry = _receiveDetailsDialog . expiry
2025-02-23 12:21:41 +01:00
createRequest ( _receiveDetailsDialog . isLightning , false )
2023-03-17 23:02:43 +01:00
}
onRejected: {
console . log ( 'rejected' )
}
2023-03-18 10:56:25 +01:00
onClosed: destroy ( )
2023-03-30 12:26:28 +02:00
}
2023-03-17 23:02:43 +01:00
}
2022-09-27 09:55:06 +02:00
Component {
id: receiveDialog
ReceiveDialog {
2022-09-27 11:43:28 +02:00
width: parent . width
height: parent . height
2022-09-27 09:55:06 +02:00
onClosed: destroy ( )
}
}
2022-09-23 12:14:19 +02:00
Component {
id: confirmPaymentDialog
ConfirmTxDialog {
2023-01-13 21:26:10 +01:00
id: _confirmPaymentDialog
2022-09-23 12:14:19 +02:00
title: qsTr ( 'Confirm Payment' )
finalizer: TxFinalizer {
wallet: Daemon . currentWallet
2023-01-03 22:52:09 +01:00
canRbf: true
2023-09-27 21:05:26 +02:00
onFinished: ( signed , saved , complete ) = > {
2023-04-21 15:09:33 +02:00
if ( ! complete ) {
var msg
if ( wallet . isWatchOnly ) {
// tx created in watchonly wallet. Show QR for signer(s)
if ( wallet . isMultisig ) {
msg = qsTr ( 'Transaction created. Present this QR code to one of the co-cigners or signing devices' )
} else {
msg = qsTr ( 'Transaction created. Present this QR code to the signing device' )
}
} else {
if ( signed ) {
msg = qsTr ( 'Transaction created and partially signed by this wallet. Present this QR code to the next co-signer' )
} else {
msg = qsTr ( 'Transaction created but not signed by this wallet yet. Sign the transaction and present this QR code to the next co-signer' )
}
}
showExport ( getSerializedTx ( ) , msg )
2023-03-30 12:26:28 +02:00
}
2023-01-13 22:39:01 +01:00
_confirmPaymentDialog . destroy ( )
}
2024-10-23 12:02:01 +02:00
onSignError: ( message ) = > {
var dialog = app . messageDialog . createObject ( mainView , {
title: qsTr ( 'Error' ) ,
text: [ qsTr ( 'Could not sign tx' ) , message ] . join ( '\n\n' ) ,
iconSource: '../../../icons/warning.png'
} )
dialog . open ( )
}
2022-06-14 11:54:32 +02:00
}
2025-03-24 12:10:41 +01:00
2023-02-10 13:28:27 +01:00
// TODO: lingering confirmPaymentDialogs can raise exceptions in
// the child finalizer when currentWallet disappears, but we need
// it long enough for the finalizer to finish..
// onClosed: destroy()
2022-06-14 11:54:32 +02:00
}
2021-04-06 01:53:46 +02:00
}
2021-04-07 16:50:34 +02:00
2024-09-17 13:22:05 +02:00
Component {
id: confirmSweepDialog
ConfirmTxDialog {
id: _confirmSweepDialog
property string privateKeys
title: qsTr ( 'Confirm Sweep' )
satoshis: MAX
finalizer: SweepFinalizer {
wallet: Daemon . currentWallet
canRbf: true
privateKeys: _confirmSweepDialog . privateKeys
}
}
}
2022-09-28 18:05:45 +02:00
Component {
id: lnurlPayDialog
LnurlPayRequestDialog {
width: parent . width * 0.9
anchors.centerIn: parent
onClosed: destroy ( )
}
}
2022-09-29 18:05:06 +02:00
Component {
id: otpDialog
OtpDialog {
2022-09-30 15:40:05 +02:00
width: parent . width * 2 / 3
2022-09-29 18:05:06 +02:00
anchors.centerIn: parent
onClosed: destroy ( )
}
}
2023-03-30 12:26:28 +02:00
Component {
id: exportTxDialog
ExportTxDialog {
onClosed: destroy ( )
}
}
2024-09-17 13:22:05 +02:00
Component {
id: sweepDialog
SweepDialog {
onClosed: destroy ( )
}
}
2021-04-01 19:54:53 +02:00
}