Building a Biometric Crypto Wallet (That Actually Works!)

Published: (January 13, 2026 at 07:05 PM EST)
5 min read
Source: Dev.to

Source: Dev.to

The “Why Did I Do This Again?” Moment

So, I built a mobile crypto wallet. But not just any wallet – one where you create your wallet using your face (or fingerprint) and send money without paying gas fees. Sounds cool, right? Well, it kind of is, and I’m here to tell you it’s also kind of not.

Let me back up.

A few weeks ago I stumbled upon Lazorkit. They had this wild idea: what if, instead of making people memorize 12‑word seed phrases (which, let’s be honest, most people just screenshot and pray their phones don’t get stolen), we used biometric authentication? You know, the Face ID thing you use to unlock your phone 50 times a day anyway?

Challenge accepted.

What I Built

The app is pretty straightforward:

  1. Tap “Create Wallet.”
  2. Your phone asks for Face ID or fingerprint.
  3. Boom – you have a Solana wallet.
  4. You can send USDC tokens without having SOL for gas fees (gas‑less transactions via a paymaster).

That’s it. No seed phrases. No “write this down on a piece of paper and hide it in your mattress.” Just your face.

Tech Stack

  • React Native (with Expo SDK 54)
  • TypeScript (because I like knowing what’s breaking before it breaks)
  • Solana blockchain (Devnet for testing)
  • Lazorkit SDK (the magic sauce)
  • WebAuthn passkeys (the real magic sauce)

The “Oh Crap” Moments (aka What I Learned)

1. Polyfills Are Your Secret Enemies

React Native doesn’t have all the JavaScript globals that web browsers do. Solana’s SDK expects things like Buffer and crypto.getRandomValues() to just… exist. They don’t.

I spent two hours debugging a cryptic error about randomness before realizing I needed to import polyfills – and import them in the exact right order at the very top of my app:

// This order matters. Don't ask me why. I've been hurt before.
import 'react-native-url-polyfill/auto';
import { Buffer } from 'buffer';
global.Buffer = Buffer;
import 'react-native-get-random-values';

Move these around and your app explodes. Fun times.

2. Simulators Are Liars

You can’t test biometric authentication properly on a simulator. I mean, you can, but it’s like testing a swimming pool by looking at a picture of water. The iOS simulator’s “fake Face ID” feature sort of works, but deep‑linking to the Lazorkit portal and back? That’s where things get weird.

Hot tip: Get a physical device. Test on real hardware. Trust me on this one.

3. WebAuthn Is Actually Pretty Cool

Here’s the thing nobody told me: WebAuthn passkeys are just public‑key cryptography with better UX. When you create a wallet:

  1. Your phone generates a key pair.
  2. The private key stays in your device’s Secure Enclave (the same place your fingerprint data lives).
  3. The public key goes to Lazorkit’s portal service.
  4. When you need to sign something, your phone uses Face ID to unlock the private key.

It’s like having a hardware wallet, but your phone is the hardware wallet. Mind. Blown.

4. Gasless Transactions Are Secretly Not Gasless

Plot twist: “gasless” transactions still have gas fees. You just don’t pay them – a paymaster does.

How it works

  1. You create a transaction (e.g., send 1 USDC to a friend).
  2. The paymaster service looks at it and says, “Cool, I’ll pay the SOL fee.”
  3. The paymaster signs the transaction with its wallet.
  4. You sign it with your biometric wallet.
  5. Transaction goes through; you paid $0.

Catch: The paymaster won’t create token accounts for you. If the recipient doesn’t already have a USDC account, the transaction fails. This burned me during testing until I realized I could just send USDC to myself.

5. Deep Linking Is Dark Magic

To make biometric authentication work, the app needs to:

  1. Open Safari/Chrome.
  2. Load the Lazorkit portal page.
  3. Trigger Face ID.
  4. Redirect back to your app.

That requires deep‑linking configuration in app.json:

{
  "scheme": "lazorkitstarter"
}

Getting this right took me three tries because I kept using weird characters. Keep it simple: lowercase, no spaces, no special characters. Future you will thank present you.

The “Wait, This Actually Works?” Moment

After wrestling with polyfills, deep links, and trying to understand why my transaction kept failing (spoiler: I had no test USDC), I finally got it working.

I opened the app, tapped “Create Wallet,” looked at my phone for Face ID, and BAM – I had a Solana wallet.

No seed phrases. No friction.

It felt like science fiction, but it’s just good API design.

The Tutorials (Because I Like You)

Tutorial 1: Wallet Creation with Biometric Authentication (~30 min)

  • Setting up polyfills (the right way)
  • Configuring LazorKitProvider
  • Deep linking between your app and the portal
  • Handling biometric authentication callbacks

Tutorial 2: Gasless USDC Transactions (~40 min)

  • Building Solana transactions with @solana/web3.js
  • Integrating a paymaster for gasless fees
  • Proper blockhash management (they expire after 60 seconds and will ruin your day)
  • Error handling and validation

Who Is This For?

You should build this if:

  • You’re learning React Native and want a real‑world project.
  • You’re curious about Solana mobile development.
  • You want to understand how WebAuthn passkeys work.
  • You like the idea of crypto wallets without seed phrases.

You should NOT build this if:

  • You need production‑ready code (this is Devnet only, folks).
  • You hate TypeScript.
  • You don’t have a physical device to test on.

Testing on a Physical iPhone or Android Device

  • You’re allergic to polyfills. (just a light‑hearted note – you’ll need a real device to run the app, not a polyfilled environment).

TL;DR

I built a mobile crypto wallet with Face ID authentication and gasless transactions. It uses WebAuthn passkeys (no seed phrases!), runs on Solana Devnet, and actually works. I learned way too much about polyfills, deep linking, and why simulators are not your friends.

If you’re learning mobile dev or blockchain stuff, give it a shot. If nothing else, you’ll have a very strong opinion about import order.

Built this? Got stuck? Found a bug? Hit me up – I’m always down to talk about why something broke.

P.S. If you try this and your app crashes because of polyfill order, just know I told you so. 😅

Back to Blog

Related posts

Read more »