add wallet type imported addresses/private keys to wizard
This commit is contained in:
@@ -153,9 +153,14 @@ Pane {
|
||||
Label { text: 'has Seed'; color: Material.accentColor }
|
||||
Label { text: Daemon.currentWallet.hasSeed }
|
||||
|
||||
Label { Layout.columnSpan:4; text: qsTr('Master Public Key'); color: Material.accentColor }
|
||||
Label {
|
||||
visible: Daemon.currentWallet.masterPubkey
|
||||
Layout.columnSpan:4; text: qsTr('Master Public Key'); color: Material.accentColor
|
||||
}
|
||||
|
||||
TextHighlightPane {
|
||||
visible: Daemon.currentWallet.masterPubkey
|
||||
|
||||
Layout.columnSpan: 4
|
||||
Layout.fillWidth: true
|
||||
padding: 0
|
||||
|
||||
102
electrum/gui/qml/components/wizard/WCImport.qml
Normal file
102
electrum/gui/qml/components/wizard/WCImport.qml
Normal file
@@ -0,0 +1,102 @@
|
||||
import QtQuick 2.6
|
||||
import QtQuick.Layouts 1.0
|
||||
import QtQuick.Controls 2.1
|
||||
|
||||
import org.electrum 1.0
|
||||
|
||||
import "../controls"
|
||||
|
||||
WizardComponent {
|
||||
id: root
|
||||
|
||||
valid: false
|
||||
|
||||
onAccept: {
|
||||
if (bitcoin.isAddressList(import_ta.text)) {
|
||||
wizard_data['address_list'] = import_ta.text
|
||||
} else if (bitcoin.isPrivateKeyList(import_ta.text)) {
|
||||
wizard_data['private_key_list'] = import_ta.text
|
||||
}
|
||||
}
|
||||
|
||||
function verify(text) {
|
||||
return bitcoin.isAddressList(text) || bitcoin.isPrivateKeyList(text)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
width: parent.width
|
||||
|
||||
Label { text: qsTr('Import Bitcoin Addresses') }
|
||||
|
||||
InfoTextArea {
|
||||
text: qsTr('Enter a list of Bitcoin addresses (this will create a watching-only wallet), or a list of private keys.')
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
TextArea {
|
||||
id: import_ta
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumHeight: 80
|
||||
focus: true
|
||||
wrapMode: TextEdit.WrapAnywhere
|
||||
onTextChanged: valid = verify(text)
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
ToolButton {
|
||||
icon.source: '../../../icons/paste.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
onClicked: {
|
||||
if (verify(AppController.clipboardToText())) {
|
||||
if (import_ta.text != '')
|
||||
import_ta.text = import_ta.text + '\n'
|
||||
import_ta.text = import_ta.text + AppController.clipboardToText()
|
||||
}
|
||||
}
|
||||
}
|
||||
ToolButton {
|
||||
icon.source: '../../../icons/qrcode.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
scale: 1.2
|
||||
onClicked: {
|
||||
var scan = qrscan.createObject(root)
|
||||
scan.onFound.connect(function() {
|
||||
if (verify(scan.scanData)) {
|
||||
if (import_ta.text != '')
|
||||
import_ta.text = import_ta.text + ',\n'
|
||||
import_ta.text = import_ta.text + scan.scanData
|
||||
}
|
||||
scan.destroy()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: qrscan
|
||||
QRScan {
|
||||
width: root.width
|
||||
height: root.height
|
||||
|
||||
ToolButton {
|
||||
icon.source: '../../../icons/closebutton.png'
|
||||
icon.height: constants.iconSizeMedium
|
||||
icon.width: constants.iconSizeMedium
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
onClicked: {
|
||||
parent.destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Bitcoin {
|
||||
id: bitcoin
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,9 +38,8 @@ WizardComponent {
|
||||
text: qsTr('Multi-signature wallet')
|
||||
}
|
||||
RadioButton {
|
||||
enabled: false
|
||||
ButtonGroup.group: wallettypegroup
|
||||
property string wallettype: 'import'
|
||||
property string wallettype: 'imported'
|
||||
text: qsTr('Import Bitcoin addresses or private keys')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class QEAddressListModel(QAbstractListModel):
|
||||
def init_model(self):
|
||||
r_addresses = self.wallet.get_receiving_addresses()
|
||||
c_addresses = self.wallet.get_change_addresses()
|
||||
n_addresses = len(r_addresses) + len(c_addresses)
|
||||
n_addresses = len(r_addresses) + len(c_addresses) if self.wallet.use_change else 0
|
||||
|
||||
def insert_row(atype, alist, address, iaddr):
|
||||
item = self.addr_to_model(address)
|
||||
@@ -80,7 +80,7 @@ class QEAddressListModel(QAbstractListModel):
|
||||
insert_row('receive', self.receive_addresses, address, i)
|
||||
i = i + 1
|
||||
i = 0
|
||||
for address in c_addresses:
|
||||
for address in c_addresses if self.wallet.use_change else []:
|
||||
insert_row('change', self.change_addresses, address, i)
|
||||
i = i + 1
|
||||
self.endInsertRows()
|
||||
|
||||
@@ -164,3 +164,12 @@ class QEBitcoin(QObject):
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
@pyqtSlot(str, result=bool)
|
||||
def isAddressList(self, csv: str):
|
||||
return keystore.is_address_list(csv)
|
||||
|
||||
@pyqtSlot(str, result=bool)
|
||||
def isPrivateKeyList(self, csv: str):
|
||||
return keystore.is_private_key_list(csv)
|
||||
|
||||
|
||||
@@ -319,6 +319,8 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
|
||||
|
||||
@pyqtProperty(str, notify=dataChanged)
|
||||
def txinType(self):
|
||||
if self.wallet.wallet_type == 'imported':
|
||||
return self.wallet.txin_type
|
||||
return self.wallet.get_txin_type(self.wallet.dummy_address())
|
||||
|
||||
@pyqtProperty(bool, notify=dataChanged)
|
||||
@@ -342,6 +344,9 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
|
||||
keystores = self.wallet.get_keystores()
|
||||
if len(keystores) > 1:
|
||||
self._logger.debug('multiple keystores not supported yet')
|
||||
if len(keystores) == 0:
|
||||
self._logger.debug('no keystore')
|
||||
return ''
|
||||
return keystores[0].get_derivation_prefix()
|
||||
|
||||
@pyqtProperty(str, notify=dataChanged)
|
||||
|
||||
@@ -59,6 +59,7 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard):
|
||||
'have_seed': { 'gui': 'WCHaveSeed' },
|
||||
'bip39_refine': { 'gui': 'WCBIP39Refine' },
|
||||
'have_master_key': { 'gui': 'WCHaveMasterKey' },
|
||||
'imported': { 'gui': 'WCImport' },
|
||||
'wallet_password': { 'gui': 'WCWalletPassword' }
|
||||
})
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ from electrum.storage import WalletStorage, StorageEncryptionVersion
|
||||
from electrum.wallet_db import WalletDB
|
||||
from electrum.bip32 import normalize_bip32_derivation, xpub_type
|
||||
from electrum import keystore
|
||||
from electrum import bitcoin
|
||||
|
||||
class WizardViewState(NamedTuple):
|
||||
view: str
|
||||
@@ -162,6 +163,10 @@ class NewWalletWizard(AbstractWizard):
|
||||
'next': 'wallet_password',
|
||||
'last': self.last_if_single_password
|
||||
},
|
||||
'imported': {
|
||||
'next': 'wallet_password',
|
||||
'last': self.last_if_single_password
|
||||
},
|
||||
'wallet_password': {
|
||||
'last': True
|
||||
}
|
||||
@@ -180,10 +185,12 @@ class NewWalletWizard(AbstractWizard):
|
||||
return self.last_if_single_password(view, wizard_data) and not wizard_data['seed_type'] == 'bip39'
|
||||
|
||||
def on_wallet_type(self, wizard_data):
|
||||
if wizard_data['wallet_type'] == '2fa':
|
||||
return 'trustedcoin_start'
|
||||
|
||||
return 'keystore_type'
|
||||
t = wizard_data['wallet_type']
|
||||
return {
|
||||
'standard': 'keystore_type',
|
||||
'2fa': 'trustedcoin_start',
|
||||
'imported': 'imported'
|
||||
}.get(t)
|
||||
|
||||
def on_keystore_type(self, wizard_data):
|
||||
t = wizard_data['keystore_type']
|
||||
@@ -205,13 +212,28 @@ class NewWalletWizard(AbstractWizard):
|
||||
|
||||
def create_storage(self, path, data):
|
||||
# only standard and 2fa wallets for now
|
||||
assert data['wallet_type'] in ['standard', '2fa']
|
||||
assert data['wallet_type'] in ['standard', '2fa', 'imported']
|
||||
|
||||
if os.path.exists(path):
|
||||
raise Exception('file already exists at path')
|
||||
storage = WalletStorage(path)
|
||||
|
||||
if data['keystore_type'] in ['createseed', 'haveseed']:
|
||||
k = None
|
||||
if not 'keystore_type' in data:
|
||||
assert data['wallet_type'] == 'imported'
|
||||
addresses = {}
|
||||
if 'private_key_list' in data:
|
||||
k = keystore.Imported_KeyStore({})
|
||||
keys = keystore.get_private_keys(data['private_key_list'])
|
||||
for pk in keys:
|
||||
assert bitcoin.is_private_key(pk)
|
||||
txin_type, pubkey = k.import_privkey(pk, None)
|
||||
addr = bitcoin.pubkey_to_address(txin_type, pubkey)
|
||||
addresses[addr] = {'type': txin_type, 'pubkey': pubkey}
|
||||
elif 'address_list' in data:
|
||||
for addr in data['address_list'].split():
|
||||
addresses[addr] = {}
|
||||
elif data['keystore_type'] in ['createseed', 'haveseed']:
|
||||
if data['seed_type'] in ['old', 'standard', 'segwit']: #2fa, 2fa-segwit
|
||||
self._logger.debug('creating keystore from electrum seed')
|
||||
k = keystore.from_seed(data['seed'], data['seed_extra_words'], data['wallet_type'] == 'multisig')
|
||||
@@ -237,7 +259,7 @@ class NewWalletWizard(AbstractWizard):
|
||||
raise Exception('unsupported/unknown keystore_type %s' % data['keystore_type'])
|
||||
|
||||
if data['encrypt']:
|
||||
if k.may_have_password():
|
||||
if k and k.may_have_password():
|
||||
k.update_password(None, data['password'])
|
||||
storage.set_password(data['password'], enc_version=StorageEncryptionVersion.USER_PASSWORD)
|
||||
|
||||
@@ -255,8 +277,12 @@ class NewWalletWizard(AbstractWizard):
|
||||
db.put('x2/', data['x2/'])
|
||||
db.put('x3/', data['x3/'])
|
||||
db.put('use_trustedcoin', True)
|
||||
elif data['wallet_type'] == 'imported':
|
||||
if k:
|
||||
db.put('keystore', k.dump())
|
||||
db.put('addresses', addresses)
|
||||
|
||||
if k.can_have_deterministic_lightning_xprv():
|
||||
if k and k.can_have_deterministic_lightning_xprv():
|
||||
db.put('lightning_xprv', k.get_lightning_xprv(data['password'] if data['encrypt'] else None))
|
||||
|
||||
db.load_plugins()
|
||||
|
||||
Reference in New Issue
Block a user