Overview
KalmForge.StoreCatalog is a static class. Items and bundles are authored on the dashboard with prices, currencies, translations and images; the SDK fetches them in one call and exposes typed Item / Bundle records.
Fetching the catalog
1var catalog = await StoreCatalog.GetAsync(lang: Localization.CurrentLanguage);2foreach (var item in catalog.items)3 Debug.Log($"{item.resolved.name} {item.price} {item.currency}");4foreach (var b in catalog.bundles)5 Debug.Log($"{b.resolved.name} contains {b.items.Count} items");Loading images
1if (item.HasImage) {2 var tex = await StoreCatalog.LoadTextureAsync(item);3 var sprite = await StoreCatalog.LoadSpriteAsync(item);4}image is an opaque token, not a URL - always call the helpers; they sign the download via the SDK's HTTP layer.
Recording purchases
Use MakePurchaseAsync for the full flow - it appends to local history first (so HasPurchased / GetPurchaseCount reflect it immediately), then logs to the backend. Failed logs stay in history marked synced = false.
1var result = await StoreCatalog.MakePurchaseAsync(item, pricePaid: item.price);2if (result.Synced) Debug.Log("Backend confirmed");34// Bundles use the same overload:5var b = await StoreCatalog.MakePurchaseAsync(bundle, pricePaid: bundle.price);67// If you only want to log, without local history:8await StoreCatalog.LogPurchaseAsync(item.id, null, item.price, item.currency);Local history
1bool owns = StoreCatalog.HasPurchased(item);2int copies = StoreCatalog.GetPurchaseCount(bundle);3float totalUsd = StoreCatalog.GetTotalSpent("USD");4var records = StoreCatalog.GetHistory(); // newest last56StoreCatalog.ClearHistory(); // local onlyRetrying failed logs
1int synced = await StoreCatalog.RetryUnsyncedAsync();2Debug.Log($"resynced {synced} pending purchases");API reference
| Name | Type | Description |
|---|---|---|
| GetAsync(lang?) | Task<Catalog> | Items + bundles localised to lang (or default). |
| LoadTextureAsync(item / bundle / token) | Task<Texture2D> | Download & decode an image to RGBA32. |
| LoadSpriteAsync(item / bundle / token) | Task<Sprite> | Same, wrapped as a Sprite (full-texture rect, pivot 0.5). |
| LogPurchaseAsync(itemId, bundleId, pricePaid, currency) | Task<bool> | Pure backend log. No local history side effects. |
| MakePurchaseAsync(item, pricePaid, currency?) | Task<PurchaseResult> | Append to local history + log to backend. |
| MakePurchaseAsync(bundle, pricePaid, currency?) | Task<PurchaseResult> | Same, for a bundle. |
| GetHistory() | IReadOnlyList<PurchaseRecord> | Snapshot of all locally recorded purchases. |
| HasPurchased(item / bundle) | bool | Local-only check, no network. |
| GetPurchaseCount(item / bundle) | int | How many times locally recorded. |
| GetTotalSpent(currency) | float | Sum of price_paid across history in the given currency. |
| ClearHistory() | void | Wipe local history. Backend records are untouched. |
| RetryUnsyncedAsync() | Task<int> | Re-log any records whose previous backend write failed. |
| HistoryFileName | string (const) | "kalmforge_purchases.json". |
REST endpoint
1# Fetch the catalog2GET /api/public/sdk/catalog?lang=en3Headers: X-API-Key: kf_xxx_yyy45# Download an image (token comes from item.image / bundle.image)6GET /api/public/sdk/catalog-image?path=<token>78# Log a soft-currency purchase9POST /api/public/sdk/catalog10{ "item_id": "...", "bundle_id": null, "player_id": "...", "install_id": "...",11 "price_paid": 4.99, "currency": "USD" }