From bbd0a2f88e32a7dedb3e833635a4a6e8a2609eb6 Mon Sep 17 00:00:00 2001
From: okaybro <66475772+Chaitanya-Keyal@users.noreply.github.com>
Date: Thu, 5 Mar 2026 22:19:54 +0000
Subject: [PATCH 01/13] docs(README): bump version to 0.8.7
---
README.md | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
index 171bd671..4e0ef878 100644
--- a/README.md
+++ b/README.md
@@ -112,23 +112,23 @@ Instructions to build a SeedSigner OS image (using precisely the same process th
## Downloading the Software
-Download the current Version (0.8.6) software image that is compatible with your Raspberry Pi Hardware. The Pi Zero 1.3 is the most common and recommended board.
+Download the current Version (0.8.7) software image that is compatible with your Raspberry Pi Hardware. The Pi Zero 1.3 is the most common and recommended board.
| Board | Download Image Link/Name |
| --------------------- | --------------------------------- |
-|**[Raspberry Pi Zero 1.3](https://www.raspberrypi.com/products/raspberry-pi-zero/)** |[`seedsigner_os.0.8.6.pi0.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.6/seedsigner_os.0.8.6.pi0.img) |
-|[Raspberry Pi Zero W](https://www.raspberrypi.com/products/raspberry-pi-zero-w/) |[`seedsigner_os.0.8.6.pi0.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.6/seedsigner_os.0.8.6.pi0.img) |
-|[Raspberry Pi Zero 2 W](https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/) |[`seedsigner_os.0.8.6.pi02w.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.6/seedsigner_os.0.8.6.pi02w.img) |
-|[Raspberry Pi 1 Model B/B+](https://www.raspberrypi.com/products/raspberry-pi-1-model-b-plus/) |[`seedsigner_os.0.8.6.pi0.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.6/seedsigner_os.0.8.6.pi0.img) |
-|[Raspberry Pi 2 Model B](https://www.raspberrypi.com/products/raspberry-pi-2-model-b/) |[`seedsigner_os.0.8.6.pi2.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.6/seedsigner_os.0.8.6.pi2.img) |
-|[Raspberry Pi 3 Model B](https://www.raspberrypi.com/products/raspberry-pi-3-model-b/) |[`seedsigner_os.0.8.6.pi02w.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.6/seedsigner_os.0.8.6.pi02w.img) |
-|[Raspberry Pi 4 Model B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/) |[`seedsigner_os.0.8.6.pi4.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.6/seedsigner_os.0.8.6.pi4.img) |
-|[Raspberry Pi 400](https://www.raspberrypi.com/products/raspberry-pi-400-unit/) |[`seedsigner_os.0.8.6.pi4.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.6/seedsigner_os.0.8.6.pi4.img) |
+|**[Raspberry Pi Zero 1.3](https://www.raspberrypi.com/products/raspberry-pi-zero/)** |[`seedsigner_os.0.8.7.pi0.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.7/seedsigner_os.0.8.7.pi0.img) |
+|[Raspberry Pi Zero W](https://www.raspberrypi.com/products/raspberry-pi-zero-w/) |[`seedsigner_os.0.8.7.pi0.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.7/seedsigner_os.0.8.7.pi0.img) |
+|[Raspberry Pi Zero 2 W](https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/) |[`seedsigner_os.0.8.7.pi02w.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.7/seedsigner_os.0.8.7.pi02w.img) |
+|[Raspberry Pi 1 Model B/B+](https://www.raspberrypi.com/products/raspberry-pi-1-model-b-plus/) |[`seedsigner_os.0.8.7.pi0.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.7/seedsigner_os.0.8.7.pi0.img) |
+|[Raspberry Pi 2 Model B](https://www.raspberrypi.com/products/raspberry-pi-2-model-b/) |[`seedsigner_os.0.8.7.pi2.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.7/seedsigner_os.0.8.7.pi2.img) |
+|[Raspberry Pi 3 Model B](https://www.raspberrypi.com/products/raspberry-pi-3-model-b/) |[`seedsigner_os.0.8.7.pi02w.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.7/seedsigner_os.0.8.7.pi02w.img) |
+|[Raspberry Pi 4 Model B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/) |[`seedsigner_os.0.8.7.pi4.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.7/seedsigner_os.0.8.7.pi4.img) |
+|[Raspberry Pi 400](https://www.raspberrypi.com/products/raspberry-pi-400-unit/) |[`seedsigner_os.0.8.7.pi4.img`](https://github.com/SeedSigner/seedsigner/releases/download/0.8.7/seedsigner_os.0.8.7.pi4.img) |
Note: If you have physically removed the WiFi component from your board, you will still use the image file of the original (un-modified) hardware. (Our files are compiled/based on the *processor* architecture). Although it is better to spend a few minutes upfront to determine which specific Pi hardware/model you have, if you are still unsure which hardware you have, you can try using the pi0.img file. Making an incorrect choice here will not ruin your board, because this is software, not firmware.
**Also download** these 2 signature verification files to the same folder
-[The Plaintext manifest file](https://github.com/SeedSigner/seedsigner/releases/download/0.8.6/seedsigner.0.8.6.sha256.txt)
-[The Signature of the manifest file](https://github.com/SeedSigner/seedsigner/releases/download/0.8.6/seedsigner.0.8.6.sha256.txt.sig)
+[The Plaintext manifest file](https://github.com/SeedSigner/seedsigner/releases/download/0.8.7/seedsigner.0.8.7.sha256.txt)
+[The Signature of the manifest file](https://github.com/SeedSigner/seedsigner/releases/download/0.8.7/seedsigner.0.8.7.sha256.txt.sig)
Users familiar with older versions of the SeedSigner software might be surprised with how fast their software downloads now are, because since version 0.6.0 the software image files are now 100x smaller! Each image file is now under 42 Megabytes so your downloads and verifications will be very quick now (and might even seem *too* quick)!
@@ -160,7 +160,7 @@ The result should confirm that 1 key was *either* imported or updated. *Ignore*
Next, you will run the *verify* command on the signature (.sig) file. (*Verify* must be run from inside the same folder that you downloaded the files into earlier.)
```
-gpg --verify seedsigner.0.8.6.sha256.txt.sig
+gpg --verify seedsigner.0.8.7.sha256.txt.sig
```
When the verify command completes successfully, it should display output like this:
@@ -230,22 +230,22 @@ Now that you have confirmed that you do have the real SeedSigner Project's Publi
**On Linux or OSX:** Run this command
```
-shasum -a 256 --ignore-missing --check seedsigner.0.8.6.sha256.txt
+shasum -a 256 --ignore-missing --check seedsigner.0.8.7.sha256.txt
```
Note: macOS versions earlier than v11 (Big Sur) do not support the `--ignore-missing` flag. You can omit it and disregard any missing file warnings.
**On Windows (inside Powershell):** Run this command
```
-CertUtil -hashfile seedsigner_os.0.8.6.Insert_Your_Pi_Models_binary_here_For_Example_pi02w.img SHA256
+CertUtil -hashfile seedsigner_os.0.8.7.Insert_Your_Pi_Models_binary_here_For_Example_pi02w.img SHA256
```
On Windows, you must then manually compare the resulting file hash value to the corresponding hash value shown inside the .SHA256 cleartext file.
Wait up to 30 seconds for the command to complete, and it should display:
```
-seedsigner_os.0.8.6.[Your_Pi_Model_For_Example:pi02w].img: OK
+seedsigner_os.0.8.7.[Your_Pi_Model_For_Example:pi02w].img: OK
```
-**If you receive the "OK" message** for your **seedsigner_os.0.8.6.[Your_Pi_Model_For_Example:pi02w].img file**, as shown above, then your verification is fully complete!
+**If you receive the "OK" message** for your **seedsigner_os.0.8.7.[Your_Pi_Model_For_Example:pi02w].img file**, as shown above, then your verification is fully complete!
**All of your downloaded files have now been confirmed as both authentic and unaltered!** You can proceed to create/write your MicroSD cardππ !!
If your file result shows "FAILED", then you must stop here immediately. Do not continue. Contact us for assistance at the Telegram group address above.
From a00810ca0d5fadb0e25f6411c602bbd97af0c3b4 Mon Sep 17 00:00:00 2001
From: S1DDHEY
Date: Sat, 4 Apr 2026 23:39:03 +0530
Subject: [PATCH 02/13] replaced os.popen() with inbuilt file handling
---
src/seedsigner/views/tools_views.py | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/seedsigner/views/tools_views.py b/src/seedsigner/views/tools_views.py
index b2c6b9fb..798cf5ba 100644
--- a/src/seedsigner/views/tools_views.py
+++ b/src/seedsigner/views/tools_views.py
@@ -1,6 +1,5 @@
import hashlib
import logging
-import os
import time
from gettext import gettext as _
@@ -148,9 +147,12 @@ class ToolsImageEntropyMnemonicLengthView(View):
# Build in some hardware-level uniqueness via CPU unique Serial num
try:
- stream = os.popen("cat /proc/cpuinfo | grep Serial")
- output = stream.read()
- serial_num = output.split(":")[-1].strip().encode('utf-8')
+ serial_num = b''
+ with open("/proc/cpuinfo", "r") as f:
+ for line in f:
+ if "Serial" in line:
+ serial_num = line.split(":")[-1].strip().encode('utf-8')
+ break
serial_hash = hashlib.sha256(serial_num)
hash_bytes = serial_hash.digest()
except Exception as e:
From 5c7dcd179abfdce3cfc47b71a986700a4826ff71 Mon Sep 17 00:00:00 2001
From: PROWLERx15
Date: Mon, 6 Apr 2026 22:34:08 +0530
Subject: [PATCH 03/13] fix back navigation
---
src/seedsigner/views/seed_views.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/seedsigner/views/seed_views.py b/src/seedsigner/views/seed_views.py
index e938da49..fe29568e 100644
--- a/src/seedsigner/views/seed_views.py
+++ b/src/seedsigner/views/seed_views.py
@@ -230,7 +230,7 @@ class SeedMnemonicEntryView(View):
return Destination(BackStackView)
else:
self.controller.storage.discard_pending_mnemonic()
- return Destination(MainMenuView)
+ return Destination(BackStackView)
# ret will be our new mnemonic word
self.controller.storage.update_pending_mnemonic(ret, self.cur_word_index)
@@ -332,6 +332,9 @@ class SeedFinalizeView(View):
button_data=button_data,
)
+ if selected_menu_num == RET_CODE__BACK_BUTTON:
+ return Destination(BackStackView)
+
if button_data[selected_menu_num] == self.FINALIZE:
seed_num = self.controller.storage.finalize_pending_seed()
return Destination(SeedOptionsView, view_args={"seed_num": seed_num}, clear_history=True)
@@ -339,9 +342,6 @@ class SeedFinalizeView(View):
elif button_data[selected_menu_num] == self.PASSPHRASE:
return Destination(SeedAddPassphraseView)
- elif selected_menu_num == RET_CODE__BACK_BUTTON:
- return Destination(BackStackView)
-
class SeedAddPassphraseView(View):
From 3f2344af60e1005bcd95f1f7b32c96fefb099964 Mon Sep 17 00:00:00 2001
From: PROWLERx15
Date: Mon, 6 Apr 2026 22:34:50 +0530
Subject: [PATCH 04/13] add tests
---
tests/test_flows_seed.py | 104 +++++++++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
diff --git a/tests/test_flows_seed.py b/tests/test_flows_seed.py
index e5f2c346..6db95f3d 100644
--- a/tests/test_flows_seed.py
+++ b/tests/test_flows_seed.py
@@ -495,6 +495,110 @@ class TestSeedFlows(FlowTest):
+class TestSeedEntryBackFlows(FlowTest):
+ """
+ Tests for every BACK exit scenario from SeedMnemonicEntryView and related views.
+
+ A naive BackStackView swap can leave resume_main_flow dangling, causing
+ auto-redirects on stale flow state. These tests verify that BACK navigation
+ returns to the correct parent view AND that no flow state leaks.
+ """
+
+ def test_back_from_seed_entry_12_word(self):
+ """
+ Seeds Menu β Load a Seed β Enter 12-word β BACK on first word β
+ should return to LoadSeedView, NOT MainMenuView.
+ """
+ self.run_sequence([
+ FlowStep(MainMenuView, button_data_selection=MainMenuView.SEEDS),
+ FlowStep(seed_views.SeedsMenuView, is_redirect=True), # No seeds loaded; auto-redirects to LoadSeedView
+ FlowStep(seed_views.LoadSeedView, button_data_selection=seed_views.LoadSeedView.TYPE_12WORD),
+ FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=RET_CODE__BACK_BUTTON),
+ FlowStep(seed_views.LoadSeedView), # Should land here, NOT MainMenuView
+ ])
+
+
+ def test_back_from_seed_entry_24_word(self):
+ """
+ Seeds Menu β Load a Seed β Enter 24-word β BACK on first word β
+ should return to LoadSeedView, NOT MainMenuView.
+ """
+ self.run_sequence([
+ FlowStep(MainMenuView, button_data_selection=MainMenuView.SEEDS),
+ FlowStep(seed_views.SeedsMenuView, is_redirect=True), # No seeds loaded; auto-redirects to LoadSeedView
+ FlowStep(seed_views.LoadSeedView, button_data_selection=seed_views.LoadSeedView.TYPE_24WORD),
+ FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=RET_CODE__BACK_BUTTON),
+ FlowStep(seed_views.LoadSeedView), # Should land here, NOT MainMenuView
+ ])
+
+
+ def test_back_from_seed_entry_mid_word(self):
+ """
+ Pressing BACK from a middle word (eg. word #2) should return to the
+ previous SeedMnemonicEntryView (eg. word #1) via the back stack.
+ """
+ self.run_sequence([
+ FlowStep(MainMenuView, button_data_selection=MainMenuView.SEEDS),
+ FlowStep(seed_views.SeedsMenuView, is_redirect=True),
+ FlowStep(seed_views.LoadSeedView, button_data_selection=seed_views.LoadSeedView.TYPE_12WORD),
+ FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value="abandon"), # word #1
+ FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=RET_CODE__BACK_BUTTON), # BACK from word #2
+ FlowStep(seed_views.SeedMnemonicEntryView), # Returns to word #1
+ ])
+
+
+ def test_back_from_seed_entry_via_seed_select(self):
+ """
+ When entering a seed via SeedSelectSeedView (e.g. during sign message flow),
+ pressing BACK on the first word should return to SeedSelectSeedView, NOT
+ MainMenuView. Crucially, resume_main_flow must remain valid since the user
+ is still within that flow.
+ """
+ from seedsigner.controller import Controller
+ from seedsigner.models.settings import SettingsConstants
+
+ self.settings.set_value(SettingsConstants.SETTING__MESSAGE_SIGNING, SettingsConstants.OPTION__ENABLED)
+
+ def load_signmessage_into_decoder(view):
+ view.decoder.add_data("signmessage m/84h/0h/0h/0/0 ascii:test message")
+
+ self.run_sequence([
+ FlowStep(MainMenuView, button_data_selection=MainMenuView.SCAN),
+ FlowStep(scan_views.ScanView, before_run=load_signmessage_into_decoder),
+ FlowStep(seed_views.SeedSignMessageStartView, is_redirect=True),
+ FlowStep(seed_views.SeedSelectSeedView, button_data_selection=seed_views.SeedSelectSeedView.TYPE_12WORD),
+ FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=RET_CODE__BACK_BUTTON), # BACK on first word
+ FlowStep(seed_views.SeedSelectSeedView), # Should return here, in the sign message flow
+ ])
+
+ # Verify resume_main_flow is still set β user is still in the sign message flow
+ assert self.controller.resume_main_flow == Controller.FLOW__SIGN_MESSAGE
+
+
+ def test_back_from_seed_finalize(self):
+ """
+ Pressing BACK from SeedFinalizeView should return to the last word
+ entry view via the back stack.
+ """
+ mnemonic = "tone flat shed cool census soul paddle boy flight fantasy stem social".split()
+ sequence = [
+ FlowStep(MainMenuView, button_data_selection=MainMenuView.SEEDS),
+ FlowStep(seed_views.SeedsMenuView, is_redirect=True),
+ FlowStep(seed_views.LoadSeedView, button_data_selection=seed_views.LoadSeedView.TYPE_12WORD),
+ ]
+
+ for word in mnemonic:
+ sequence.append(FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=word))
+
+ sequence += [
+ FlowStep(seed_views.SeedFinalizeView, screen_return_value=RET_CODE__BACK_BUTTON),
+ FlowStep(seed_views.SeedMnemonicEntryView), # Returns to last word entry
+ ]
+
+ self.run_sequence(sequence)
+
+
+
class TestMessageSigningFlows(FlowTest):
MAINNET_DERIVATION_PATH = "m/84h/0h/0h/0/0"
TESTNET_DERIVATION_PATH = "m/84h/1h/0h/0/0"
From 804dad9870b892fbbc39b55ca35026da7ac2cb8d Mon Sep 17 00:00:00 2001
From: PROWLERx15
Date: Fri, 10 Apr 2026 00:04:27 +0530
Subject: [PATCH 05/13] remove test
---
tests/test_flows_seed.py | 22 ----------------------
1 file changed, 22 deletions(-)
diff --git a/tests/test_flows_seed.py b/tests/test_flows_seed.py
index 6db95f3d..03dfc882 100644
--- a/tests/test_flows_seed.py
+++ b/tests/test_flows_seed.py
@@ -575,28 +575,6 @@ class TestSeedEntryBackFlows(FlowTest):
assert self.controller.resume_main_flow == Controller.FLOW__SIGN_MESSAGE
- def test_back_from_seed_finalize(self):
- """
- Pressing BACK from SeedFinalizeView should return to the last word
- entry view via the back stack.
- """
- mnemonic = "tone flat shed cool census soul paddle boy flight fantasy stem social".split()
- sequence = [
- FlowStep(MainMenuView, button_data_selection=MainMenuView.SEEDS),
- FlowStep(seed_views.SeedsMenuView, is_redirect=True),
- FlowStep(seed_views.LoadSeedView, button_data_selection=seed_views.LoadSeedView.TYPE_12WORD),
- ]
-
- for word in mnemonic:
- sequence.append(FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=word))
-
- sequence += [
- FlowStep(seed_views.SeedFinalizeView, screen_return_value=RET_CODE__BACK_BUTTON),
- FlowStep(seed_views.SeedMnemonicEntryView), # Returns to last word entry
- ]
-
- self.run_sequence(sequence)
-
class TestMessageSigningFlows(FlowTest):
From ef7d3716d17a18caf10de4763c54109998750fbe Mon Sep 17 00:00:00 2001
From: PROWLERx15
Date: Fri, 10 Apr 2026 00:05:05 +0530
Subject: [PATCH 06/13] update conditional branch
---
src/seedsigner/views/seed_views.py | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/src/seedsigner/views/seed_views.py b/src/seedsigner/views/seed_views.py
index fe29568e..a2761f99 100644
--- a/src/seedsigner/views/seed_views.py
+++ b/src/seedsigner/views/seed_views.py
@@ -226,11 +226,10 @@ class SeedMnemonicEntryView(View):
)
if ret == RET_CODE__BACK_BUTTON:
- if self.cur_word_index > 0:
- return Destination(BackStackView)
- else:
+ # Only need to discard when exiting from the very first word
+ if self.cur_word_index == 0:
self.controller.storage.discard_pending_mnemonic()
- return Destination(BackStackView)
+ return Destination(BackStackView)
# ret will be our new mnemonic word
self.controller.storage.update_pending_mnemonic(ret, self.cur_word_index)
@@ -332,9 +331,6 @@ class SeedFinalizeView(View):
button_data=button_data,
)
- if selected_menu_num == RET_CODE__BACK_BUTTON:
- return Destination(BackStackView)
-
if button_data[selected_menu_num] == self.FINALIZE:
seed_num = self.controller.storage.finalize_pending_seed()
return Destination(SeedOptionsView, view_args={"seed_num": seed_num}, clear_history=True)
From d0b729a52e558e006ef6b7d5f7efba2f80514e80 Mon Sep 17 00:00:00 2001
From: PROWLERx15
Date: Mon, 1 Jun 2026 11:56:57 +0530
Subject: [PATCH 07/13] added comment explaining changes
---
src/seedsigner/views/seed_views.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/seedsigner/views/seed_views.py b/src/seedsigner/views/seed_views.py
index a2761f99..53370f0c 100644
--- a/src/seedsigner/views/seed_views.py
+++ b/src/seedsigner/views/seed_views.py
@@ -226,7 +226,10 @@ class SeedMnemonicEntryView(View):
)
if ret == RET_CODE__BACK_BUTTON:
- # Only need to discard when exiting from the very first word
+ # RET_CODE__BACK_BUTTON can happen in two ways here:
+ # 1. Backing out of the very first word completely aborts the mnemonic entry.
+ # 2. Backing out of a subsequent word just returns to the previous word.
+ # In both cases we return to BackStackView, but for case #1 we must also discard.
if self.cur_word_index == 0:
self.controller.storage.discard_pending_mnemonic()
return Destination(BackStackView)
From 60cb1376c05845bcc3490c6d47fb9139a5175439 Mon Sep 17 00:00:00 2001
From: PROWLERx15
Date: Mon, 1 Jun 2026 11:57:54 +0530
Subject: [PATCH 08/13] refactor 12/24 word tests into a single test
---
tests/test_flows_seed.py | 34 +++++++++++-----------------------
1 file changed, 11 insertions(+), 23 deletions(-)
diff --git a/tests/test_flows_seed.py b/tests/test_flows_seed.py
index 03dfc882..601e7a44 100644
--- a/tests/test_flows_seed.py
+++ b/tests/test_flows_seed.py
@@ -504,32 +504,20 @@ class TestSeedEntryBackFlows(FlowTest):
returns to the correct parent view AND that no flow state leaks.
"""
- def test_back_from_seed_entry_12_word(self):
+ def test_back_from_seed_entry_first_word(self):
"""
- Seeds Menu β Load a Seed β Enter 12-word β BACK on first word β
+ Seeds Menu β Load a Seed β Enter 12/24-word β BACK on first word β
should return to LoadSeedView, NOT MainMenuView.
"""
- self.run_sequence([
- FlowStep(MainMenuView, button_data_selection=MainMenuView.SEEDS),
- FlowStep(seed_views.SeedsMenuView, is_redirect=True), # No seeds loaded; auto-redirects to LoadSeedView
- FlowStep(seed_views.LoadSeedView, button_data_selection=seed_views.LoadSeedView.TYPE_12WORD),
- FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=RET_CODE__BACK_BUTTON),
- FlowStep(seed_views.LoadSeedView), # Should land here, NOT MainMenuView
- ])
-
-
- def test_back_from_seed_entry_24_word(self):
- """
- Seeds Menu β Load a Seed β Enter 24-word β BACK on first word β
- should return to LoadSeedView, NOT MainMenuView.
- """
- self.run_sequence([
- FlowStep(MainMenuView, button_data_selection=MainMenuView.SEEDS),
- FlowStep(seed_views.SeedsMenuView, is_redirect=True), # No seeds loaded; auto-redirects to LoadSeedView
- FlowStep(seed_views.LoadSeedView, button_data_selection=seed_views.LoadSeedView.TYPE_24WORD),
- FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=RET_CODE__BACK_BUTTON),
- FlowStep(seed_views.LoadSeedView), # Should land here, NOT MainMenuView
- ])
+ for seed_type in [seed_views.LoadSeedView.TYPE_12WORD, seed_views.LoadSeedView.TYPE_24WORD]:
+ self.run_sequence([
+ FlowStep(MainMenuView, button_data_selection=MainMenuView.SEEDS),
+ FlowStep(seed_views.SeedsMenuView, is_redirect=True), # No seeds loaded; auto-redirects to LoadSeedView
+ FlowStep(seed_views.LoadSeedView, button_data_selection=seed_type),
+ FlowStep(seed_views.SeedMnemonicEntryView, screen_return_value=RET_CODE__BACK_BUTTON),
+ FlowStep(seed_views.LoadSeedView), # Should land here, NOT MainMenuView
+ ])
+ BaseTest.reset_controller()
def test_back_from_seed_entry_mid_word(self):
From 3a449ab3b323ea179c972ef6e99d39623cd105fe Mon Sep 17 00:00:00 2001
From: okaybro <66475772+Chaitanya-Keyal@users.noreply.github.com>
Date: Sun, 3 May 2026 22:20:20 -0400
Subject: [PATCH 09/13] ci: update workflow to include localization
dependencies and compile translations
---
.github/workflows/tests.yml | 6 ++++--
l10n/requirements-l10n.txt | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index c1e14c97..32ce2ec0 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -35,8 +35,10 @@ jobs:
run: |
sudo apt-get install libzbar0
python -m pip install --upgrade pip
- pip install -r requirements.txt -r tests/requirements.txt
- pip install .
+ pip install -r requirements.txt -r tests/requirements.txt -r l10n/requirements-l10n.txt
+ pip install -e .
+ - name: Compile translations
+ run: python setup.py compile_catalog
- name: Test with pytest
run: |
mkdir artifacts
diff --git a/l10n/requirements-l10n.txt b/l10n/requirements-l10n.txt
index b83c7a02..d7821516 100644
--- a/l10n/requirements-l10n.txt
+++ b/l10n/requirements-l10n.txt
@@ -1 +1,2 @@
Babel==2.16.0
+setuptools>=82.0.0
From 94485e525ce9156ddbf8f50e30d078faaf21b656 Mon Sep 17 00:00:00 2001
From: Kshitij <162005485+PROWLERx15@users.noreply.github.com>
Date: Tue, 2 Jun 2026 13:19:24 +0530
Subject: [PATCH 10/13] update comment
Co-authored-by: kdmukai <934746+kdmukai@users.noreply.github.com>
---
src/seedsigner/views/seed_views.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/seedsigner/views/seed_views.py b/src/seedsigner/views/seed_views.py
index 53370f0c..cb2032ed 100644
--- a/src/seedsigner/views/seed_views.py
+++ b/src/seedsigner/views/seed_views.py
@@ -226,10 +226,10 @@ class SeedMnemonicEntryView(View):
)
if ret == RET_CODE__BACK_BUTTON:
- # RET_CODE__BACK_BUTTON can happen in two ways here:
- # 1. Backing out of the very first word completely aborts the mnemonic entry.
- # 2. Backing out of a subsequent word just returns to the previous word.
- # In both cases we return to BackStackView, but for case #1 we must also discard.
+ # This handles two possible scenarios:
+ # 1. Backing out of the first word cancels the mnemonic entry process;
+ return to whichever `View` routed us here initially.
+ # 2. Backing out of the current word returns to the previous word.
if self.cur_word_index == 0:
self.controller.storage.discard_pending_mnemonic()
return Destination(BackStackView)
From cf37ac2a8e24046b4f170d1266cd53131f492a8e Mon Sep 17 00:00:00 2001
From: PROWLERx15
Date: Tue, 2 Jun 2026 18:29:51 +0530
Subject: [PATCH 11/13] fix comment
---
src/seedsigner/views/seed_views.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/seedsigner/views/seed_views.py b/src/seedsigner/views/seed_views.py
index cb2032ed..65830d37 100644
--- a/src/seedsigner/views/seed_views.py
+++ b/src/seedsigner/views/seed_views.py
@@ -227,8 +227,8 @@ class SeedMnemonicEntryView(View):
if ret == RET_CODE__BACK_BUTTON:
# This handles two possible scenarios:
- # 1. Backing out of the first word cancels the mnemonic entry process;
- return to whichever `View` routed us here initially.
+ # 1. Backing out of the first word cancels the mnemonic entry process;
+ # return to whichever `View` routed us here initially.
# 2. Backing out of the current word returns to the previous word.
if self.cur_word_index == 0:
self.controller.storage.discard_pending_mnemonic()
From 6ddc7a99c09bbdb1e055aa5a1435fc734db9d366 Mon Sep 17 00:00:00 2001
From: PROWLERx15
Date: Tue, 2 Jun 2026 19:07:51 +0530
Subject: [PATCH 12/13] changessss
---
tests/test_flows_seed.py | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/tests/test_flows_seed.py b/tests/test_flows_seed.py
index 601e7a44..578f0094 100644
--- a/tests/test_flows_seed.py
+++ b/tests/test_flows_seed.py
@@ -506,8 +506,8 @@ class TestSeedEntryBackFlows(FlowTest):
def test_back_from_seed_entry_first_word(self):
"""
- Seeds Menu β Load a Seed β Enter 12/24-word β BACK on first word β
- should return to LoadSeedView, NOT MainMenuView.
+ Pressing BACK on the first word of mnemonic entry should return to
+ the View that initiated the mnemonic entry process.
"""
for seed_type in [seed_views.LoadSeedView.TYPE_12WORD, seed_views.LoadSeedView.TYPE_24WORD]:
self.run_sequence([
@@ -534,13 +534,16 @@ class TestSeedEntryBackFlows(FlowTest):
FlowStep(seed_views.SeedMnemonicEntryView), # Returns to word #1
])
+ # Verify we're back on word #1: word at index 0 should still be set
+ # from the previous entry, while word at index 1 should be unset.
+ assert self.controller.storage.get_pending_mnemonic_word(0) == "abandon"
+ assert self.controller.storage.get_pending_mnemonic_word(1) is None
+
def test_back_from_seed_entry_via_seed_select(self):
"""
- When entering a seed via SeedSelectSeedView (e.g. during sign message flow),
- pressing BACK on the first word should return to SeedSelectSeedView, NOT
- MainMenuView. Crucially, resume_main_flow must remain valid since the user
- is still within that flow.
+ Backing out of mnemonic entry during an active flow must preserve
+ `resume_main_flow` so the user remains within that flow.
"""
from seedsigner.controller import Controller
from seedsigner.models.settings import SettingsConstants
From 3d8af166de30ab30934c692a7ad9ab8c75f38493 Mon Sep 17 00:00:00 2001
From: okaybro <66475772+Chaitanya-Keyal@users.noreply.github.com>
Date: Sun, 3 May 2026 21:59:47 -0400
Subject: [PATCH 13/13] chore: update seedsigner-translations submodule pointer
to latest dev (708961)
---
src/seedsigner/resources/seedsigner-translations | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/seedsigner/resources/seedsigner-translations b/src/seedsigner/resources/seedsigner-translations
index 6b911be2..708961a4 160000
--- a/src/seedsigner/resources/seedsigner-translations
+++ b/src/seedsigner/resources/seedsigner-translations
@@ -1 +1 @@
-Subproject commit 6b911be2da88cd186d86ff5b7641fb048ebc3e9c
+Subproject commit 708961a4163b1bd43eb15c4a26713649c63f6ccd