larger QR during wallet exports

This commit is contained in:
Peter D. Gray 2024-03-27 11:11:40 -04:00
parent d963dab12a
commit c9641bcd55
No known key found for this signature in database
GPG Key ID: A2DCD558C2BE5D7C
4 changed files with 38 additions and 25 deletions

View File

@ -110,5 +110,9 @@
- Bugfix: base64 PSBT via QR was not properly decoded
- Bugfix: Fix inability to activate Duress Wallet as temporary seed
when master seed is 12 words
- Bugfix: Switch to BBQr for larger data exports at a new lower size threshold.
- generally, won't show tiny QR anymore with 1:1 pixel to module size.
- Sparrow wallet export will always be BBQr (if not saved to a card).
- most other exports fit into a reasonable QR (large / lower rez).
- Tweak: Default idle timeout when on battery, was reduced to 10 minutes from 30.
- Tweak: Cursor movements wrap around if menu is longer than screen height.

View File

@ -1058,7 +1058,6 @@ async def export_xpub(label, _2, item):
if glob.NFC and ch in '3'+KEY_NFC:
await glob.NFC.share_text(xpub)
else:
from ux import show_qr_code
await show_qr_code(xpub, False)
break
@ -1161,7 +1160,7 @@ async def samourai_account_descriptor(name, account_num):
ch = await ux_show_story(
ss_descriptor_export_story(
addition=" for Samourai %s account." % name,
background="\n")
background=" ")
)
if ch != 'y':

View File

@ -12,6 +12,21 @@ from auth import write_sig_file
from public_constants import AF_CLASSIC, AF_P2WPKH, AF_P2WPKH_P2SH, AF_P2WSH, AF_P2WSH_P2SH, AF_P2SH
from charcodes import KEY_NFC, KEY_CANCEL, KEY_QR
async def export_by_qr(body, label, is_json=False):
# render as QR and show on-screen
from ux import show_qr_code
try:
await show_qr_code(body, msg=label)
except ValueError:
if version.has_qwerty:
# do BBQr on Q
from ux_q1 import show_bbqr_codes
await show_bbqr_codes('J' if is_json else 'U', body, label)
# on Mk4, if too big ... just do nothing (but JSON should have fit?)
return
def generate_public_contents():
# Generate public details about wallet.
@ -119,7 +134,7 @@ async def write_text_file(fname_pattern, body, title, derive, addr_fmt):
# Export data as a text file.
from glob import dis, NFC
from files import CardSlot, CardMissingError, needs_microsd
from ux import import_export_prompt, show_qr_code
from ux import import_export_prompt
choice = await import_export_prompt("%s file" % title, is_import=False,
no_qr=(not version.has_qwerty))
@ -127,19 +142,12 @@ async def write_text_file(fname_pattern, body, title, derive, addr_fmt):
if choice == KEY_CANCEL:
return
elif choice == KEY_QR:
try:
await show_qr_code(body, msg=title)
except ValueError:
from ux_q1 import show_bbqr_codes
await show_bbqr_codes('U', body, title)
await export_by_qr(body, title)
return
elif choice == KEY_NFC:
await NFC.share_text(body)
return
# too big anyway
assert choice != KEY_QR
# choose a filename
try:
dis.fullscreen("Saving...")
@ -433,13 +441,16 @@ async def make_json_wallet(label, func, fname_pattern='new-wallet.json'):
from glob import dis, NFC
from files import CardSlot, CardMissingError, needs_microsd
from ux import import_export_prompt, show_qr_code
from ux import import_export_prompt
from qrs import MAX_V11_CHAR_LIMIT
dis.fullscreen('Generating...')
json_str, derive, addr_fmt = func()
skip_sig = derive is False and addr_fmt is False
choice = await import_export_prompt("%s file" % label, is_import=False)
choice = await import_export_prompt("%s file" % label, is_import=False,
no_qr=(not version.has_qwerty and len(json_str) >= MAX_V11_CHAR_LIMIT))
if choice == KEY_CANCEL:
return
elif choice == KEY_NFC:
@ -447,14 +458,9 @@ async def make_json_wallet(label, func, fname_pattern='new-wallet.json'):
return
elif choice == KEY_QR:
# render as QR and show on-screen
# - maybe block this option, if data too big to make it easy?
try:
await show_qr_code(json_str)
except ValueError:
if version.has_qwerty:
# do BBQr on Q
from ux_q1 import show_bbqr_codes
await show_bbqr_codes('J', json_str, label)
# - on mk4, this isn't offered if more than about 300 bytes because we can't
# show that as a single QR
await export_by_qr(json_str, label, is_json=True)
return
# choose a filename and save

View File

@ -12,7 +12,11 @@ from version import has_qwerty
# TODO: This class has a terrible API!
MAX_V40_SIZE = 4296
# Alnum limit for a single QR, in chars. Min error correction (L).
MAX_V40_SIZE = const(4296)
# Max in a V11 as bytes (not alnum) ... the limit on Mk4 screen
MAX_V11_CHAR_LIMIT = const(321)
class QRDisplaySingle(UserInteraction):
# Show a single QR code for (typically) a list of addresses, or a single value.
@ -35,8 +39,8 @@ class QRDisplaySingle(UserInteraction):
# - version=4..11 => single pixel per module
# - not really providing enough space around these, shrug
# - inverted QR (black/white swap) still readable by scanners, altho wrong
# - on Q: ver 25 => 117x117 is largest that can be pixel-doubled, can do
# v40 tho at 1:1, but most find that unreadable
# - on Q: ver 25 => 117x117 is largest that can be pixel-doubled
# - on Q: v40 is possible at at 1:1, but most find that unreadable, so avoid 1:1
if self.is_alnum:
# targeting 'alpha numeric' mode, nice and dense; caps only tho
enc = uqr.Mode_ALPHANUMERIC if not msg.isdigit() else uqr.Mode_NUMERIC
@ -47,7 +51,7 @@ class QRDisplaySingle(UserInteraction):
# can fail if not enough space in QR
self.qr_data = uqr.make(msg, min_version=2,
max_version=11 if not has_qwerty else 40,
max_version=11 if not has_qwerty else 25,
encoding=enc)
def redraw(self):