Docs

MoonX, PayBox, and x402 for people who still have email.

Passkey app

you want users who still have email. they should get a wallet without a seed phrase lecture. moonx does that. pretending otherwise is how you invent support tickets.

stack

  • @moon-x/react-sdk - MoonXProvider, useMoonX().start(), ethereum wallet hooks
  • passkey step-up for wallet create / sign (moonx presence tokens)
  • optional app session cookie after JWKS verification (k4d pattern: POST /api/auth/session)

official: moonx getting started

steps

1. keys

create an app in the moonx dashboard. ship moon_pk_* to the browser. keep moon_sk_* on the server. forever.

2. provider

import { MoonXProvider } from "@moon-x/react-sdk";
import "@moon-x/react-sdk/style.css";

export function AppProviders({ children }: { children: React.ReactNode }) {
  return (
    <MoonXProvider publishableKey={process.env.NEXT_PUBLIC_MOONX_PUBLISHABLE_KEY!}>
      {children}
    </MoonXProvider>
  );
}

3. sign in

import { useMoonX } from "@moon-x/react-sdk";

export function SignIn() {
  const { start, user, ready } = useMoonX();
  if (!ready) return <span>…</span>;
  if (user) return <span>signed in</span>;
  return <button onClick={() => start()}>sign in</button>;
}

email OTP or google/apple oauth. the modal is not optional homework.

4. wallet + passkey

import { useCreateWallet } from "@moon-x/react-sdk/ethereum";
import { useSignMessage } from "@moon-x/react-sdk/ethereum";

export function WalletBit() {
  const { createWallet } = useCreateWallet();
  const { signMessage } = useSignMessage();
  return (
    <>
      <button onClick={() => createWallet()}>create wallet</button>
      <button onClick={() => signMessage({ message: "hello" })}>sign</button>
    </>
  );
}

first sensitive op enrolls a passkey. moonx never holds the raw key material. that is the entire point.

5. backend session (optional, k4d style)

verify moonx access/identity tokens against your app JWKS, then mint your own http-only session. see backend verification. k4d wires this at /api/auth/session.

pitfalls

  • missing NEXT_PUBLIC_MOONX_PUBLISHABLE_KEY means a brick wall, not a vibe.
  • allowed origins in the moonx dashboard must include every host you actually use (gateway, escrow, docs, localhost ports).
  • do not name this product "human wallet". that brand is taken. say passkey / embedded / email-in.

next