Skip to content
LeekWallet DIY HardwareWallet

LeekWallet DIY HardwareWallet

Open-source ESP32 hardware wallet.

Created on 11th September 2026

•

LeekWallet DIY HardwareWallet

LeekWallet DIY HardwareWallet

Open-source ESP32 hardware wallet.

The problem LeekWallet DIY HardwareWallet solves

Most crypto users still have to trust devices they do not control.

A browser, phone, or desktop can prepare a transaction, but if that host is compromised it can change the recipient, amount, approval, or contract call before the user signs it. Hardware wallets reduce this risk, but many are expensive, closed-source, dependent on proprietary hardware, or still expose users to blind-signing flows they cannot meaningfully verify.

LeekWallet explores a different approach: a low-cost, fully open hardware wallet that makes the device itself the final authority.

The host can request an action, but the wallet independently parses, reconstructs, hashes, displays, and signs it. If LeekWallet cannot explain a transaction on its own screen, it refuses to sign it by default.

This lets people use LeekWallet for:

  • Self-custody of EVM assets without keeping private keys on a laptop or phone.
  • Verifying transactions on an independent screen before a signature is produced.
  • Signing with no cable and no radio at all. On the camera build, the device reads the transaction request off a phone's screen with its own camera, shows every field on its own display, and hands the signature back as a QR code for the phone to broadcast. It follows EIP-4527, the QR protocol other hardware wallets already speak, so nothing is invented for this project alone.
  • Using dapps through WalletConnect while keeping the signing decision on separate hardware.
  • Reducing blind signing, because known contract calls are decoded and unsupported calldata is rejected by default.
  • Managing multiple wallets from one inexpensive device.
  • Creating seeds with additional user-controlled entropy, including physical dice.
  • Using temporary seeds without persistent storage, allowing a stateless workflow where the secret disappears when the device locks or loses power.
  • Connecting over USB or BLE while maintaining an encrypted authenticated session with the companion, or over none of them.
  • Building and auditing the entire device themselves, from firmware to companion application, on a desktop, on Android, or as a browser extension.

The project is also intentionally inexpensive. The basic ESP32-S3, OLED and button hardware can cost roughly $8–15, and the camera build that signs air-gapped costs a few dollars more. That makes hardware-wallet experimentation and security education accessible to developers who may never purchase a dedicated commercial device.

LeekWallet does not claim that an ESP32 is equivalent to a certified secure element. Instead, it asks a different question: how much hardware-wallet security can be made understandable, reproducible, auditable and affordable using completely open hardware and software?

  • Building and auditing the entire device themselves, from firmware to companion application, on a desktop, on Android, or as a browser extension.

The project is also intentionally inexpensive. The basic ESP32-S3, OLED and button hardware can cost roughly $8–15, and the camera build that signs air-gapped costs a few dollars more. That makes hardware-wallet experimentation and security education accessible to developers who may never purchase a dedicated commercial device.

LeekWallet does not claim that an ESP32 is equivalent to a certified secure element. Instead, it asks a different question: how much hardware-wallet security can be made understandable, reproducible, auditable and affordable using completely open hardware and software?

The result is both a usable testnet wallet and an open security research platform that developers can inspect, modify, break, test and improve.

Challenges I ran into

This was my first project using an ESP32-S3 as the security-critical hardware of a system. I am not a hardware or embedded-software engineer, so a large part of the project became an exercise in learning through debugging, measurement and testing.

One of the hardest challenges was entropy and seed generation. Generating a wallet seed sounds simple until the quality of the random source becomes part of the security model. I did not want the firmware to silently continue if its entropy source failed, so the design evolved toward hardware RNG health checks, fail-closed behavior, mandatory user-generated entropy and optional physical dice. I also had to think carefully about what entropy could honestly be counted rather than simply claiming that any unpredictable-looking input was secure.

Another major challenge was building a secure communication protocol between the hardware wallet and untrusted companion devices. LeekWallet communicates with Linux, macOS, Windows and Android over USB or BLE. That meant dealing not only with encryption but also authentication, replay protection, framing, BLE packet fragmentation and session lifecycle. The current protocol uses X25519, HKDF and ChaCha20-Poly1305, with a passkey derived from the handshake and verified on the wallet's own screen.

BLE introduced several particularly difficult bugs because the same logical protocol behaves very differently when transported through small MTU-sized packets. Building protocol conformance tests for both USB and BLE helped uncover cases where a command worked over one transport but failed over the other.

The signing flow was another challenge. I did not want the ESP32 to blindly sign hashes prepared by the companion. The device therefore parses EIP-1559 transactions, re-serializes them and calculates the digest itself. Contract calls added another layer: the firmware needs to decide what it understands well enough to display. That led to a deliberately small, refuse-by-default decoder rather than trying to support arbitrary calldata.

Removing the cable entirely was the hardest thing I have built so far. On the camera version the device reads a transaction request off a phone's screen and answers with a QR code of its own, following EIP-4527, so the wallet can sign with no USB and no radio. Two things made this difficult. The first was the wire format: animated QR carries a message in fragments with error correction, and both sides have to agree exactly, so I wrote the encoder and decoder twice, once in C for the device and once in TypeScript for the companion, and drove both from the same generated test vectors. Wherever they disagreed, one of them was wrong, which is how several parser faults surfaced before any hardware ran. I also wrote a second, stricter parser for the signing format, on the rule that a new test vector comes first and a parser change second.

The second difficulty was physical, and I did not expect it. A QR code on a 0.96-inch screen puts each square on a single 0.17 mm pixel, and whether it can be read at all comes down to optics: focus distance, exposure, screen brightness, and how long each fragment stays on screen relative to how often the camera captures. Almost every failure looked identical from the outside, a camera that was on with nothing happening, so I added counters for frames captured, codes located and codes read. The difference between those numbers is the diagnosis: nothing located means the code is too small or too dark, located but not read means the squares are not being resolved. I also learned that a laptop webcam cannot read that panel at all, which is a limitation I now document rather than work around.

That work also produced the most embarrassing kind of bug, the self-inflicted one. Trying to keep the image steady, I locked the camera's exposure after the first successful read, which on this sensor loads a stored exposure rather than the one in use, and frames stretched until capture timed out. Trying to reduce heat, I put the camera to sleep when the scanner closed, and since this board has no wire to reset the camera, it stayed asleep through every restart and reported no camera until the board was unplugged. Both looked like hardware faults. The serial log, which prints what the camera actually answered, is what distinguished my mistakes from a genuinely loose ribbon cable.

Performance had a similar lesson. Reading a QR felt far too slow, and I assumed optics. The real causes were that the decoder was being compiled with debugging enabled rather than optimisation, and that it used double-precision arithmetic on a chip whose floating-point unit only does single precision, so every calculation was emulated in software. Fixing those took a transaction from several seconds of hunting to a couple of seconds start to finish.

Embedded development also made ordinary software bugs more dangerous. Power can disappear during a PIN change or wipe, button events can arrive while a screen is

Tracks Applied (1)

Smart Devices, Open Hardware & Privacy Hardware

LeekWallet fits the Smart Devices, Open Hardware & Privacy Hardware track because the hardware is not simply a periphera...Read More

Cheer Project

Cheering for a project means supporting a project you like with as little as 0.0025 ETH. Right now, you can Cheer using ETH on Arbitrum, Optimism and Base.

Discussion

Builders also viewed

See more projects on Devfolio