Skip to main content

Quick start — embed a Keyban wallet in a React app

Tutorial

What you'll build

A bare-bones React app, scaffolded with Vite, that signs a user in with Google and shows their non-custodial wallet address — derived on the fly by the Keyban SDK, no seed phrase, no extension. The same wiring applies to Email OTP, Phone OTP or Auth0 once the providers are in place.

  • Time~30 min
  • DifficultyBeginner — basic React + npm
  • You'll needNode.js 18+, an App ID from the Keyban Admin Portal

The stack you're wiring

Three pieces talk to each other: your React app, the Keyban SDK, and the Keyban backend. The SDK is the only layer you import — it brokers authentication, MPC key derivation and ledger calls so your code never handles a private key.

  1. Your app

    • React + Vite

      Renders <KeybanProvider> and reads useKeybanAccount.

  2. SDK

    • @keyban/sdk-react

      Auth, MPC client share, account hooks.

  3. Keyban platform

    • Keyban backend

      Issues sessions, holds the server share, signs on-chain.

  4. Ledger

    • Stellar Testnet

      Default network for the Loyalty product family.

A four-layer stack: the React app calls into @keyban/sdk-react, which talks to the Keyban backend, which settles writes on the chosen ledger.

Step 1 — Provision an application

Open the Keyban Admin Portal and create an application. The product family you pick determines the ledger:

  • Loyalty → Stellar (the network used in this tutorial)
  • Digital Product Passport → Starknet
  • Embedded Wallet (generic) → Base

network is immutable on an application — testnet artefacts do not migrate to mainnet, so plan accordingly. Copy the App ID from the application's detail panel; you'll paste it in Step 4.

Step 2 — Scaffold the React app

Vite gives you a typed React skeleton in a few seconds.

npm create vite@latest my-wallet-app -- --template react-ts
cd my-wallet-app

Step 3 — Install the Keyban React SDK

npm install @keyban/sdk-react

The package re-exports everything you need: the provider, the auth and account hooks, and the Network enum.

Step 4 — Wire up the providers and the login UI

Replace src/App.tsx with the snippet below. Three things to notice:

  • LocalStorageClientShareProvider keeps the user's MPC client share in the browser — fine for a tutorial, not for production. See ClientShareProvider for the secure alternatives.
  • Suspense boundaries are mandatory: the SDK's hooks suspend while the client share is being fetched and while the account is being derived.
  • signIn({ type: "google" }) triggers the Google OAuth pop-up. To use Email OTP, Phone OTP or Auth0 instead, follow the dedicated Email OTP tutorial — those flows need extra fields (emailInputName, otpInputName, …).
import {
KeybanProvider,
Network,
useKeybanAccount,
useKeybanAuth,
type ClientShareProvider,
} from "@keyban/sdk-react";
import { Suspense } from "react";

class LocalStorageClientShareProvider implements ClientShareProvider {
async get(key: string): Promise<string | null> {
return window.localStorage.getItem(key);
}
async set(key: string, clientShare: string): Promise<void> {
window.localStorage.setItem(key, clientShare);
}
}

const clientShareProvider = new LocalStorageClientShareProvider();

function AccountInfo() {
const { user, signOut } = useKeybanAuth();
const [account, accountError] = useKeybanAccount();

if (accountError) return <p>Error loading account: {accountError.message}</p>;

return (
<div>
<p>Welcome, {user?.name}!</p>
<p>Wallet address: {account.address}</p>
<button onClick={() => signOut()}>Logout</button>
</div>
);
}

function WalletInfo() {
const { user, signIn } = useKeybanAuth();

if (!user) {
return <button onClick={() => signIn({ type: "google" })}>Login with Google</button>;
}

return (
<Suspense fallback={<div>Loading account…</div>}>
<AccountInfo />
</Suspense>
);
}

export default function App() {
return (
<KeybanProvider
network={Network.StellarTestnet}
appId="YOUR_APP_ID"
clientShareProvider={clientShareProvider}
>
<h1>My Keyban Wallet</h1>
<Suspense fallback={<div>Loading…</div>}>
<WalletInfo />
</Suspense>
</KeybanProvider>
);
}

Replace "YOUR_APP_ID" with the value from Step 1.

Step 5 — Run it

npm run dev

Open http://localhost:5173. You should see:

  1. A Login with Google button.
  2. After authenticating, your wallet address (G… for Stellar) and a Logout button.

If the wallet address never appears, the most likely culprits are an incorrect appId, a network mismatch with the application's product family, or third-party cookies blocked in your browser.

Next steps