Better Wallet Pi · v0.1.0
Doc  BW-PI / SPEC 0.1
Issue  2026-05-06
Class  Reference design
Status   PROTOTYPE

Open-source · Solana-first · Air-gapped · Raspberry Pi

A Solana wallet that cannot connect to anything.

Better Wallet Pi is a buildable reference design for signing Solana via Keystone-style UR requests over QR — never over the wire. The online wallet shows an animated ur:sol-sign-request; the Pi scans it, renders the transaction or message for review, signs offline at m/44'/501'/i', and returns ur:sol-signature by QR. No driver. No data cable. No background sync.

Primary path
Solana (Keystone UR)
Network surface
0 / 0
Standards
BC-UR · Keystone Solana
SLIP-10 · BIP-39
Orthographic illustration of the Better Wallet Pi device with labelled callouts.
FIG · 01
SCALE 1:1
SIGN DENY AIR-GAPPED BW-PI/0.1.0 A B C D
A
3.5″ SPI display
B
UR-capable camera
C
Confirm · GPIO 17
D
Deny · GPIO 27
SYS STATUS / AIR-GAPPED
RT 00:00:13.27
camera_loop idle · awaiting UR frame frame 03 / 24 · part 0x4a frame 11 / 24 · part 0x9c frame 24 / 24 · reassembled
state_machine READY PARSE_REQUEST · sol-sign-request AWAIT_CONFIRM · gpio SIGNING · sol · ed25519 EMIT_SIGNATURE · ur:sol-signature DISPLAYING · fountain part 08/24 DISPLAYING · fountain part 16/24
sol_parser idle tx · legacy message tx · v0 · 1 sig msg · off-chain utf-8 idle
display_loop rendering home rendering tx detail rendering signature QR · part 02 rendering signature QR · part 12
gpio_loop listening · pin 17 · pin 27 pin 17 high · CONFIRM listening · pin 17 · pin 27
> bw-pi await scan
/sol transport Keystone Solana UR
/sol request ur:sol-sign-request
/sol response ur:sol-signature
/derivation m/44'/501'/i'
/host Raspberry Pi 4 / CM4
/network none

Most hardware wallets ship with closed firmware, a proprietary chip, and a USB cable. This one ships with none of those.

  1. 01

    No path in.

    WiFi and Bluetooth are disabled in firmware. There is no USB data path. The device cannot phone home — there is no home to call.

  2. 02

    Light in. Light out.

    Animated UR fountain-encoded QR carries the request in. A second QR carries the Ed25519 signature out. Nothing else crosses.

  3. 03

    No mystery chips.

    Every line of the signing path is open-source Python on commodity silicon. Read it, run it, fork it, build it.

§ 02 / Architecture

Two devices. One photon-thick channel.

The signing flow is a closed loop with exactly one boundary. Bytes never cross it. Only the camera and the screen do — the payload is always an animated BC-UR fountain QR with a sol-sign-request (or legacy-compatible UR types the wallet emits).

Online · Networked

A

Your laptop, in the world.

  • 01

    A Solana wallet builds the unsigned transaction or message and wraps it in a Keystone Solana sign request for the Pi camera.

  • 02

    It is rendered as animated QR fragments that fountain-decode into a single CBOR payload on the Pi.

  • 06

    Camera scans the signed result and broadcasts via the chain's normal path.

AIR GAP

UR · light only

no packets

Offline · Air-gapped

B

The Pi, in a Faraday calm.

  • 03

    Camera decodes the QR. UR fragments fountain-reassemble into a structured sign request.

  • 04

    Human-readable summary on the 3.5″ screen. SIGN or DENY by hand.

  • 05

    wallet.sol.sign returns a SolSignResult (64-byte Ed25519). The firmware encodes ur:sol-signature for the return QR.

§ 03 / Chain

Solana first. Air gap always. Keystone UR in. Signature UR out. No network stack.

The firmware speaks Keystone-style Solana sign requests: scan an animated ur:sol-sign-request, confirm on-device, and show ur:sol-signature for the online wallet to finish broadcast.

Solana

/sol
Curve
Ed25519
Derivation
SLIP-10 · m/44'/501'/{i}'
Payload
versioned transaction or off-chain message (wallet-supplied bytes)
Transport
Keystone Solana UR · BC-UR fountain QR (ur:sol-sign-request)
Compatible
Solflare (Keystone flow) · Phantom (if Keystone Solana is exposed)
Out
ur:sol-signature (animated QR)

A note

Solflare supports this device as a Keystone-class Solana signer today. Phantom compatibility depends on the extension exposing the same Keystone Solana UR path — the firmware side is aligned with ur:sol-sign-request / ur:sol-signature. Start with devnet or a throwaway mainnet key until you trust your build.

Solana docs ↗

§ 04 / Source of truth

One signer. One Solana surface.

Verbatim from wallet/__init__.py. Every SolSignRequest passes through this method: path checks, optional pubkey binding, then Ed25519 signing. Anything else is a bug.

wallet/__init__.py · read-only
view raw ↗
35 def sign(self, request: SolSignRequest):
36 if not isinstance(request, SolSignRequest):
37 raise ValueError(f"unsupported sign request type: {type(request).__name__}")
38
39 account_index = _account_index_from_path(request.derivation_path)
40 account = next((entry for entry in self.sol_accounts if int(entry["index"]) == account_index), None)
41 if account is None:
42 raise ValueError("requested signer derivation path is not available on this device")
43
44 if request.address:
45 requested_address = _derive.sol_bytes_to_address(request.address)
46 if requested_address != account["public_key"]:
47 raise ValueError("requested signer pubkey does not match derivation path")
48
49 signing_key = _derive.derive_sol_signing_key(self._mnemonic, index=account_index)
50 return _sol.sign(signing_key, request)

§ 05 / Cornerstones

Claims are easy to write. These are the structural decisions that make them hold.

We don't ask you to trust the marketing. We ask you to read the file path next to each claim, and verify it for yourself.

  1. § 05.1

    No WiFi. No Bluetooth. No USB data.

    Network silicon is disabled at the firmware level via the Raspberry Pi config overlay. There is no driver path to enable it from userspace. CM4 no-wireless variants remove the silicon entirely.

    config.txt :: dtoverlay=disable-wifi,disable-bt
  2. § 05.2

    PIN-stretched encrypted mnemonic.

    The keystore stores the BIP-39 mnemonic, encrypted with AES-256-GCM keyed by a scrypt-stretched PIN. The mnemonic is the single source of truth — an Ed25519 signing key for Solana is re-derived from it on unlock via SLIP-10. No private key persists on disk.

    wallet/keystore.py · AES-GCM
  3. § 05.3

    BIP-39 recovery, day one.

    A 12-word mnemonic is generated on first boot and shown once for offline backup. Solana accounts derive at m/44'/501'/i' (SLIP-10 Ed25519). One backup seeds every signer slot the device exposes.

    wallet/derive.py · BIP-32 + SLIP-10
  4. § 05.4

    Hard module isolation.

    Only state/machine.py is permitted to import wallet/. The boundary is checked architecturally. Adding networking, USB, or Bluetooth code anywhere is a project-level rule, not a convention.

    state/machine.py · sole importer
  5. § 05.5

    Fully auditable.

    Every line of the signing path is open-source Python: derivation in wallet/derive.py, UR typing in ur/, and Ed25519 signatures via pynacl. No closed firmware. No secure element you have to take on faith. Read it before you trust it.

    github.com/BetterWallet/solana-firmware

§ 06 / Hardware

A reference design. Not a product.

There is no SKU. There is no shipping date. There is a list of commodity parts, an SD-card image, and a repository whose every screw and every line is yours to inspect.

BILL OF MATERIALS

approx US$ 80–120

REF PART DETAIL QTY
PI Raspberry Pi 4 or CM4 (no-wireless) for production ×1
DSP 3.5″ SPI touchscreen 480 × 320 · ADS7846 · tft35a overlay ×1
CAM Pi Camera Module libcamera · ribbon variant recommended ×1
BTN Momentary push buttons GPIO 17 (sign) · GPIO 27 (deny) ×2
SD microSD card 8 GB · Class 10 minimum ×1
PSU USB-C power supply 5 V · 3 A · power-only, no data ×1

OUTCOME

Hardware whose every screw is yours to inspect.

Source the parts. Flash the SD card. Solder two buttons. You now hold a hardware wallet whose entire trust chain you can audit, fork, and rebuild from scratch.

A note, plainly

This is a Phase 1 prototype. The architecture is built for the right reasons, but no external audit has been performed and the code has not been hardened against side-channel attacks. Use a testnet account before anything else.

§ 07 / Datasheet

No mystery. No magic.

A small surface area of well-understood, off-the-shelf components.

Software

Language
Python 3.11+ · asyncio
sol crypto
pynacl · solders
QR transport
pyzbar · BC-UR (_bc_ur) · cbor2
Display
pygame · framebuffer (/dev/fb1)
Camera
picamera2 (libcamera)

Standards

sol transport
Keystone Solana UR · BC-UR
sol request
ur:sol-sign-request
sol response
ur:sol-signature
mnemonic
BIP-39 · 12 words
sol path
SLIP-10 · m/44'/501'/{i}'
curve
Ed25519

Compatibility

Solflare
Keystone Solana UR
Phantom
depends on Keystone exposure in app
cluster
mainnet-beta · devnet · testnet
air gap
camera + display only
license
open source · see repo

§ 08 / Questions

The uncomfortable answers, first.

01 Is this ready to hold real funds today?

No, and we will not pretend otherwise. Better Wallet Pi is a Phase 1 Python prototype. Use Solana devnet or a disposable key first. The architecture is built for the right reasons, but no external audit has been performed and the code has not been hardened against side-channel attacks.

02 Which Solana wallets does it work with?

Solflare supports the Keystone Solana UR flow this firmware implements — pair it as a Keystone-class hardware signer and use animated `ur:sol-sign-request` / `ur:sol-signature` QRs. Phantom may work once the extension exposes the same Keystone Solana path; until then, treat Phantom as experimental.

03 Why center Solana?

Solana already uses Ed25519 at standard BIP-44 paths, and Keystone's Solana UR encoding gives us an open, QR-native request/response framing that maps cleanly onto Pi camera + display. The air gap stays visible: the hot machine prepares and broadcasts; the cold Pi parses, verifies, and signs.

04 How is this different from a Ledger or Trezor?

Ledger and Trezor ship sealed devices with proprietary firmware and a USB cable into a host computer. Better Wallet Pi is open hardware you build yourself, has no USB data path at all, and has no closed components in the signing path.

05 Why a Raspberry Pi?

It is cheap, widely available, well documented, and auditable. The CM4 no-wireless variant is recommended for production builds because the network silicon is physically absent — not just disabled in software.

06 Has the code been audited?

Not externally. Open source means you can audit it yourself — and you should, before trusting it with non-trivial value. The codebase is small and the security boundaries are explicit.

07 Can I contribute?

Yes — issues and pull requests welcome on GitHub. The project follows one strict architectural rule: only state/machine.py may import wallet/. Read CONTEXT.md before sending a PR.

§ 09 / Coda

Don't trust.
Verify.
Then build it.

The repository is the source of truth. The website is the menu; the menu is not the meal. Star it, fork it, audit it, build it.