2023-07-17 10:49:06 +02:00
import QtQuick
import QtQuick . Layouts
import QtQuick . Controls
import QtQuick . Controls . Material
2022-07-28 16:52:01 +02:00
import org . electrum 1.0
import "../controls"
WizardComponent {
id: root
2023-04-29 13:45:28 +02:00
securePage: true
2022-07-28 16:52:01 +02:00
valid: false
2022-11-10 00:41:29 +01:00
property int cosigner: 0
property int participants: 0
2023-10-23 15:30:56 +02:00
property string multisigMasterPubkey
2022-11-10 00:41:29 +01:00
2022-10-24 13:04:46 +02:00
function apply ( ) {
2022-11-29 11:28:59 +01:00
applyMasterKey ( masterkey_ta . text )
}
function applyMasterKey ( key ) {
key = key . trim ( )
2022-11-10 00:41:29 +01:00
if ( cosigner ) {
2022-11-29 11:28:59 +01:00
wizard_data [ 'multisig_cosigner_data' ] [ cosigner . toString ( ) ] [ 'master_key' ] = key
2022-11-10 00:41:29 +01:00
} else {
2022-11-29 11:28:59 +01:00
wizard_data [ 'master_key' ] = key
2022-11-10 00:41:29 +01:00
}
2022-07-28 16:52:01 +02:00
}
function verifyMasterKey ( key ) {
2022-11-10 11:13:21 +01:00
valid = false
validationtext . text = ''
2022-11-29 11:28:59 +01:00
key = key . trim ( )
2022-11-10 11:13:21 +01:00
2023-10-23 15:30:56 +02:00
if ( ! key ) {
validationtext . text = ''
return false
}
2022-11-29 11:28:59 +01:00
if ( ! bitcoin . verifyMasterKey ( key , wizard_data [ 'wallet_type' ] ) ) {
2022-11-14 14:37:05 +01:00
validationtext . text = qsTr ( 'Error: invalid master key' )
2022-11-10 11:13:21 +01:00
return false
2022-11-14 14:37:05 +01:00
}
2022-11-10 11:13:21 +01:00
if ( cosigner ) {
2022-11-29 11:28:59 +01:00
applyMasterKey ( key )
2023-05-11 09:55:19 +00:00
if ( wiz . hasDuplicateMasterKeys ( wizard_data ) ) {
2022-11-10 11:13:21 +01:00
validationtext . text = qsTr ( 'Error: duplicate master public key' )
return false
}
2023-05-11 09:55:19 +00:00
if ( wiz . hasHeterogeneousMasterKeys ( wizard_data ) ) {
validationtext . text = qsTr ( 'Error: master public key types do not match' )
return false
}
2022-11-10 11:13:21 +01:00
}
return valid = true
2022-07-28 16:52:01 +02:00
}
ColumnLayout {
width: parent . width
2022-11-28 17:42:29 +01:00
Label {
2023-02-09 01:13:05 +01:00
Layout.fillWidth: true
2022-11-28 17:42:29 +01:00
visible: cosigner
text: qsTr ( 'Here is your master public key. Please share it with your cosigners' )
wrapMode: Text . Wrap
}
2026-02-21 16:25:53 +01:00
DialogHighlightPane {
2022-11-28 17:42:29 +01:00
Layout.fillWidth: true
2023-02-09 01:13:05 +01:00
visible: cosigner
2022-11-28 17:42:29 +01:00
RowLayout {
width: parent . width
Label {
Layout.fillWidth: true
text: multisigMasterPubkey
font.pixelSize: constants . fontSizeMedium
font.family: FixedFont
wrapMode: Text . Wrap
}
ToolButton {
icon.source: '../../../icons/share.png'
icon.color: 'transparent'
onClicked: {
2023-04-24 13:34:05 +02:00
var dialog = app . genericShareDialog . createObject ( app , {
title: qsTr ( 'Master public key' ) ,
text: multisigMasterPubkey
} )
2022-11-28 17:42:29 +01:00
dialog . open ( )
}
}
}
}
Rectangle {
2023-04-21 14:50:08 +02:00
Layout.fillWidth: true
2022-11-28 17:42:29 +01:00
Layout.preferredHeight: 1
Layout.topMargin: constants . paddingLarge
Layout.bottomMargin: constants . paddingLarge
visible: cosigner
color: Material . accentColor
}
2022-11-10 00:41:29 +01:00
Label {
text: qsTr ( 'Cosigner #%1 of %2' ) . arg ( cosigner ) . arg ( participants )
visible: cosigner
}
Label {
2023-04-21 14:50:08 +02:00
Layout.fillWidth: true
2022-11-29 11:28:59 +01:00
text: cosigner
2024-11-13 14:42:46 +01:00
? [ qsTr ( 'Please enter the master public key (xpub) of your cosigner.' ) ,
qsTr ( 'Enter their master private key (xprv) if you want to be able to sign for them.' )
] . join ( '\n' )
: [ qsTr ( 'Please enter your master private key (xprv).' ) ,
qsTr ( 'You can also enter a public key (xpub) here, but be aware you will then create a watch-only wallet if all cosigners are added using public keys' )
] . join ( '\n' )
2023-04-21 14:50:08 +02:00
wrapMode: Text . Wrap
2022-11-10 00:41:29 +01:00
}
2022-07-28 16:52:01 +02:00
RowLayout {
2023-11-15 18:28:44 +01:00
ElTextArea {
2022-07-28 16:52:01 +02:00
id: masterkey_ta
Layout.fillWidth: true
2023-11-15 18:28:44 +01:00
Layout.minimumHeight: 160
2022-11-14 14:37:05 +01:00
font.family: FixedFont
2022-07-28 16:52:01 +02:00
wrapMode: TextEdit . WrapAnywhere
2022-11-29 11:28:59 +01:00
onTextChanged: {
2024-01-30 02:11:01 +00:00
if ( anyActiveFocus ) {
2022-11-29 11:28:59 +01:00
verifyMasterKey ( text )
2024-01-30 02:11:01 +00:00
}
2022-11-29 11:28:59 +01:00
}
2023-04-29 13:42:10 +02:00
inputMethodHints: Qt . ImhSensitiveData | Qt . ImhNoPredictiveText | Qt . ImhNoAutoUppercase
2023-11-15 18:28:44 +01:00
background: PaneInsetBackground {
baseColor: constants . darkerDialogBackground
}
2022-07-28 16:52:01 +02:00
}
ColumnLayout {
2023-11-15 18:28:44 +01:00
Layout.alignment: Qt . AlignTop
2022-07-28 16:52:01 +02:00
ToolButton {
icon.source: '../../../icons/paste.png'
icon.height: constants . iconSizeMedium
icon.width: constants . iconSizeMedium
onClicked: {
2022-11-29 11:28:59 +01:00
if ( verifyMasterKey ( AppController . clipboardToText ( ) ) )
masterkey_ta . text = AppController . clipboardToText ( )
else
masterkey_ta . text = ''
2022-07-28 16:52:01 +02:00
}
}
ToolButton {
icon.source: '../../../icons/qrcode.png'
icon.height: constants . iconSizeMedium
icon.width: constants . iconSizeMedium
scale: 1.2
onClicked: {
2023-04-24 13:34:05 +02:00
var dialog = app . scanDialog . createObject ( app , {
hint: cosigner
? qsTr ( 'Scan a cosigner master public key' )
: qsTr ( 'Scan a master key' )
} )
2025-07-22 14:18:43 +02:00
dialog . onFoundText . connect ( function ( data ) {
if ( verifyMasterKey ( data ) )
masterkey_ta . text = data
2022-11-29 11:28:59 +01:00
else
masterkey_ta . text = ''
2023-04-24 13:34:05 +02:00
dialog . close ( )
2022-07-28 16:52:01 +02:00
} )
2023-04-24 13:34:05 +02:00
dialog . open ( )
2022-07-28 16:52:01 +02:00
}
}
}
}
2022-11-10 00:41:29 +01:00
TextArea {
id: validationtext
2022-11-10 11:13:21 +01:00
visible: text
2022-11-10 00:41:29 +01:00
Layout.fillWidth: true
readOnly: true
wrapMode: TextInput . WordWrap
background: Rectangle {
color: 'transparent'
}
}
2022-07-28 16:52:01 +02:00
}
Bitcoin {
id: bitcoin
2023-10-23 15:30:56 +02:00
onValidationMessageChanged: {
validationtext . text = validationMessage
}
2022-07-28 16:52:01 +02:00
}
2022-11-10 00:41:29 +01:00
Component.onCompleted: {
if ( wizard_data [ 'wallet_type' ] == 'multisig' ) {
if ( 'multisig_current_cosigner' in wizard_data )
cosigner = wizard_data [ 'multisig_current_cosigner' ]
participants = wizard_data [ 'multisig_participants' ]
2023-10-23 15:30:56 +02:00
if ( 'multisig_master_pubkey' in wizard_data ) {
multisigMasterPubkey = wizard_data [ 'multisig_master_pubkey' ]
}
2022-11-10 00:41:29 +01:00
}
2023-01-02 17:00:40 +01:00
Qt . callLater ( masterkey_ta . forceActiveFocus )
2022-11-10 00:41:29 +01:00
}
2022-07-28 16:52:01 +02:00
}