Setup
Everything on the client runs through one component: the provider. You wrap your app in IAMGameWalletProvider once, give it your publishable key, and every wallet hook and component below it just works. This page gets that mounted correctly and explains what you get in return.
New to the mental model (apps, keys, environments, the custodial wallet)? Read Core concepts first — this page assumes you know what a publishable key is.
1. Install
One package covers the provider, hooks, and prebuilt components.
npm install @iamgame/wallet-sdkRequires React 18+. The SDK is client-side — see the SSR note below.
2. Store your publishable key
The publishable key (pk_test_… / pk_live_…) ships in your client bundle, so it belongs in a public env var. In Next.js that means the NEXT_PUBLIC_ prefix, otherwise the value isn’t exposed to the browser.
# .env.local (never commit real keys)
NEXT_PUBLIC_IAMGAME_WALLET_PK=pk_test_your_key_herepk_ can only act for the wallet of whoever is currently signed in, so it’s safe in the browser. Your sk_ secret key must never appear in client code or a NEXT_PUBLIC_ var — it stays on your backend.3. Wrap your app in the provider
Point the SDK at the API with baseUrl and pass your key. Mount it high enough that every part of your game that touches the wallet is inside it — typically your root layout.
"use client";
import { IAMGameWalletProvider } from "@iamgame/wallet-sdk";
export function WalletProviders({ children }: { children: React.ReactNode }) {
return (
<IAMGameWalletProvider
publishableKey={process.env.NEXT_PUBLIC_IAMGAME_WALLET_PK!}
baseUrl="https://api-wallet.iamgame.com/v1"
onError={(err, { operation }) => {
// Wire this to your error tracker (Sentry, etc.).
console.error("[wallet]", operation, err);
}}
>
{children}
</IAMGameWalletProvider>
);
}The three props you’ll actually set:
| Prop | Required | What it does |
|---|---|---|
publishableKey | Yes | Your app's pk_. Picks the environment (test → devnet, live → mainnet) and identifies your app. |
baseUrl | Yes | The wallet API. Use https://api-wallet.iamgame.com/v1 for both test and live — the key decides the environment, not the URL. |
onError | Optional | Called when any wallet operation fails in the UI (login, sign, withdraw, export, wallet load, or a render crash). Wire it to your error tracker; omit it and failures just aren't reported. |
initData — no button, no modal. Pass autoTelegram={false} to require an explicit login instead. Outside Telegram it’s a silent no-op. More in Login & sign-in.What the provider gives you
Once mounted, everything below it can read the auth state and the signed-in player’s wallet through hooks and components — no prop-drilling, no manual token passing:
- Auth state & sign-in methods via
useWalletAuthand the prebuiltWalletLogin/WalletLoginModal. - The wallet, address & balances via
useWallet,useWalletBalanceandWalletAddress/WalletBalance. - Signing, deposit, withdraw & export via
useWalletSign,WalletDeposit,WalletWithdraw,WalletExport.
Session persistence
On a successful login the provider stores a session and, by default, persists it in localStorage so the player stays signed in across reloads. On mount it bootstraps that stored session, silently refreshing the access token if it has expired. Your auth status moves through loading → anonymous → authenticated as this settles.
Need a non-persistent session (e.g. an embedded/kiosk context)? Swap the storage strategy — both are exported:
import { IAMGameWalletProvider, inMemorySession } from "@iamgame/wallet-sdk";
<IAMGameWalletProvider
publishableKey={process.env.NEXT_PUBLIC_IAMGAME_WALLET_PK!}
baseUrl="https://api-wallet.iamgame.com/v1"
storage={inMemorySession()} // default is localStorageSession() — persists across reloads
>
{children}
</IAMGameWalletProvider>The client session token is short-lived and is not proof of identity on its own — your backend must verify it server-to-server. That handoff lives in Authentication.
SSR & “use client”
The provider, hooks, and components use React state and browser APIs (localStorage, window.Telegram), so they only run in the browser. In the Next.js App Router, any file that mounts the provider or calls a wallet hook needs the “use client” directive at the top.
- Put the provider in a small client component (like
WalletProvidersabove) and render that from your serverlayout.tsx— the layout itself stays a server component. - Anything calling
useWalletAuth,useWallet,useWalletBalance, etc. must also be a client component.
// app/layout.tsx (server component — no "use client")
import { WalletProviders } from "./WalletProviders";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<WalletProviders>{children}</WalletProviders>
</body>
</html>
);
}useIsTelegram() return false on the server and the first client render, then the real value after mount — so they never cause a hydration mismatch. You don’t need to guard them yourself.Where to go next
- Login & sign-in — add a working sign-in with the drop-in component or your own UI.
- Address & balances — show the player’s wallet and funds.
- Core concepts — apps, keys, environments, and the money models.