Core concepts

Five ideas explain almost everything about integrating IAMGame Wallet. Read this once and the rest of the docs will click into place: apps & keys, environments, the custodial wallet, identities & scope, and the money models.

Apps & keys

You create an app in the developer portal. Every app gets two API keys that split cleanly by where they run:

KeyPrefixRuns whereCan do
Publishablepk_test_… / pk_live_…Frontend (shipped in your game client)Start logins, read the signed-in user's own wallet
Secretsk_test_… / sk_live_…Backend only — never in the browserVerify sessions, move money, run the ledger, pay referrals
Never ship a secret key
A pk_ is safe in client code — it can only act for the wallet of whoever is currently signed in. An sk_ can move money for any user in your app; keep it on your server and in your secret manager.

Multiple apps belong to a studio (your team/organisation). Team members, billing, and live-access approvals live at the studio level; keys, currencies, and config are per-app.

Environments: test and live

Every app has two isolated environments, keyed off which key you use:

  • test (pk_test_ / sk_test_) — runs on Solana devnet. Free test tokens, nothing is real. New apps start here.
  • live (pk_live_ / sk_live_) — runs on Solana mainnet, real money. You request live access in the portal once you’re ready.

Users, wallets, balances, and sessions are completely separate across the two environments — a test user is not a live user. Point your dev/staging builds at test keys and your production build at live keys; the same code works against both.

The custodial wallet

When a player signs in, IAMGame provisions them an embedded Solana wallet — a real on-chain address whose key is held in secure hardware (KMS) on the signer, not in the browser. Players never see a seed phrase or install an extension. Your game asks the wallet to sign or move funds through the SDK; the signer does the cryptography.

Self-custody is still possible
Custodial is the default (best UX for games), but a player can export their wallet to take full self-custody at any time — see Withdraw & export.

Players can also sign in with an external wallet (Phantom, Solflare, Backpack) via Sign-In-With-Solana — that’s a login method, covered in Authentication.

Identities & scope

A user is identified by how they logged in — an identity is a(type, externalId) pair: a Solana pubkey (SIWS), a Telegram user id, or an email address. The same person signing in the same way always resolves to the same user and the same wallet.

Scope decides whether wallets are shared across your apps. By default apps are GLOBAL-scoped: a player who signs in with the same identity across two of your apps gets one wallet, shared. An app can instead be isolated, giving its users their own wallets separate from your other apps. Most integrations want the shared default.

Why this matters
If you run several games and want a player’s balance to follow them everywhere, keep the default shared scope and have them log in the same way in each game. If a game must ring-fence its funds (e.g. a regional/regulatory boundary), isolate it.

The money models

There are three server-side ways to move value, and picking the right one is the most important integration decision. A quick map — the Choose a money model page goes deep:

ModelUse it forHow it works
LedgerHigh-frequency play (slots, crash, per-tick betting)Open a session with a lock, then bet/win/rollback off-chain at speed, settle once. No on-chain tx per action.
Custodial treasuryReal-money balances users top up and cash outUser's real wallet ↔ your game treasury. deposit / withdraw move actual on-chain USDC, tracked to a confirmed signature.
Pool-escrow custodyPari-mutuel pools (everyone stakes, winners split)Lock each stake into a pool, settle the whole pool atomically with a conservation guard, refund if voided.

They compose. A typical real-money game uses the ledger for fast in-round play, the treasury for deposits/withdrawals at the cash boundary, and referrals on top to pay a network cut of the rake.

Amounts are integers

Every amount in the API is an integer string in the token’s smallest unit — never a float. SOL is in lamports (109), USDC in micro-USDC (106). Use BigInt, and pass amounts as strings so nothing rounds.

TS
const oneUsdc  = "1000000";      // 1 USDC = 10^6 micro-USDC
const halfSol  = "500000000";    // 0.5 SOL = 5 × 10^8 lamports

// format for display with the SDK helper — never parseFloat a raw amount
import { formatTokenAmount } from "@iamgame/wallet-sdk";

Referrals — the full loop

The wallet has a built-in multi-level referral system so you can reward players who bring other players. It spans the client and your server; here’s the whole loop end-to-end so the two halves make sense together:

StepWhereWhat happens
1. CaptureClientA player arrives on a ?ref=CODE link. The SDK captures the code and holds it (see Referrals in your UI).
2. AttributeClient → serverOn their first sign-in the code is attached, and the wallet records first-touch attribution (immutable, within a 7-day window).
3. Build the chainAutomaticAttribution forms an upward chain: L1 = whose code they used, L2 = that person’s referrer, and so on.
4. RewardServerWhen a round takes house rake, you call server.referrals.distribute to split a cut up that chain. You choose what % of the rake and how it splits per level.
5. WithdrawServer / playerEarnings accrue as off-chain credits; the referrer withdraws them to their wallet with server.referrals.withdraw.

Client side you only capture and display; all the money logic (attribution, the split, payouts) is server-side with your sk_ key. Full detail: Referrals in your UI (capture) and Referral payouts (reward & withdraw).

Where to go next