blue wallet export option

This commit is contained in:
scgbckbone 2026-02-24 02:13:50 +01:00 committed by doc-hex
parent e914fd8f03
commit 271599fde6
4 changed files with 23 additions and 18 deletions

View File

@ -15,6 +15,7 @@ This lists the new changes that have not yet been published in a normal release.
- Bugfix: Replace `/` with `-` in exported file names of multisig wallet export artifacts.
- Enhancement: Show the BIP-39 passphrase on-screen (must scroll down) once new key is in effect.
- Enhancement: New "Buried Settings" menu, inside Settings menu, for rarely-applied settings.
- Enhancement: Add `Blue Wallet` option to `Export Wallet`
# Mk Specific Changes

View File

@ -1132,19 +1132,21 @@ async def export_xpub(label, _2, item):
await show_qr_code(xpub, False)
def electrum_export_story(background=False):
def electrum_export_story(noun="Electrum", background=False):
# saves memory being in a function
return ('''\
This saves a skeleton Electrum wallet file. \
You can then open that file in Electrum without ever connecting this Coldcard to a computer.\n
'''
This saves a skeleton %s wallet file. \
You can then open that file in the wallet without ever connecting this Coldcard to a computer.\n
''' % noun
+ (background or 'Choose an address type for the wallet on the next screen.'+PICK_ACCOUNT)
+ SENSITIVE_NOT_SECRET)
async def electrum_skeleton(*a):
async def electrum_skeleton(a, b, item):
# save xpub, and some other public details into a file: NOT MULTISIG
title = item.arg
fname_pat = "new-%s.json" % title.lower()
ch = await ux_show_story(electrum_export_story(), escape='1')
ch = await ux_show_story(electrum_export_story(title), escape='1')
account_num = 0
if ch == '1':
@ -1154,7 +1156,7 @@ async def electrum_skeleton(*a):
rv = [
MenuItem(chains.addr_fmt_label(af), f=electrum_skeleton_step2,
arg=(af, account_num))
arg=(af, account_num, title, fname_pat))
for af in chains.SINGLESIG_AF
]
the_ux.push(MenuSystem(rv))
@ -1301,10 +1303,10 @@ without ever connecting this Coldcard to a computer.\
async def electrum_skeleton_step2(_1, _2, item):
# pick a semi-random file name, render and save it.
addr_fmt, account_num = item.arg
await export_contents('Electrum wallet',
addr_fmt, account_num, title, fname_pat = item.arg
await export_contents(title + " wallet",
lambda: generate_electrum_wallet(addr_fmt, account_num),
"new-electrum.json", is_json=True)
fname_pat, is_json=True)
async def _generic_export(prompt, label, f_pattern):
# like the Multisig export, make a single JSON file with

View File

@ -229,14 +229,15 @@ WalletExportMenu = [
MenuItem("Nunchuk", f=named_generic_skeleton, arg="Nunchuk"),
MenuItem("Bull Bitcoin", f=ss_descriptor_skeleton,
arg=(True, [AF_P2WPKH], "", "bull-bitcoin.txt", KEY_QR)),
MenuItem("Zeus", f=ss_descriptor_skeleton,
arg=(True, [AF_P2WPKH, AF_P2WPKH_P2SH], "Zeus Wallet", "zeus-export.txt", None)),
MenuItem("Electrum Wallet", f=electrum_skeleton),
MenuItem("Blue Wallet", f=electrum_skeleton, arg="Blue"),
MenuItem("Electrum Wallet", f=electrum_skeleton, arg="Electrum"),
MenuItem("Wasabi Wallet", f=wasabi_skeleton),
MenuItem("Fully Noded", f=named_generic_skeleton, arg="Fully Noded"),
MenuItem("Unchained", f=unchained_capital_export),
MenuItem("Theya", f=named_generic_skeleton, arg="Theya"),
MenuItem("Bitcoin Safe", f=named_generic_skeleton, arg="Bitcoin Safe"),
MenuItem("Zeus", f=ss_descriptor_skeleton,
arg=(True, [AF_P2WPKH, AF_P2WPKH_P2SH], "Zeus Wallet", "zeus-export.txt", None)),
MenuItem("Samourai Postmix", f=samourai_post_mix_descriptor_export),
MenuItem("Samourai Premix", f=samourai_pre_mix_descriptor_export),
# MenuItem("Samourai BadBank", f=samourai_bad_bank_descriptor_export), # not released yet

View File

@ -258,12 +258,13 @@ def test_export_wasabi(way, dev, pick_menu_item, goto_home, cap_story, press_sel
@pytest.mark.parametrize('mode', [ "Classic P2PKH", "P2SH-Segwit", "Segwit P2WPKH"])
@pytest.mark.parametrize('acct_num', [ None, '0', '9897'])
@pytest.mark.parametrize('acct_num', [ None, '9897'])
@pytest.mark.parametrize('way', ["sd", "vdisk", "nfc", "qr"])
@pytest.mark.parametrize('testnet', [True, False])
@pytest.mark.parametrize('name', ["Electrum"])#, "Blue"]) # same tests, not needed
def test_export_electrum(way, dev, mode, acct_num, pick_menu_item, goto_home, cap_story, need_keypress,
microsd_path, nfc_read_json, virtdisk_path, use_mainnet, testnet, load_export,
press_select, skip_if_useless_way, expect_acctnum_captured):
press_select, skip_if_useless_way, expect_acctnum_captured, name):
# lightly test electrum wallet export
skip_if_useless_way(way)
@ -279,12 +280,12 @@ def test_export_electrum(way, dev, mode, acct_num, pick_menu_item, goto_home, ca
pick_menu_item('Advanced/Tools')
pick_menu_item('File Management')
pick_menu_item('Export Wallet')
pick_menu_item('Electrum Wallet')
pick_menu_item(f'{name} Wallet')
time.sleep(0.1)
title, story = cap_story()
assert 'This saves a skeleton Electrum wallet' in story
assert f'This saves a skeleton {name} wallet' in story
assert 'Press (1) to' in story
if acct_num is not None:
@ -300,7 +301,7 @@ def test_export_electrum(way, dev, mode, acct_num, pick_menu_item, goto_home, ca
expect_acctnum_captured(acct_num)
obj = load_export(way, label="Electrum wallet", is_json=True, addr_fmt=af)
obj = load_export(way, label=f"{name} wallet", is_json=True, addr_fmt=af)
ks = obj['keystore']
assert ks['ckcc_xfp'] == simulator_fixed_xfp