# Player — `client.player` `PlayerDomain` (source: `src/domains/PlayerDomain.ts`) — the observable player profile: player, linked identities, currency balances and inventory stacks. Synced under revision key `profile`. There is no separate ledger service in this SDK. Balances and items are read from the profile and are written server-side (admin adjust, module functions). ## Surface `client.player` is a `SyncedState`: ```ts client.player.value // PlayerProfile | undefined client.player.status // 'idle' | 'loading' | 'ready' | 'error' client.player.onChange((snapshot) => { /* fires immediately */ }); await client.player.load(); await client.player.reload(); // force refetch ``` ## Types ```ts interface PlayerProfile { balances?: CurrencyBalance[]; identities?: PlayerProfileIdentity[]; items?: InventoryStack[]; player?: Player; } interface PlayerProfileIdentity { createdAt: string; provider: string; // 'device' | 'google' | 'apple' | 'custom' | 'custom:' subject: string; } interface Player { createdAt?: string; id?: string; language?: string; nickname?: string; projectId?: string; region?: string; } interface CurrencyBalance { balance?: number; currency?: string; // currency slug configured in the dashboard } interface InventoryStack { item?: string; // item slug quantity?: number; } ``` ## Behavior notes - `balances` carries one entry per currency in the latest release, zero-filled for a player who never received it; `items` carries one entry per non-empty inventory stack. Both bump the `profile` revision when they change. - Warmed automatically at login (with catalog). - Kept fresh by the revision poll; call `reload()` after a module function that changes balances or items. - All fields are optional on the wire (`?`); code defensively. - React: `useSyncExternalStore` maps directly onto `onChange` (see the SDK README "React recipe").