Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert2cc #7700

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
cc903e3
initial POC via plugin
Feb 20, 2022
995c253
handle chmod unavailable; refactor
Feb 20, 2022
c5830c2
fix single sig related issues
Feb 21, 2022
f5db121
case where client has no device
Feb 21, 2022
6584a72
POC for direct USB multisig wallet import
Feb 23, 2022
e1f08f9
Merge branch 'spesmilo:master' into convert2cc
scgbckbone Feb 27, 2022
3497b7e
add convert2cc plugin (initial POC)
Mar 1, 2022
652bc51
typecheck client selected by keystore - check if plugin types match
Mar 2, 2022
2f20d4c
Merge branch 'master' of https://github.com/scgbckbone/electrum into …
Mar 4, 2022
0d3b2f0
change way to get cc client
Mar 4, 2022
6713b1f
remove lost comment
Mar 4, 2022
9404068
close opened cc clients when done with them
Mar 4, 2022
5d4dcbf
always add convert2cc button if plugin is active; new error modal to …
Mar 5, 2022
bd7bb75
descriptions
Mar 6, 2022
68623c6
more descriptions; refactor
Mar 6, 2022
6d9b06b
handle coldcard with connection already open; do not send client to c…
Mar 7, 2022
9d64f8f
revert os.chmod as it is covered in other PR
Mar 7, 2022
c048f29
expose msg when coldcard is plugged in but cannot connect to it (used…
Mar 7, 2022
465b129
add ability to disable buttons in ChoicesLayout; refactor dialog for …
Mar 7, 2022
46ce92f
use electrum CKCCClients if available
Mar 9, 2022
bc98438
add warning for encrypted wallets
Mar 9, 2022
51df1b5
add ability to preserve encryption settings (pwd/hww) during convert2cc
Mar 10, 2022
f98e70e
do not show unpaired icon - only paired; enable device (ckcc-protocol…
Mar 10, 2022
c211f04
Merge branch 'master' of https://github.com/scgbckbone/electrum into …
Mar 14, 2022
01f9006
scaled to width seems to have no effect - removing
Mar 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 15 additions & 8 deletions electrum/gui/qt/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
import csv
from decimal import Decimal
import base64
from functools import partial
from functools import partial, reduce
import operator
import queue
import asyncio
from typing import Optional, TYPE_CHECKING, Sequence, List, Union
Expand Down Expand Up @@ -593,15 +594,16 @@ def on_cb(x):
if cb_checked:
self.config.set_key('dont_show_testnet_warning', True)

def open_wallet(self):
def open_wallet(self, filename=None):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add ability to skip getOpenFileName dialog if filename is provided

try:
wallet_folder = self.get_wallet_folder()
except FileNotFoundError as e:
self.show_error(str(e))
return
filename, __ = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder)
if not filename:
return
filename, __ = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder)
if not filename:
return
self.gui_object.new_window(filename)

def select_backup_dir(self, b):
Expand Down Expand Up @@ -2471,6 +2473,7 @@ def show_wallet_info(self):
seed_available += f" ({ks.get_seed_type()})"
keystore_types = [k.get_type_text() for k in self.wallet.get_keystores()]
grid = QGridLayout()
# this can be changed to self.wallet.storage.basename()
basename = os.path.basename(self.wallet.storage.path)
grid.addWidget(WWLabel(_("Wallet name")+ ':'), 0, 0)
grid.addWidget(WWLabel(basename), 0, 1)
Expand Down Expand Up @@ -2571,17 +2574,21 @@ def label(idx, ks):
ks_vbox.addWidget(WWLabel(_("Master Public Key")))
ks_vbox.addWidget(mpk_text)
ks_vbox.addLayout(der_path_hbox)

ks_stack.addWidget(ks_w)

select_ks(0)
vbox.addWidget(ks_stack)

vbox.addStretch(1)
btn_export_info = run_hook('wallet_info_buttons', self, dialog)
wallet_info_btns = run_hook('wallet_info_buttons', self, dialog)
btn_close = CloseButton(dialog)
btns = Buttons(btn_export_info, btn_close)
vbox.addLayout(btns)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar to https://github.com/spesmilo/electrum/pull/7682/files where we need an ability to add multiple buttons to wallet information dialog

if wallet_info_btns:
# now more than one wallet_info_butons hook, needs concat
wallet_info_btns = reduce(operator.concat, wallet_info_btns)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now we also expect more than one hook to provide data

buttons = Buttons(*wallet_info_btns, btn_close)
else:
buttons = Buttons(btn_close)
vbox.addLayout(buttons)
dialog.setLayout(vbox)
dialog.exec_()

Expand Down
14 changes: 12 additions & 2 deletions electrum/gui/qt/util.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import asyncio
import json
import os.path
import time
import sys
Expand Down Expand Up @@ -388,7 +389,7 @@ def text_dialog(
return txt.toPlainText()

class ChoicesLayout(object):
def __init__(self, msg, choices, on_clicked=None, checked_index=0):
def __init__(self, msg, choices, on_clicked=None, checked_index=0, disable_buttons=False):
vbox = QVBoxLayout()
if len(msg) > 50:
vbox.addWidget(WWLabel(msg))
Expand All @@ -402,12 +403,21 @@ def __init__(self, msg, choices, on_clicked=None, checked_index=0):
self.group = group = QButtonGroup()
for i,c in enumerate(choices):
button = QRadioButton(gb2)
button.setText(c)
if isinstance(c, tuple):
# tuple of text, icon path
logo = QIcon()
logo.addPixmap(QPixmap(icon_path(c[1])))
button.setText(c[0])
button.setIcon(logo)
else:
button.setText(c)
vbox2.addWidget(button)
group.addButton(button)
group.setId(button, i)
if i==checked_index:
button.setChecked(True)
if disable_buttons:
button.setEnabled(False)

if on_clicked:
group.buttonClicked.connect(partial(on_clicked, self))
Expand Down
2 changes: 2 additions & 0 deletions electrum/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ def run_hook(name, *args):
results.append(r)

if results:
if name == "wallet_info_buttons":
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure If I understand this constraint - why can only one result from hook be accepted? Here I expect more than one hook to provide data

return results
assert len(results) == 1, results
return results[0]

Expand Down
1 change: 1 addition & 0 deletions electrum/plugins/coldcard/coldcard.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Coldcard Electrum plugin main code.
#
#
import copy
import os, time, io
import traceback
from typing import TYPE_CHECKING, Optional
Expand Down
20 changes: 13 additions & 7 deletions electrum/plugins/coldcard/qt.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import time, os
from functools import partial
import copy
import json

from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtWidgets import QPushButton, QLabel, QVBoxLayout, QWidget, QGridLayout
from PyQt5.QtWidgets import QPushButton, QLabel, QVBoxLayout, QWidget, QGridLayout, QHBoxLayout

from electrum.gui.qt.util import (WindowModalDialog, CloseButton, Buttons, getOpenFileName,
getSaveFileName)
getSaveFileName, WWLabel)
from electrum.gui.qt.transaction_dialog import TxDialog
from electrum.gui.qt.main_window import ElectrumWindow

Expand Down Expand Up @@ -47,19 +47,25 @@ def show_address(keystore=keystore):
def wallet_info_buttons(self, main_window, dialog):
# user is about to see the "Wallet Information" dialog
# - add a button if multisig wallet, and a Coldcard is a cosigner.
buttons = []
wallet = main_window.wallet

if type(wallet) is not Multisig_Wallet:
return

if not any(type(ks) == self.keystore_class for ks in wallet.get_keystores()):
coldcard_keystores = [
ks
for ks in wallet.get_keystores()
if type(ks) == self.keystore_class
]
if not coldcard_keystores:
# doesn't involve a Coldcard wallet, hide feature
return

btn = QPushButton(_("Export for Coldcard"))
btn.clicked.connect(lambda unused: self.export_multisig_setup(main_window, wallet))

return btn
buttons.append(btn)
return buttons

def export_multisig_setup(self, main_window, wallet):

Expand All @@ -73,7 +79,7 @@ def export_multisig_setup(self, main_window, wallet):
config=self.config,
)
if fileName:
with open(fileName, "wt") as f:
with open(fileName, "w") as f:
ColdcardPlugin.export_ms_wallet(wallet, f, basename)
main_window.show_message(_("Wallet setup file exported successfully"))

Expand Down
6 changes: 6 additions & 0 deletions electrum/plugins/convert2cc/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from electrum.i18n import _

fullname = _('convert2cc')
description = _('Provides support for converting hardware wallet to Coldcard')
requires = [('ckcc', 'github.com/Coldcard/ckcc-protocol')]
available_for = ['qt']