mera is a TypeScript library that derives secret key material from passkeys. A passkey ceremony returns 32 bytes, and those bytes seed an ordinary account on any chain, with no recovery phrase to write down, no smart contract account, and no third party in the signing path. mera is powered by the WebAuthn PRF extension, part of the standard behind passkeys and already shipping in mainstream authenticators.
Try it in the demo below: create a passkey, and the demo derives a crypto account from it and funds it with play money so you can trade shares in a fictional computer company. The passkey lives in your authenticator and is scoped exclusively to the demo.
The current state of crypto onboarding
Remember these twelve words… or lose all your crypto
The path to self-custody (nobody except the user can move funds) of crypto assets has not changed much in a decade. Most crypto wallets generate a recovery phrase (a BIP-39 mnemonic of twelve or twenty-four words) and ask the user to write it down.

Backing that phrase up is manual and easy to get wrong. As of early 2025, analysts estimate that 2.3 million - 3.7 million bitcoin are permanently lost.
New devices
It gets even more difficult if you use crypto on multiple devices. You may have created the seed phrase from a browser extension, but if you want to access the relevant accounts on mobile, you’ll have to find a legitimate wallet application and input your recovery phrase or import private keys. That process is cumbersome and not without exploitation risk from bad actors who would love you to input that sensitive information into their “wallet” app. You wouldn’t be the first to wonder, “is this browser extension with 300 reviews safe?”
Hosted logins are another option. Users sign in with an identity provider such as Google, and a third-party service like Privy holds or shards the key.
What are passkeys?
A passkey is a keypair held in a device’s secure hardware, unlocked by a biometric, PIN, or password, and synced across a user’s devices by the platform. Modern phones and laptops can create one, and every mainstream browser can use one. The user signs in with no password and no phrase to keep, and the application never manages the key: creating it, storing it, unlocking it, and syncing it all belong to the platform.
Each sign-in runs a ceremony. The site sends a one-time challenge, the browser hands it to the authenticator, and the authenticator asks for a face, fingerprint, or PIN before signing. What it signs is a fixed structure:
signature = sign(authenticatorData ‖ SHA-256(clientDataJSON))
The authenticator populates authenticatorData: a hash of the site’s ID, a signature counter, and flags such as whether the user was verified. The browser populates clientDataJSON: the challenge, the origin, and the type of operation. For a sign-in on account.example.com:
authenticatorData
rpIdHash 32 bytes SHA-256("account.example.com")
flags 1 byte user present, user verified, backup state
signCount 4 bytes uint32
clientDataJSON
{
"type": "webauthn.get",
"challenge": "<what the app sent, base64url>",
"origin": "https://account.example.com"
}
Each passkey lives on an authenticator (a phone, a laptop, or a security key) and works on exactly one site, the relying party. That is the credential crypto onboarding is missing: the platform creates it, protects it, and syncs it. So could a passkey signature authorize a blockchain transaction, making the authenticator the account?
Not directly. An application controls only the challenge payload, while the signature covers the whole envelope around it, including the origin. A blockchain cannot authenticate such a signature because:
- The envelope commits to the origin and the browser’s data, neither of which appears in the transaction it executes.
- EVM execution authenticates signatures on the secp256k1 curve, while passkeys sign on P-256 (also called secp256r1). Solana uses the Ed25519 curve.
The workaround is to move verification on-chain: a smart contract checks the passkey signature, and a precompile does the P-256 curve arithmetic (Monad implements this at address 0x0100). The account is then that contract rather than a keypair, which brings requirements of its own. A contract cannot initiate its own transaction, so this path relies on a bundler / relayer service or an executor account that the app runs itself, and each user’s account either needs to deploy a fresh contract (and incur costs) or perform an EIP-7702 delegation. Solana has its own P-256 precompile, which can be paired with a smart-account program like LazorKit or a third-party key service like Para or Privy. Every version of this adds infrastructure.
The other direction is to skip on-chain verification altogether and use the passkey as the source of a seed for an ordinary account.
Enter the WebAuthn PRF extension
In addition to the signature, the PRF extension returns 32 pseudorandom bytes that are completely determined by three things:
- A 32-byte salt
- Relying party ID, e.g. account.example.com
- Your passkey (unlocked by a fingerprint, face ID, pin, etc.)
This is incredibly powerful, because the output can be applied to any use case. Check out the interactive demo below, in which one 32-byte output maps cleanly onto multiple different domains, most notably generating a keypair on the secp256k1 curve (an EVM account) and a keypair on the ed25519 curve (a Solana account).
Three properties make the output usable as key material:
- Deterministic. The secret is created once per passkey. The same passkey, relying party, and salt return the same 32 bytes.
- Site-scoped. The secret belongs to the credential, and the credential to one relying party, so a phishing site gets different bytes from a different credential.
- Full entropy. HMAC-SHA-256 output is 32 uniformly distributed bytes (full-strength randomness), directly usable as a seed or a private key.
The PRF extension was proposed in May 2020. More public commentary started in 2023, e.g. Encrypting Data in the Browser Using WebAuthn but only really started to pick up wider adoption by authenticators, operating systems and browsers in the past couple years (all three must be compatible). To our knowledge, mera is the first application of the PRF extension to the domain of crypto accounts.
What is mera?
mera is a small library (1600 LOC) of useful primitives for the crypto use case: passkey ceremonies that return PRF output, signing sessions for secp256k1 and Ed25519, address helpers, and an encrypted vault format. Deriving keys this way takes the recovery phrase out of onboarding. Users already entrust their authenticators with critical credentials and typically have secure methods of recovering access.
There are two ways to use the PRF output: derive the account’s keys from it, or use it to encrypt an independent secret, e.g. an existing seed phrase. The first application is passkey accounts.
Passkey accounts
The application runs the passkey-derived PRF bytes through its derivation scheme of choice; mera’s demo feeds them into BIP-39 and derives keys with BIP-32 for secp256k1 and SLIP-0010 for Ed25519. Additional accounts can be derived via HD paths, the standard hierarchy used by wallet applications for multiple accounts.

The demo uses the following code snippet for sign-in and keypair derivation.
import {
createSecp256k1SigningSession,
getEvmAddress,
getPasskeyPrfOutput,
} from "@category-labs/mera"
import { HDKey } from "@scure/bip32"
import { entropyToMnemonic, mnemonicToSeedSync } from "@scure/bip39"
import { wordlist } from "@scure/bip39/wordlists/english.js"
const { prfOutput } = await getPasskeyPrfOutput({ rpId: "account.example.com" })
const mnemonic = entropyToMnemonic(prfOutput, wordlist)
const seed = mnemonicToSeedSync(mnemonic)
const node = HDKey.fromMasterSeed(seed).derive("m/44'/60'/0'/0/0")
const session = createSecp256k1SigningSession({
privateKey: node.privateKey,
})
const address = getEvmAddress(session.publicKey)
A passkey account doesn’t require the app to persist any data, which removes the cross-device import described earlier. Wherever the authenticator syncs the passkey, the same ceremony returns the same bytes (and the same derived accounts). No third party sits in the signing path. The associated seed phrase can be exported (must be supported by the application) and later imported into any standard wallet application.
Loss of passkey access means loss of access to the derived accounts.
Secret vault
Another way to use mera is by encrypting an independent secret. Rather than deriving crypto accounts themselves, the PRF output derives a cryptographic key that can be used to encrypt the secret. This generates an encrypted version of the secret that can be stored by the application or authenticator (if supported). For more information, refer to the docs.

Developers should think critically about access to application memory during a passkey ceremony. Learn more in security model.
Why mera?
Category Labs’s contributions to open source software have been primarily dedicated to Monad consensus and execution. mera is a library with applications beyond Monad but aligns with our broader goal of improving crypto user experience with technical solutions. The hard part is adoption of the PRF extension by operating systems, browsers, and authenticators - six years of work and counting. mera applies that widely adopted feature to a blockchain context and solves the two onboarding issues raised earlier by:
- Offloading generation and management of a seed phrase to a (PRF-implementing) authenticator that is already trusted and low friction.
- Supporting access to mera-derived crypto accounts across different devices natively by inheriting syncing properties of existing authenticators.
mera is licensed under either the Apache License 2.0 or the MIT License, at the licensee’s option. We believe the crypto app experience has room for improvement and invite you to build with mera. Point your coding agent to the github repo, read the docs and let us know how it can be improved!