This commit is contained in:
scgbckbone 2025-04-10 10:52:53 +02:00 committed by doc-hex
parent 6a63c7bde9
commit c4b7260686
5 changed files with 87 additions and 58 deletions

View File

@ -1495,47 +1495,52 @@ async def qr_share_file(_1, _2, item):
return f.endswith('.psbt') or f.endswith('.txn') \
or f.endswith('.txt') or f.endswith(".json") or fname.endswith(".sig")
while 1:
txid = None
fn = await file_picker(min_size=10, max_size=MAX_TXN_LEN, taster=is_suitable)
if not fn: return
try:
while 1:
txid = None
fn = await file_picker(min_size=10, max_size=MAX_TXN_LEN, taster=is_suitable)
if not fn: return
basename = fn.split('/')[-1]
ext = fn.split('.')[-1].lower()
basename = fn.split('/')[-1]
ext = fn.split('.')[-1].lower()
try:
with CardSlot() as card:
with open(fn, 'rb') as fp:
data = fp.read()
try:
with CardSlot() as card:
with open(fn, 'rb') as fp:
data = fp.read()
except CardMissingError:
await needs_microsd()
return
except CardMissingError:
await needs_microsd()
return
if ext == "txn":
tc = "T"
txid = txid_from_fname(basename)
if data[2:8] == b'000000':
# it's a txn, and we wrote as hex
if ext == "txn":
tc = "T"
txid = txid_from_fname(basename)
if data[2:8] == b'000000':
# it's a txn, and we wrote as hex
data = data.decode()
else:
assert data[2:8] == bytes(6)
data = b2a_hex(data).decode()
elif data[0:5] == b'psbt\xff':
tc = "P"
elif data[0:6] in (b'cHNidP', b'707362'):
tc = "U"
data = data.decode().strip()
elif ext in ('txt', 'json', 'sig'):
tc = "U"
if ext == "json":
tc = "J"
data = data.decode()
else:
assert data[2:8] == bytes(6)
data = b2a_hex(data).decode()
elif data[0:5] == b'psbt\xff':
tc = "P"
elif data[0:6] in (b'cHNidP', b'707362'):
tc = "U"
data = data.decode().strip()
elif ext in ('txt', 'json', 'sig'):
tc = "U"
if ext == "json":
tc = "J"
data = data.decode()
else:
raise ValueError(ext)
await export_by_qr(data, txid, tc, force_bbqr=force_bbqr)
raise ValueError(ext)
await export_by_qr(data, txid, tc, force_bbqr=force_bbqr)
except Exception as e:
await ux_show_story(
title="ERROR",
msg="Failed to share file via QR.\n\n%s\n%s" % (e, problem_file_line(e))
)
async def nfc_share_file(*A):
# Share txt, txn and PSBT files over NFC.

View File

@ -856,6 +856,7 @@ async def done_signing(psbt, tx_req, input_method=None, filename=None,
if ok is None:
title = "Failed to Teleport"
else:
title = "Sent by Teleport"
_, num_sigs_needed = ok
if num_sigs_needed > 0:
s, aux = ("", "is") if num_sigs_needed == 1 else ("s", "are")

View File

@ -336,9 +336,8 @@ class OwnershipCache:
while 1:
ch = await ux_show_story(msg, title=title, escape=esc, hint_icons=KEY_QR)
if ch in ("1"+KEY_QR):
await show_qr_code(addr,
is_alnum=(wallet.addr_fmt & (AFC_BECH32 | AFC_BECH32M)),
msg=addr, is_addrs=True)
await show_qr_code(addr, msg=addr, is_addrs=True,
is_alnum=(wallet.addr_fmt & (AFC_BECH32 | AFC_BECH32M)))
elif not is_ms and (ch == "0"): # only singlesig
from msgsign import sign_with_own_address
await sign_with_own_address(sp, wallet.addr_fmt)

View File

@ -86,8 +86,8 @@ class QRDisplaySingle(UserInteraction):
msg = self.msg
else:
msg = None
if isinstance(body, str) and not has_qwerty:
# on Mk4 if no self.msg, we show part of the body
if isinstance(body, str):
# sanity check
msg = body
dis.draw_qr_display(self.qr_data, msg, self.is_alnum,

View File

@ -956,19 +956,47 @@ def test_custom_pushtx_url(goto_home, pick_menu_item, press_select, enter_comple
assert settings_get('ptxurl', None) is None
@pytest.mark.parametrize("fname,mode,ftype", [
("ccbk-start.json", "r", "J"),
("ckcc-backup.txt", "r", "U"),
("devils-txn.txn", "rb", "T"),
("example-change.psbt", "rb", "P"),
("sim_conso5.psbt", "rb", "P"), # binary psbt
("payjoin.psbt", "r", "U"), # base64 string in file
("worked-unsigned.psbt", "rb", "U"), # hex string psbt
("coldcard-export.json", "rb", "J"),
("coldcard-export.sig", "r", "U"),
@pytest.mark.parametrize("fname,ftype", [
("ccbk-start.json", "J"),
("ckcc-backup.txt", "U"),
("devils-txn.txn", "T"),
("example-change.psbt", "P"),
("sim_conso5.psbt", "P"), # binary psbt
("payjoin.psbt", "U"), # base64 string in file
("worked-unsigned.psbt", "U"), # hex string psbt
("coldcard-export.json", "J"),
("coldcard-export.sig", "U"),
])
def test_qr_share_files(fname, mode, ftype, readback_bbqr, need_keypress,
goto_home, pick_menu_item, is_q1, cap_menu):
def test_bbqr_share_files(fname, ftype, readback_bbqr, need_keypress,
goto_home, pick_menu_item, is_q1, cap_menu):
goto_home()
if not is_q1:
pick_menu_item("Advanced/Tools")
pick_menu_item("File Management")
assert "BBQr File Share" not in cap_menu()
return
fpath = "data/" + fname
shutil.copy2(fpath, '../unix/work/MicroSD')
pick_menu_item("Advanced/Tools")
pick_menu_item("File Management")
pick_menu_item("BBQr File Share")
time.sleep(.1)
pick_menu_item(fname)
file_type, rb = readback_bbqr()
assert file_type == ftype
with open(fpath, "rb") as f:
res = f.read()
assert res == rb
os.remove('../unix/work/MicroSD/' + fname)
@pytest.mark.parametrize("fname", [
"ccbk-start.json",
"devils-txn.txn",
"payjoin.psbt", # base64 string in file
])
def test_qr_share_files(fname, pick_menu_item, goto_home, is_q1, cap_menu, cap_screen_qr):
goto_home()
if not is_q1:
pick_menu_item("Advanced/Tools")
@ -983,15 +1011,11 @@ def test_qr_share_files(fname, mode, ftype, readback_bbqr, need_keypress,
pick_menu_item("QR File Share")
time.sleep(.1)
pick_menu_item(fname)
file_type, rb = readback_bbqr()
assert file_type == ftype
with open(fpath, mode) as f:
qr = cap_screen_qr()
with open(fpath, "r") as f:
res = f.read()
if fname.endswith(".txn"):
res = bytes.fromhex(res.decode())
assert res == rb
assert res == qr.decode()
os.remove('../unix/work/MicroSD/' + fname)