Simulator

Real SeedSigner device firmware, the actual Python off the device, running in this browser tab. Its screen is a canvas, its buttons are your keyboard, and its camera is your webcam.

This is a simulator, not a wallet. It runs in a browser tab on an ordinary computer: no secure element, no air gap, nothing hidden from the rest of the machine.

Treat every key it shows you as public, and never enter a seed phrase you rely on. If you want something to type in, use a BIP39 test vector; they exist for exactly this.

Open the simulator

First load fetches about 30 MB (Python and the wallet) and takes a few seconds. After that it runs offline. Arrow keys move, Enter selects, 1 2 3 are the side buttons, or click the buttons on the device.

What it actually is

Not a re-creation. The wallet's own Python is executed by Pyodide (CPython compiled to WebAssembly) inside a Web Worker, and the firmware's own entry point is what runs. The menus, the seed handling, the PSBT parsing and the QR encoders are all upstream's, unmodified.

Two firmwares are built and the simulator says which one it is running: stock SeedSigner, what a plain device runs, and the 3rdIteration smartcard fork, a third party fork that adds SeedKeeper and Satochip support. The control under the device switches between them.

Only the four places the firmware reaches for hardware are replaced, from the outside, and the fourth only exists in the fork:

Each firmware is pinned to a single upstream commit, and a build script in the repository rebuilds it from that commit, so the claim that this is real device firmware is one you can check rather than take on trust.

What works, and what does not

Nothing leaves the tab. This page and the simulator both declare a content security policy that permits no connections to any other origin, and there is no server to send anything to.

If the simulator does not start

It needs to be served with Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp; without them the browser withholds the shared memory every keypress travels on, and the wallet never starts. Scanning additionally needs a secure context: https, or localhost. Both are covered in the repository's self-hosting notes.