MONAVYSelf-host it

Wallet infrastructure · self-hosted · MIT

Not your keys,
not your coins.

Monavy is Privy, but free — and the key never leaves your user's device.

Same drop-in modal, same hooks, same transfer webhooks. You host it, so it costs nothing. The key is generated in your user's browser, so there is nobody left who could hand it over.

$0 self-hostedNo key custody, ever10 chains built inSigned transfer webhooks
providers.tsx
<MonavyProvider appId="app_live_…" apiUrl="https://monavy.acme.dev">
  {children}
  <MonavyModal appName="Acme" />
</MonavyProvider>

// that's the integration. the key is made here, in the browser,
// and there is no code path that uploads it.

Two differences

Everything Privy does. Two things it can't.

Monavy matches the developer experience — embedded wallets, email login, passkeys, React hooks, webhooks. It parts ways on custody and on price.

01

Free when you host it

The SDK, the server, the dashboard and the webhook pipeline are one MIT repository. Clone it, point it at a SQLite file, and you are running the whole product. No seat pricing, no MAU tier that resets your budget in month four, no vendor who can raise the price of your login screen.

Cost per monthly active wallet
$0
Data leaving your infrastructure
none
Vendor able to lock you out
none

02

The key never leaves the device — and never had to travel to get there

A hardware wallet is safe once it reaches you. Getting it to you is the weak part: it has to be manufactured, sold and shipped, and that distribution chain necessarily knows your name and your street address. Those customer databases have leaked. Monavy has no distribution chain. The key is generated on hardware the user already owns, sealed with their passkey, and stored encrypted in their browser.

Where the key is created
the user's device
Who ships anything to the user
nobody
Personal data in a fulfilment database
none

Architecture

One line separates what you run from what you can never see.

Everything on the left happens in the user's browser. Everything on the right is your server. Nothing crosses that line except public data.

The user's device

secp256k1 keypair
generated by WebCrypto, in the tab
AES-256-GCM vault
sealed with a passkey (WebAuthn PRF) or PBKDF2 passcode
IndexedDB
ciphertext at rest; auto-locks after idle
Every signature
produced locally, then broadcast to the chain's RPC

No code path in @monavy/core passes key material to a network call. That is the invariant the whole design rests on.

Your server

Email + one-time code
identifies the user; grants no signing power
Wallet registry
addresses and protection type — public data
Event outbox
transfers reported by the SDK, stored durably
Signed delivery
HMAC-SHA256 per endpoint, with retries

Take this server offline and users can still sign and send. They lose the dashboard and the webhooks — not their money.

Transfer webhooks

Your backend finds out about the transfer without watching the chain.

The SDK reports every ERC20, ERC721 and ERC1155 transfer it signs — submitted, confirmed, reverted. Your Monavy server stores it, signs it with the endpoint's own secret, and retries for a day if your service is down.

app/providers.tsx — client
<MonavyProvider
  appId={APP_ID}
  apiUrl="https://monavy.acme.dev"
  webhooks={{ endpoint: `${API}/api/v1/events` }}
>

// queued in localStorage, batched, retried with
// backoff. a closed tab still delivers on next load.
app/api/webhooks/route.ts — your server
import { createWebhookHandler } from "@monavy/webhooks/server";

export const POST = createWebhookHandler({
  secret: process.env.MONAVY_WEBHOOK_SECRET!,
  onEvent: async (event) => {
    if (event.type !== "transfer.confirmed") return;
    await fulfilOrder(event.data.hash, event.data.chainId);
  },
});

// HMAC-SHA256 over "<timestamp>.<raw body>", constant-time
// compared, replay window enforced. throw to get a retry.

Same event shape on every chain

EthereumBaseOptimismArbitrumPolygonSepoliaBase SepoliaOP SepoliaArbitrum SepoliaAmoy+ any EVM chain you pass in

Honest comparison

Where Monavy wins, and where it doesn't.

A managed provider takes real work off your plate. If you would rather buy that than run it, buy it. This table is for the teams who would rather run it.

 MonavyManaged embedded wallets
Where the private key livesThe user's device, onlySplit across provider-operated shares
Price at 100k monthly wallets$0 — you host itPriced per monthly active wallet
Can the vendor be compelled to act?There is no vendorThe provider holds a share
Runs with the vendor offlineYes — signing is localNo
Source availableMIT, whole stackClient SDKs
Email / passkey loginIncludedIncluded
React hooks + drop-in modalIncludedIncluded
Signed transfer webhooksIncluded, with retriesIncluded
Someone else runs the serversNo — that is the tradeYes
Compliance paperwork handled for youNo — that is the tradeYes

Comparison describes the self-hosted Monavy stack in this repository against the general shape of managed embedded-wallet services. Check any specific vendor's current documentation before making a decision on it.

Pricing

Zero, forever, when you host it.

There is no paid tier of Monavy and no feature held back for one. The only thing you can pay for is somebody else doing the setup.

Self-hosted
$0forever

Clone it, point it at a SQLite file, and you are running the whole product. No seat pricing, no monthly-active-wallet meter, and no vendor who can reprice your login screen later.

  • Unlimited wallets and monthly actives
  • Every chain, including any EVM chain you add
  • Signed transfer webhooks with retries
  • Dashboard, wallet registry and delivery log
  • Passkey and passcode vaults, recovery kits
  • The whole stack, MIT licensed
Run it in 60 seconds

Installation

Talk to Digital Native

Want Monavy running in your stack without doing it yourself? Digital Native installs and configures it for you. The software stays free and yours — you are paying for the setup, not for a licence.

  • Deployed into your infrastructure
  • Origin allow-list, email delivery and RPCs configured
  • Wired into your existing app and backend
  • Handover with your team
digitalnative.vip ↗

Quickstart

Running locally in about a minute.

No account to create, no API key to wait for, no card on file.

  1. 01

    Clone and install

    One repository holds the SDK, the server, the dashboard and a working example dapp.

    git clone https://github.com/hskang9/monavy
    cd monavy && pnpm install && pnpm build
  2. 02

    Start your server

    SQLite by default, so there is nothing to provision. Seeding creates an operator account and a demo app.

    pnpm --filter @monavy/admin db:push
    pnpm --filter @monavy/admin seed
    pnpm dev:admin        # → localhost:3002
  3. 03

    Wire up your app

    Wrap the tree once. The modal handles login, wallet creation, unlock and recovery.

    pnpm add @monavy/react @monavy/webhooks
    
    <MonavyProvider appId="app_…" apiUrl="https://monavy.acme.dev">
      {children}
      <MonavyModal appName="Acme" />
    </MonavyProvider>