@hyve-sdk/js
v2.4.0
Published
Hyve SDK - TypeScript wrapper for Hyve game server integration
Readme
@hyve-sdk/js
TypeScript SDK for integrating games with the Hyve platform. Provides authentication, telemetry, persistent storage, ads, billing, and native bridge capabilities.
Installation
pnpm add @hyve-sdk/jsQuick Start
import { HyveClient } from "@hyve-sdk/js";
// Authentication is automatic — the SDK reads hyve-access and game-id from the URL
const client = new HyveClient();
console.log("User ID:", client.getUserId());
console.log("Game ID:", client.getGameId());
console.log("Authenticated:", client.isUserAuthenticated());The SDK reads authentication from URL parameters automatically during construction:
https://your-game.com?hyve-access=eyJhbGci...&game-id=my-gameEnvironment detection happens automatically from the parent page URL (games run in iframes):
- Dev:
marvin.dev.hyve.ggordev.hyve.gg - Prod:
marvin.hyve.ggorhyve.gg - Override with
isDevin config for local testing only
React Integration
Import from @hyve-sdk/js/react for the React provider and hook:
import { HyveSdkProvider, useHyveSdk } from "@hyve-sdk/js/react";
function App() {
return (
<HyveSdkProvider config={{ isDev: true }}>
<Game />
</HyveSdkProvider>
);
}
function Game() {
const sdk = useHyveSdk();
const handleScore = () => {
sdk.sendTelemetry("game", "player", "score_submitted", null, null, { score: 1000 });
};
return <button onClick={handleScore}>Submit Score</button>;
}You can also pass a pre-created client:
const client = new HyveClient({ isDev: true });
<HyveSdkProvider client={client}>
<App />
</HyveSdkProvider>Telemetry
await client.sendTelemetry(
"game", // location
"player", // category
"action", // action
"combat", // sub-category (optional)
"attack", // sub-action (optional)
{ // event details (optional)
damage: 100,
targetId: "enemy-123",
}
);Requires a valid hyve-access JWT and game-id in the URL.
Persistent Game Data
Save and retrieve game data with either cloud (default) or local storage:
// Save a value
await client.saveGameData("player_level", 5);
await client.saveGameData("settings", { volume: 0.8, fullscreen: true });
// Get a value
const item = await client.getGameData("player_level");
console.log(item?.value); // 5
// Batch save
await client.batchSaveGameData([
{ key: "coins", value: 1200 },
{ key: "lives", value: 3 },
]);
// Batch get
const items = await client.getMultipleGameData(["coins", "lives"]);
// Delete
await client.deleteGameData("temp_key");
await client.deleteMultipleGameData(["key1", "key2"]);Storage Modes
// Set mode at construction
const client = new HyveClient({ storageMode: "local" });
// Or override per-call
await client.saveGameData("key", "value", "local");
await client.getGameData("key", "cloud");
// Change mode at runtime
client.configureStorage("cloud");
console.log(client.getStorageMode()); // "cloud"| Mode | Description |
|------|-------------|
| cloud | Synced to backend API (default) |
| local | Browser localStorage, device-only |
Ads
Ads are disabled by default and must be explicitly configured.
const client = new HyveClient({
ads: {
enabled: true,
onBeforeAd: (type) => game.pause(),
onAfterAd: (type) => game.resume(),
onRewardEarned: () => { player.coins += 100; },
},
});
const result = await client.showAd("rewarded");
if (result.success) {
console.log("User watched the ad");
}
await client.showAd("interstitial"); // between levels
await client.showAd("preroll"); // game start| Ad Type | Use Case |
|---------|----------|
| rewarded | User watches full ad for a reward |
| interstitial | Between levels or game screens |
| preroll | Before the game starts |
The SDK automatically routes ad calls through the appropriate platform SDK (CrazyGames, Playgama, or the default Google H5 Ads SDK) based on the current domain.
Platform Integrations
CrazyGames
When running on CrazyGames, the SDK auto-initializes the CrazyGames SDK and routes ads through it. Use these additional lifecycle methods:
// Call when gameplay begins (required by CrazyGames policy)
await client.gameplayStart();
// Call when gameplay stops (paused, died, menu, etc.)
await client.gameplayStop();
// Trigger a celebration effect on the CrazyGames website
await client.happytime();Playgama
When running on Playgama, the SDK auto-initializes the Playgama Bridge and routes ads through it. No additional setup required.
Billing
Billing supports web (Stripe) and native (In-App Purchases) — platform is detected automatically.
const client = new HyveClient({
billing: {
stripePublishableKey: "pk_live_...",
},
});
if (client.isBillingAvailable()) {
client.onPurchaseComplete((result) => {
console.log("Purchase successful:", result.transactionId);
});
client.onPurchaseError((result) => {
console.error("Purchase failed:", result.error?.message);
});
const products = await client.getBillingProducts();
await client.purchaseProduct("price_1234");
}For web, add a container element for the Stripe checkout UI:
<div id="stripe-checkout-element"></div>| Platform | Payment Method | Detection |
|----------|---------------|-----------|
| Web | Stripe Embedded Checkout | Default |
| Native iOS/Android | In-App Purchases | ReactNativeWebView in window |
Native Bridge
Type-safe bidirectional communication between your web game and a React Native WebView host.
import { NativeBridge } from "@hyve-sdk/js";
if (NativeBridge.isNativeContext()) {
NativeBridge.initialize();
// Listen for IAP availability
NativeBridge.on("IAP_AVAILABILITY_RESULT", (payload) => {
if (payload.available) {
console.log("IAP available on:", payload.platform);
}
});
NativeBridge.checkIAPAvailability();
// Request push notification permission
NativeBridge.on("PUSH_PERMISSION_GRANTED", (payload) => {
console.log("Token:", payload?.token);
});
NativeBridge.requestNotificationPermission();
// Send/receive custom messages
NativeBridge.send("GAME_EVENT", { action: "level_complete", level: 3 });
NativeBridge.on("CUSTOM_RESPONSE", (payload) => {
console.log("Received:", payload);
});
}NativeBridge API
| Method | Description |
|--------|-------------|
| isNativeContext() | Check if running in React Native WebView |
| initialize() | Start the message listener |
| send(type, payload?) | Send a message to the native app |
| on(type, handler) | Register a message handler |
| off(type) | Remove a message handler |
| clearHandlers() | Remove all handlers |
| checkIAPAvailability() | Request IAP availability from native |
| requestNotificationPermission() | Request push notification permission |
Logger
import { logger } from "@hyve-sdk/js";
logger.debug("Debug info", { data: "value" });
logger.info("Informational message");
logger.warn("Warning message");
logger.error("Error message", error);
// Namespaced child logger
const gameLogger = logger.child("Game");
gameLogger.info("Game started");
// Output: [Hyve SDK] [Game] [INFO] [timestamp] Game startedOverride log level in the browser:
localStorage.setItem("HYVE_SDK_LOG_LEVEL", "error,warn");API Reference
HyveClient Config
new HyveClient(config?: {
isDev?: boolean; // Override env detection (local testing only)
apiBaseUrl?: string; // Override API base URL
storageMode?: "cloud" | "local";
ads?: AdConfig;
billing?: BillingConfig;
})Authentication
| Method | Returns | Description |
|--------|---------|-------------|
| getUserId() | string \| null | Authenticated user ID |
| getGameId() | string \| null | Game ID from URL or JWT |
| getSessionId() | string | Unique session ID |
| getJwtToken() | string \| null | Raw JWT string |
| isUserAuthenticated() | boolean | Whether a user ID was extracted |
| hasJwtToken() | boolean | Whether a JWT is present |
| logout() | void | Clear auth state |
| reset() | void | Clear auth and generate new session ID |
API
| Method | Returns | Description |
|--------|---------|-------------|
| callApi<T>(endpoint, options?) | Promise<T> | Authenticated fetch to the Hyve API |
| getInventory() | Promise<Inventory> | Get user inventory |
| getInventoryItem(itemId) | Promise<InventoryItem> | Get a specific inventory item |
Telemetry
| Method | Returns | Description |
|--------|---------|-------------|
| sendTelemetry(location, category, action, subCategory?, subAction?, details?) | Promise<boolean> | Send an analytics event |
| updateTelemetryConfig(config) | void | Update telemetry settings at runtime |
Storage
| Method | Returns | Description |
|--------|---------|-------------|
| saveGameData(key, value, storage?) | Promise<SaveGameDataResponse> | Save a single value |
| batchSaveGameData(items, storage?) | Promise<SaveGameDataResponse> | Save multiple values |
| getGameData(key, storage?) | Promise<GameDataItem \| null> | Get a single value |
| getMultipleGameData(keys, storage?) | Promise<GameDataItem[]> | Get multiple values |
| deleteGameData(key, storage?) | Promise<boolean> | Delete a single value |
| deleteMultipleGameData(keys, storage?) | Promise<number> | Delete multiple values |
| configureStorage(mode) | void | Set default storage mode |
| getStorageMode() | "cloud" \| "local" | Get current storage mode |
Ads
| Method | Returns | Description |
|--------|---------|-------------|
| configureAds(config) | void | Configure the ads service |
| showAd(type) | Promise<AdResult> | Show an ad |
| areAdsReady() | boolean | Check if ads have initialized |
| gameplayStart() | Promise<void> | Notify gameplay started (CrazyGames) |
| gameplayStop() | Promise<void> | Notify gameplay stopped (CrazyGames) |
| happytime() | Promise<void> | Trigger celebration effect (CrazyGames) |
Billing
| Method | Returns | Description |
|--------|---------|-------------|
| getBillingPlatform() | BillingPlatform | "web" | "native" | "unknown" |
| isBillingAvailable() | boolean | Check if billing is ready |
| getBillingProducts() | Promise<BillingProduct[]> | Fetch available products |
| purchaseProduct(productId, options?) | Promise<PurchaseResult> | Initiate a purchase |
| onPurchaseComplete(callback) | void | Register purchase success handler |
| onPurchaseError(callback) | void | Register purchase error handler |
| unmountBillingCheckout() | void | Clean up Stripe checkout UI |
Build Output
| Format | File | Use |
|--------|------|-----|
| CJS | dist/index.js | Node.js / bundler |
| ESM | dist/index.mjs | Bundler (tree-shakeable) |
| CJS (React) | dist/react.js | React integration |
| ESM (React) | dist/react.mjs | React integration (tree-shakeable) |
Development
pnpm run check-types # Type check
pnpm run lint # Lint
pnpm run build # BuildLicense
MIT
