Quick start — embed a Keyban wallet in a React app
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 IDfrom 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.
Your app
React + Vite
Renders <KeybanProvider> and reads useKeybanAccount.
SDK
@keyban/sdk-react
Auth, MPC client share, account hooks.
Keyban platform
Keyban backend
Issues sessions, holds the server share, signs on-chain.
Ledger
Stellar Testnet
Default network for the Loyalty product family.
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:
LocalStorageClientShareProviderkeeps the user's MPC client share in the browser — fine for a tutorial, not for production. SeeClientShareProviderfor the secure alternatives.Suspenseboundaries 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:
- A Login with Google button.
- 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
- Send a transaction. The
KeybanAccountclass exposestransfer,transferERC20,transferNFT. Get test tokens from the How to get test tokens guide. - Harden the client share. Move it off
localStorage— see Security & best practices. - Browse the SDK surface. Full reference at
@keyban/sdk-react. - Stuck? Join the Discord community.